summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Sehmisch <tmw@crushnet.org>2008-05-07 23:14:54 +0000
committerPhilipp Sehmisch <tmw@crushnet.org>2008-05-07 23:14:54 +0000
commit4c54e5c20379bbff60a25924790d19a2eb912267 (patch)
treeb7831416313259343bd5463574fd36b697d82982
parent7d559cbae9c713e15ae0c943a4d571122bf29bc6 (diff)
downloadmanaserv-4c54e5c20379bbff60a25924790d19a2eb912267.tar.gz
manaserv-4c54e5c20379bbff60a25924790d19a2eb912267.tar.bz2
manaserv-4c54e5c20379bbff60a25924790d19a2eb912267.tar.xz
manaserv-4c54e5c20379bbff60a25924790d19a2eb912267.zip
Implemented script bindings for making beings talk and sending private chat messages from scripts to clients. Implemented trigger areas which are only triggered once when a being steps into them instead of every tick.
-rw-r--r--ChangeLog14
-rw-r--r--data/test.lua26
-rw-r--r--src/game-server/mapreader.cpp3
-rw-r--r--src/game-server/state.cpp24
-rw-r--r--src/game-server/state.hpp9
-rw-r--r--src/game-server/trigger.cpp11
-rw-r--r--src/game-server/trigger.hpp6
-rw-r--r--src/scripting/lua.cpp65
8 files changed, 138 insertions, 20 deletions
diff --git a/ChangeLog b/ChangeLog
index 5474c763..b0df9770 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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);