diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | data/test.lua | 26 | ||||
-rw-r--r-- | src/game-server/mapreader.cpp | 3 | ||||
-rw-r--r-- | src/game-server/state.cpp | 24 | ||||
-rw-r--r-- | src/game-server/state.hpp | 9 | ||||
-rw-r--r-- | src/game-server/trigger.cpp | 11 | ||||
-rw-r--r-- | src/game-server/trigger.hpp | 6 | ||||
-rw-r--r-- | src/scripting/lua.cpp | 65 |
8 files changed, 138 insertions, 20 deletions
@@ -1,3 +1,17 @@ +2008-05-08 Philipp Sehmisch <tmw@crushnet.org> + + * src/game-server/trigger.cpp, src/game-server/trigger.hpp, + src/game-server/mapreader.cpp, src/game-server/scripting.cpp: Implemented + possibility to have trigger areas which only trigger when a being enters + them and not every game tick the being is inside. + * src/scripting/lua.cpp, src/game-server/state.cpp, + src/game-server/state.hpp: Implemented script bindings for making beings + say something, sending private chat messages from scripts to clients. + * data/test.lua: The trigger areas now make every being which steps on them + say something and send a private chat message to the being which steps on + them. Made the guard at the gate say something in random intervals to + demonstrate tmw.being_say with NPCs. + 2008-05-06 Philipp Sehmisch <tmw@crushnet.org> * src/game-server/trigger.cpp, src/game-server/trigger.h, diff --git a/data/test.lua b/data/test.lua index 0edc15e3..06d6136d 100644 --- a/data/test.lua +++ b/data/test.lua @@ -21,21 +21,22 @@ atinit(function() create_npc(200, 50 * 32 + 16, 19 * 32 + 16, npc1_talk, npclib.walkaround_small) create_npc(201, 51 * 32 + 16, 25 * 32 + 16, npc4_talk, npclib.walkaround_wide) create_npc(126, 45 * 32 + 16, 25 * 32 + 16, npc5_talk, npclib.walkaround_map) - create_npc(122, 58 * 32 + 16, 15 * 32 + 16, npc6_talk, nil) + create_npc(122, 58 * 32 + 16, 15 * 32 + 16, npc6_talk, npc6_update) - create_npc(200, 63 * 32 + 16, 31 * 32 + 16, nil, nil) - tmw.trigger_create(56 * 32, 30 * 32, 64, 64, "patrol_waypoint", 1) - tmw.trigger_create(63 * 32, 30 * 32, 64, 64, "patrol_waypoint", 2) + tmw.trigger_create(56 * 32, 32 * 32, 64, 64, "patrol_waypoint", 1, true) + tmw.trigger_create(63 * 32, 32 * 32, 64, 64, "patrol_waypoint", 2, true) end) function patrol_waypoint(obj, id) if (id == 1) then - tmw.being_walk(obj, 64 * 32, 31 * 32, 400) + tmw.chatmessage(obj, "you've reached patrol point 1") + tmw.being_say(obj, "I have reached patrol point 1") end if (id == 2) then - tmw.being_walk(obj, 57 * 32, 31 * 32, 400) + tmw.chatmessage(obj, "you've reached patrol point 2") + tmw.being_say(obj, "I have reached patrol point 2") end end @@ -121,3 +122,16 @@ function npc6_talk(npc, ch) guard_position = 1 end end + +function npc6_update(npc) + local r = math.random(0, 100) + if (r == 0) then + tmw.being_say(npc, "*humhumhum*") + end + if (r == 1) then + tmw.being_say(npc, "guarding the city gate is so much fun *sigh*") + end + if (r == 2) then + tmw.being_say(npc, "can't someone order me to walk to the other side of the gate?") + end +end diff --git a/src/game-server/mapreader.cpp b/src/game-server/mapreader.cpp index b5210f23..39d209d6 100644 --- a/src/game-server/mapreader.cpp +++ b/src/game-server/mapreader.cpp @@ -231,7 +231,8 @@ static Map *readMap(xmlNodePtr node, std::string const &path, MapComposite *comp { things.push_back(new TriggerArea( composite, rect, - new WarpAction(destMap, destX, destY))); + new WarpAction(destMap, destX, destY), + false)); } } else diff --git a/src/game-server/state.cpp b/src/game-server/state.cpp index 2d6e4a04..03c6e3c1 100644 --- a/src/game-server/state.cpp +++ b/src/game-server/state.cpp @@ -612,18 +612,30 @@ void GameState::enqueueWarp(Character *ptr, MapComposite *m, int x, int y) void GameState::sayAround(Object *obj, std::string const &text) { - MessageOut msg(GPMSG_SAY); - msg.writeShort(!obj->canMove() ? 65535 : - static_cast< MovingObject * >(obj)->getPublicID()); - msg.writeString(text); - Point speakerPosition = obj->getPosition(); for (CharacterIterator i(obj->getMap()->getAroundObjectIterator(obj, AROUND_AREA)); i; ++i) { if (speakerPosition.inRangeOf((*i)->getPosition(), AROUND_AREA)) { - gameHandler->sendTo(*i, msg); + sayTo(*i, obj, text); } } } + +void GameState::sayTo(Object *destination, Object *source, std::string const &text) +{ + if (destination->getType() != OBJECT_CHARACTER) return; //only characters will read it anyway + + MessageOut msg(GPMSG_SAY); + if (source == NULL) { + msg.writeShort(0); + } else if (!source->canMove()) { + msg.writeShort(65535); + } else { + msg.writeShort(static_cast< MovingObject * >(source)->getPublicID()); + } + msg.writeString(text); + + gameHandler->sendTo(static_cast< Character * >(destination), msg); +} diff --git a/src/game-server/state.hpp b/src/game-server/state.hpp index 67f91311..68bf6b32 100644 --- a/src/game-server/state.hpp +++ b/src/game-server/state.hpp @@ -91,9 +91,16 @@ namespace GameState void enqueueWarp(Character *, MapComposite *, int x, int y); /** - * Says something around an object. + * Says something to an object + * @note passing NULL as source generates a message from "Server:" + */ + void sayTo(Object *destination, Object *source, std::string const &text); + + /** + * Says something to everything around an object. */ void sayAround(Object *, std::string const &text); + } #endif diff --git a/src/game-server/trigger.cpp b/src/game-server/trigger.cpp index 3309c754..8252fafc 100644 --- a/src/game-server/trigger.cpp +++ b/src/game-server/trigger.cpp @@ -51,11 +51,18 @@ void ScriptAction::process(Object *obj) void TriggerArea::update() { + std::set<Object*> insideNow; for (MovingObjectIterator i(getMap()->getInsideRectangleIterator(mZone)); i; ++i) { - if (mZone.contains((*i)->getPosition())) + if (mZone.contains((*i)->getPosition())) //<-- Why is this additional condition necessary? Shouldn't getInsideRectangleIterator already exclude those outside of the zone? --Crush { - mAction->process(*i); + insideNow.insert(*i); + + if (!mOnce || mInside.find(*i) == mInside.end()) + { + mAction->process(*i); + } } } + mInside.swap(insideNow); //swapping is faster than assigning } diff --git a/src/game-server/trigger.hpp b/src/game-server/trigger.hpp index 3ca52fba..30944d86 100644 --- a/src/game-server/trigger.hpp +++ b/src/game-server/trigger.hpp @@ -70,14 +70,16 @@ class TriggerArea : public Thing /** * Creates a rectangular trigger for a given map. */ - TriggerArea(MapComposite *m, Rectangle const &r, TriggerAction *ptr) - : Thing(OBJECT_OTHER, m), mZone(r), mAction(ptr) {} + TriggerArea(MapComposite *m, Rectangle const &r, TriggerAction *ptr, bool once) + : Thing(OBJECT_OTHER, m), mZone(r), mAction(ptr), mOnce(once) {} virtual void update(); private: Rectangle mZone; TriggerAction *mAction; + bool mOnce; + std::set<Object *> mInside; }; #endif diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp index 62fd64a4..a8663f75 100644 --- a/src/scripting/lua.cpp +++ b/src/scripting/lua.cpp @@ -414,6 +414,32 @@ static int LuaBeing_Walk(lua_State *s) } /** + * Makes the being say something + * tmw.being_say(source, message) + */ +static int LuaBeing_Say(lua_State *s) +{ + if (!lua_isuserdata(s, 1) || !lua_isstring(s, 2) ) + { + raiseScriptError(s, "being_say called with incorrect parameters."); + return 0; + } + + Being *being = getBeing(s, 1); + std::string message = lua_tostring(s, 2); + + if (being && message != "") + { + GameState::sayAround(being, message); + } else { + raiseScriptError(s, "being_say called with incorrect parameters."); + return 0; + } + + return 0; +} + +/** * Function for getting the x-coordinate of the position of a being */ static int LuaPosX(lua_State *s) @@ -561,7 +587,8 @@ static int LuaTrigger_Create(lua_State *s) !lua_isnumber(s, 3) || !lua_isnumber(s, 4) || !lua_isstring(s, 5) || - !lua_isnumber(s, 6)) + !lua_isnumber(s, 6) || + !lua_isboolean(s, 7)) { raiseScriptError(s, "trigger_create called with incorrect parameters."); return 0; @@ -576,6 +603,7 @@ static int LuaTrigger_Create(lua_State *s) int height = lua_tointeger(s, 4); std::string function = lua_tostring(s, 5); int id = lua_tointeger(s, 6); + bool once = lua_toboolean(s, 7); LOG_INFO("Created script trigger at "<<x<<":"<<y<<" ("<<width<<"x"<<height<<") function: "<<function<<" ("<<id<<")"); @@ -589,13 +617,44 @@ static int LuaTrigger_Create(lua_State *s) ScriptAction *action = new ScriptAction(script, function, id); Rectangle r = { x, y, width, height }; - TriggerArea *area = new TriggerArea(m, r, action); + TriggerArea *area = new TriggerArea(m, r, action, once); bool ret = GameState::insert(area); lua_pushboolean(s, ret); return 1; } +/** + * Creates a chat message in the users chatlog(s) + * global message: tmw.chatmessage (message) + * private massage: tmw.chatmessage (recipent, message) + */ +static int LuaChatmessage(lua_State *s) +{ + if (lua_gettop(s) == 2 && lua_isuserdata(s, 1) && lua_isstring(s, 2) ) + { + Being *being = getBeing(s, 1); + std::string message = lua_tostring(s, 2); + + if (being && message != "") + { + GameState::sayTo(being, NULL, message); + } + } + else if(lua_gettop(s) == 1 && lua_isstring(s, 1)) + { + // TODO: make chatserver send a global message + } + else + { + raiseScriptError(s, "being_say called with incorrect parameters."); + return 0; + } + + return 0; +} + + LuaScript::LuaScript(): nbArgs(-1) { @@ -615,9 +674,11 @@ LuaScript::LuaScript(): { "chr_set_quest", &LuaChr_SetQuest }, { "monster_create", &LuaMonster_Create }, { "being_walk", &LuaBeing_Walk }, + { "being_say", &LuaBeing_Say }, { "posX", &LuaPosX }, { "posY", &LuaPosY }, { "trigger_create", &LuaTrigger_Create }, + { "chatmessage", &LuaChatmessage }, { NULL, NULL } }; luaL_register(mState, "tmw", callbacks); |