diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | data/scripts/libtmw.lua | 19 | ||||
-rw-r--r-- | data/test.lua | 19 | ||||
-rw-r--r-- | src/scripting/lua.cpp | 41 | ||||
-rw-r--r-- | src/scripting/script.cpp | 5 | ||||
-rw-r--r-- | src/scripting/script.hpp | 23 |
6 files changed, 108 insertions, 7 deletions
@@ -1,3 +1,11 @@ +2008-07-07 Philipp Sehmisch <tmw@crushnet.org> + + * src/scripting/script.cpp, src/scripting/script.hpp, src/scripting/lua.cpp, + data/scripts/libtmw.lua: Implemented death listener for scripting engine. + * data/test.lua: Made the spider tamer a scorpion tamer (because spiders aren't + implemeted and thus make bad test subjects in this case) and used the death + listeners to make him complain when the scorpions are killed. + 2008-07-07 Roderic Morris <roderic@ccs.neu.edu> * src/chat-server/chathandler.hpp, src/chat-server/chathandler.cpp, diff --git a/data/scripts/libtmw.lua b/data/scripts/libtmw.lua index e788a59b..83e3b40b 100644 --- a/data/scripts/libtmw.lua +++ b/data/scripts/libtmw.lua @@ -322,6 +322,25 @@ function schedule_every(seconds, funct) end +-- DEATH NOTIFICATIONS +local ondeath_functs = {} + +function onDeath(being, funct) + if ondeath_functs[being] == nil then + ondeath_functs[being] = {} + end + table.insert(ondeath_functs[being], funct) + tmw.noteOnDeath(being) +end + +function deathNotification(being) + if type(ondeath_functs[being]) == "table" then + for i,funct in pairs(ondeath_functs[being]) do + funct() + end + end +end + -- Below are some convenience methods added to the engine API diff --git a/data/test.lua b/data/test.lua index cebabddb..75a903ed 100644 --- a/data/test.lua +++ b/data/test.lua @@ -20,7 +20,7 @@ require "data/scripts/npclib" atinit(function() create_npc("Test NPC", 200, 50 * TILESIZE + 16, 19 * TILESIZE + 16, npc1_talk, npclib.walkaround_small) create_npc("Teleporter", 201, 51 * TILESIZE + 16, 25 * TILESIZE + 16, npc4_talk, npclib.walkaround_wide) - create_npc("Spider Tamer", 126, 45 * TILESIZE + 16, 25 * TILESIZE + 16, npc5_talk, npclib.walkaround_map) + create_npc("Scorpion Tamer", 126, 45 * TILESIZE + 16, 25 * TILESIZE + 16, npc5_talk, nil) create_npc("Guard", 122, 58 * TILESIZE + 16, 15 * TILESIZE + 16, npc6_talk, npc6_update) create_npc("Fire Demon", 202, 58 * TILESIZE + 16, 35 * TILESIZE + 16, firedemon_talk, firedemon_update) @@ -115,15 +115,22 @@ function npc4_talk(npc, ch) end function npc5_talk(npc, ch) - do_message(npc, ch, "I am the spider tamer. Do you want me to spawn some spiders?") + do_message(npc, ch, "I am the scorpion tamer. Do you want me to spawn some scorpions?") local answer = do_choice(npc, ch, "Yes", "No"); if answer == 1 then local x = tmw.posX(npc) local y = tmw.posY(npc) - tmw.monster_create(1012, x + TILESIZE, y + TILESIZE) - tmw.monster_create(112, x - TILESIZE, y + TILESIZE) - tmw.monster_create(1012, x + TILESIZE, y - TILESIZE) - tmw.monster_create(1012, x - TILESIZE, y - TILESIZE) + m1 = tmw.monster_create(1, x + TILESIZE, y + TILESIZE) + m2 = tmw.monster_create(1, x - TILESIZE, y + TILESIZE) + m3 = tmw.monster_create(1, x + TILESIZE, y - TILESIZE) + m4 = tmw.monster_create(1, x - TILESIZE, y - TILESIZE) + + onDeath(m1, function() tmw.being_say(npc, "NOOO!") end) + onDeath(m2, function() tmw.being_say(npc, "Please stop this violence!") end) + onDeath(m3, function() tmw.being_say(npc, "Stop slaughtering my scorpions!") end) + onDeath(m4, function() tmw.being_say(npc, "Leave my scorpions alone!") end) + onDeath(m4, function() tmw.being_say(m4, "AAARGH!") end) + end end diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp index ae9ff1b2..5a9364db 100644 --- a/src/scripting/lua.cpp +++ b/src/scripting/lua.cpp @@ -79,6 +79,8 @@ class LuaScript: public Script static void getQuestCallback(Character *, std::string const &, std::string const &, void *); + void processDeathEvent(Being* thing); + private: lua_State *mState; @@ -721,6 +723,33 @@ static int LuaGetBeingsInCircle(lua_State *s) return 1; } +/** + * Makes the server call the lua function deathEvent + * with the being ID when the being dies. + * tmw.noteOnDeath (being) + */ +static int LuaNoteOnDeath(lua_State *s) +{ + if (!lua_islightuserdata(s, 1) || lua_gettop(s) != 1) + { + raiseScriptError(s, "lua_noteOnDeath called with incorrect parameters."); + return 0; + } + + lua_pushlightuserdata(s, (void *)®istryKey); + lua_gettable(s, LUA_REGISTRYINDEX); + Script *t = static_cast<Script *>(lua_touserdata(s, -1)); + Being *being = getBeing(s, 1); + if (!being) + { + raiseScriptError(s, "lua_noteOnDeath called for nonexistent being."); + return 0; + } + + being->addListener(t->getScriptDeathListener()); + return 0; +} + LuaScript::LuaScript(): nbArgs(-1) { @@ -747,6 +776,7 @@ LuaScript::LuaScript(): { "trigger_create", &LuaTrigger_Create }, { "chatmessage", &LuaChatmessage }, { "get_beings_in_circle", &LuaGetBeingsInCircle}, + { "noteOnDeath", &LuaNoteOnDeath }, { NULL, NULL } }; luaL_register(mState, "tmw", callbacks); @@ -835,6 +865,17 @@ void LuaScript::load(char const *prog) } } +void LuaScript::processDeathEvent(Being *being) +{ + prepare("deathNotification"); + push(being); + //TODO: get and push a list of creatures who contributed to killing the + // being. This might be very interesting for scripting quests. + execute(); + + being->removeListener(getScriptDeathListener()); +} + static Script *LuaFactory() { return new LuaScript(); diff --git a/src/scripting/script.cpp b/src/scripting/script.cpp index 408bf28a..7c6318af 100644 --- a/src/scripting/script.cpp +++ b/src/scripting/script.cpp @@ -33,6 +33,11 @@ typedef std::map< std::string, Script::Factory > Engines; static Engines *engines = NULL; +Script::Script(): + mMap(NULL), + mEventListener(&scriptDeathEventDispatch) +{} + void Script::registerEngine(std::string const &name, Factory f) { if (!engines) diff --git a/src/scripting/script.hpp b/src/scripting/script.hpp index 6a101edf..d9a8aca7 100644 --- a/src/scripting/script.hpp +++ b/src/scripting/script.hpp @@ -26,6 +26,8 @@ #include <string> +#include "game-server/eventlistener.hpp" + class MapComposite; class Thing; @@ -51,7 +53,7 @@ class Script /** * Constructor. */ - Script(): mMap(NULL) {} + Script(); /** * Destructor. @@ -124,8 +126,27 @@ class Script MapComposite *getMap() const { return mMap; } + EventListener *getScriptDeathListener() + { return &mEventListener; } + + virtual void processDeathEvent(Being* thing) = 0; + private: MapComposite *mMap; + EventListener mEventListener; /**< Tracking of being deaths. */ + + friend struct ScriptDeathEventDispatch; }; +struct ScriptDeathEventDispatch: EventDispatch +{ + ScriptDeathEventDispatch() + { + typedef EventListenerFactory< Script, &Script::mEventListener > Factory; + died = &Factory::create< Being, &Script::processDeathEvent >::function; + } +}; + +static ScriptDeathEventDispatch scriptDeathEventDispatch; + #endif |