summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--example/scripts/global_events.lua8
-rw-r--r--scripts/lua/libmana.lua37
-rw-r--r--src/game-server/character.cpp6
-rw-r--r--src/game-server/postman.h7
-rw-r--r--src/game-server/quest.cpp2
-rw-r--r--src/game-server/quest.h5
-rw-r--r--src/scripting/lua.cpp32
-rw-r--r--src/scripting/luascript.cpp81
-rw-r--r--src/scripting/luascript.h22
-rw-r--r--src/scripting/script.cpp2
-rw-r--r--src/scripting/script.h17
11 files changed, 139 insertions, 80 deletions
diff --git a/example/scripts/global_events.lua b/example/scripts/global_events.lua
index c320d163..42a25f00 100644
--- a/example/scripts/global_events.lua
+++ b/example/scripts/global_events.lua
@@ -37,7 +37,7 @@ end)
-- This function is called after chr_death_accept. The difference is that
-- it is called in the context of the map the character is spawned on after
-- the respawn logic has happened.
-function on_chr_respawn(ch)
+local function on_chr_respawn(ch)
-- calls the local_respawn_function of the map the character respawned
-- on when the script of the map has one
if local_respawn_function ~= nil then
@@ -49,7 +49,7 @@ end
-- This function is called when a new character enters the world for the
-- first time. This can, for example, be used to give starting equipment
-- to the character and/or initialize a tutorial quest.
-function on_chr_birth(ch)
+local function on_chr_birth(ch)
-- this message is shown on first login.
mana.chat_message(0, ch, "And so your adventure begins...")
end
@@ -57,14 +57,14 @@ end
-- This function is called when a character logs into the game. This can,
-- for example, be utilized for a message-of-the-day or for various
-- handlings of offline processing mechanics.
-function on_chr_login(ch)
+local function on_chr_login(ch)
mana.chat_message(0, ch, "Welcome to Manasource")
end
-- This function is called when a character is disconnected. This could
-- be useful for various handling of offline processing mechanics.
-function on_chr_logout(ch)
+local function on_chr_logout(ch)
-- notifies nearby players of logout
local around = mana.get_beings_in_circle(posX(ch), posY(ch), 1000)
local msg = mana.being_get_name(ch).." left the game."
diff --git a/scripts/lua/libmana.lua b/scripts/lua/libmana.lua
index 8b13911f..75ad17ab 100644
--- a/scripts/lua/libmana.lua
+++ b/scripts/lua/libmana.lua
@@ -239,10 +239,11 @@ function npc_post(npc, ch, sender, letter)
end
end
--- Called by the game whenever the value of a quest variable is known.
--- Checks that the NPC expects it, and processes the respective coroutine.
+-- Registered as the function to call whenever a value of a quest variable is
+-- retrieved. Checks that the NPC expects it, and processes the respective
+-- coroutine.
-- Note: the check for NPC correctness is missing, but it should never matter.
-function quest_reply(ch, name, value)
+local function npc_quest_reply(ch, name, value)
local w = states[ch]
if w then
local w3 = w[3]
@@ -256,7 +257,9 @@ function quest_reply(ch, name, value)
states[ch] = nil
end
-function post_reply(ch, sender, letter)
+-- Registered as the function to call whenever the server has recovered a
+-- post for a user.
+local function npc_post_reply(ch, sender, letter)
local w = states[ch]
if w then
local w3 = w[3]
@@ -417,8 +420,8 @@ function on_remove(being, funct)
mana.being_register(being)
end
--- called by the engine when a registred being dies.
-function death_notification(being)
+-- Registered as callback for when a registered being dies.
+local function death_notification(being)
if type(ondeath_functs[being]) == "table" then
for i,funct in pairs(ondeath_functs[being]) do
funct()
@@ -427,8 +430,8 @@ function death_notification(being)
end
end
--- called by the engine when a registred being is removed.
-function remove_notification(being)
+-- Registered as callback for when a registered being is removed.
+local function remove_notification(being)
if type(onremove_functs[being]) == "table" then
for i,funct in pairs(onremove_functs[being]) do
funct()
@@ -451,17 +454,9 @@ mana.chr_money = function(ch)
return mana.being_get_base_attribute(ch, ATTR_GP)
end
+-- Register callbacks
+mana.on_npc_quest_reply(npc_quest_reply)
+mana.on_npc_post_reply(npc_post_reply)
-
-function cast(ch, arg)
- if arg == 1 then
- mana.being_say(ch, "Kaaame...Haaame... HAAAAAA!")
- end
- if arg == 2 then
- mana.being_say(ch, "HAA-DOKEN!")
- end
- if arg == 3 then
- mana.being_say(ch, "Sonic BOOM")
- end
-
-end
+mana.on_being_death(death_notification)
+mana.on_being_remove(remove_notification)
diff --git a/src/game-server/character.cpp b/src/game-server/character.cpp
index b5051764..950c6496 100644
--- a/src/game-server/character.cpp
+++ b/src/game-server/character.cpp
@@ -52,12 +52,12 @@ const float Character::EXPCURVE_FACTOR = 10.0f;
const float Character::LEVEL_SKILL_PRECEDENCE_FACTOR = 0.75f;
const float Character::EXP_LEVEL_FLEXIBILITY = 1.0f;
-Script::Ref Character::mDeathCallback = Script::NoRef;
-Script::Ref Character::mDeathAcceptedCallback = Script::NoRef;
+Script::Ref Character::mDeathCallback;
+Script::Ref Character::mDeathAcceptedCallback;
static bool executeCallback(Script::Ref function, Character *character)
{
- if (function == Script::NoRef)
+ if (!function.isValid())
return false;
Script *script = ScriptManager::currentState();
diff --git a/src/game-server/postman.h b/src/game-server/postman.h
index 82b7a5a7..5669ebef 100644
--- a/src/game-server/postman.h
+++ b/src/game-server/postman.h
@@ -25,12 +25,13 @@
#include <string>
class Character;
+class Script;
struct PostCallback
{
void (*handler)(Character *, const std::string &sender,
- const std::string &letter, void *data);
- void *data;
+ const std::string &letter, Script *script);
+ Script *script;
};
class PostMan
@@ -64,7 +65,7 @@ public:
std::map<Character*, PostCallback>::iterator itr = mCallbacks.find(player);
if (itr != mCallbacks.end())
{
- itr->second.handler(player, sender, letter, itr->second.data);
+ itr->second.handler(player, sender, letter, itr->second.script);
}
}
diff --git a/src/game-server/quest.cpp b/src/game-server/quest.cpp
index e4607c6a..974fc4ce 100644
--- a/src/game-server/quest.cpp
+++ b/src/game-server/quest.cpp
@@ -152,7 +152,7 @@ void recoveredQuestVar(int id, const std::string &name,
for (QuestCallbacks::const_iterator k = j->second.begin(),
k_end = j->second.end(); k != k_end; ++k)
{
- k->handler(ch, name, value, k->data);
+ k->handler(ch, name, value, k->script);
}
variables.erase(j);
diff --git a/src/game-server/quest.h b/src/game-server/quest.h
index 56fa5c2a..86d2be46 100644
--- a/src/game-server/quest.h
+++ b/src/game-server/quest.h
@@ -24,12 +24,13 @@
#include <string>
class Character;
+class Script;
struct QuestCallback
{
void (*handler)(Character *, const std::string &name,
- const std::string &value, void *data);
- void *data;
+ const std::string &value, Script *script);
+ Script *script;
};
/**
diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp
index 7a94ce24..33bd9eb9 100644
--- a/src/scripting/lua.cpp
+++ b/src/scripting/lua.cpp
@@ -97,6 +97,34 @@ static int on_character_death_accept(lua_State *s)
return 0;
}
+static int on_npc_quest_reply(lua_State *s)
+{
+ luaL_checktype(s, 1, LUA_TFUNCTION);
+ LuaScript::setQuestReplyCallback(getScript(s));
+ return 0;
+}
+
+static int on_npc_post_reply(lua_State *s)
+{
+ luaL_checktype(s, 1, LUA_TFUNCTION);
+ LuaScript::setPostReplyCallback(getScript(s));
+ return 0;
+}
+
+static int on_being_death(lua_State *s)
+{
+ luaL_checktype(s, 1, LUA_TFUNCTION);
+ LuaScript::setDeathNotificationCallback(getScript(s));
+ return 0;
+}
+
+static int on_being_remove(lua_State *s)
+{
+ luaL_checktype(s, 1, LUA_TFUNCTION);
+ LuaScript::setRemoveNotificationCallback(getScript(s));
+ return 0;
+}
+
/**
* mana.npc_message(NPC*, Character*, string): void
* Callback for sending a NPC_MESSAGE.
@@ -2590,6 +2618,10 @@ LuaScript::LuaScript():
static luaL_Reg const callbacks[] = {
{ "on_character_death", &on_character_death },
{ "on_character_death_accept", &on_character_death_accept },
+ { "on_npc_quest_reply", &on_npc_quest_reply },
+ { "on_npc_post_reply", &on_npc_post_reply },
+ { "on_being_death", &on_being_death },
+ { "on_being_remove", &on_being_remove },
{ "npc_create", &npc_create },
{ "npc_message", &npc_message },
{ "npc_choice", &npc_choice },
diff --git a/src/scripting/luascript.cpp b/src/scripting/luascript.cpp
index 605302e6..27361579 100644
--- a/src/scripting/luascript.cpp
+++ b/src/scripting/luascript.cpp
@@ -24,12 +24,17 @@
#include "scripting/luautil.h"
-#include "game-server/being.h"
+#include "game-server/character.h"
#include "utils/logger.h"
#include <cassert>
#include <cstring>
+Script::Ref LuaScript::mQuestReplyCallback;
+Script::Ref LuaScript::mPostReplyCallback;
+Script::Ref LuaScript::mDeathNotificationCallback;
+Script::Ref LuaScript::mRemoveNotificationCallback;
+
LuaScript::~LuaScript()
{
lua_close(mState);
@@ -38,7 +43,8 @@ LuaScript::~LuaScript()
void LuaScript::prepare(Ref function)
{
assert(nbArgs == -1);
- lua_rawgeti(mState, LUA_REGISTRYINDEX, function);
+ assert(function.isValid());
+ lua_rawgeti(mState, LUA_REGISTRYINDEX, function.value);
assert(lua_isfunction(mState, -1));
nbArgs = 0;
mCurFunction = "<callback>"; // We don't know the function name
@@ -122,10 +128,10 @@ void LuaScript::assignCallback(Script::Ref &function)
assert(lua_isfunction(mState, -1));
// If there is already a callback set, replace it
- if (function != NoRef)
- luaL_unref(mState, LUA_REGISTRYINDEX, function);
+ if (function.isValid())
+ luaL_unref(mState, LUA_REGISTRYINDEX, function.value);
- function = luaL_ref(mState, LUA_REGISTRYINDEX);
+ function.value = luaL_ref(mState, LUA_REGISTRYINDEX);
}
void LuaScript::load(const char *prog, const char *name)
@@ -155,20 +161,26 @@ void LuaScript::load(const char *prog, const char *name)
void LuaScript::processDeathEvent(Being *being)
{
- prepare("death_notification");
- 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();
+ if (mDeathNotificationCallback.isValid())
+ {
+ prepare(mDeathNotificationCallback);
+ 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();
+ }
}
void LuaScript::processRemoveEvent(Thing *being)
{
- prepare("remove_notification");
- 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();
+ if (mRemoveNotificationCallback.isValid())
+ {
+ prepare(mRemoveNotificationCallback);
+ 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(getScriptListener());
}
@@ -177,31 +189,30 @@ void LuaScript::processRemoveEvent(Thing *being)
* Called when the server has recovered the value of a quest variable.
*/
void LuaScript::getQuestCallback(Character *q, const std::string &name,
- const std::string &value, void *data)
+ const std::string &value, Script *script)
{
- LuaScript *s = static_cast< LuaScript * >(data);
- assert(s->nbArgs == -1);
- lua_getglobal(s->mState, "quest_reply");
- lua_pushlightuserdata(s->mState, q);
- lua_pushstring(s->mState, name.c_str());
- lua_pushstring(s->mState, value.c_str());
- s->nbArgs = 3;
- s->execute();
+ if (mQuestReplyCallback.isValid())
+ {
+ script->prepare(mQuestReplyCallback);
+ script->push(q);
+ script->push(name);
+ script->push(value);
+ script->execute();
+ }
}
/**
- * Called when the server has recovered the post for a user
+ * Called when the server has recovered the post for a user.
*/
void LuaScript::getPostCallback(Character *q, const std::string &sender,
- const std::string &letter, void *data)
+ const std::string &letter, Script *script)
{
- // get the script
- LuaScript *s = static_cast<LuaScript*>(data);
- assert(s->nbArgs == -1);
- lua_getglobal(s->mState, "post_reply");
- lua_pushlightuserdata(s->mState, q);
- lua_pushstring(s->mState, sender.c_str());
- lua_pushstring(s->mState, letter.c_str());
- s->nbArgs = 3;
- s->execute();
+ if (mPostReplyCallback.isValid())
+ {
+ script->prepare(mPostReplyCallback);
+ script->push(q);
+ script->push(sender);
+ script->push(letter);
+ script->execute();
+ }
}
diff --git a/src/scripting/luascript.h b/src/scripting/luascript.h
index 6f2bceee..ecd249ae 100644
--- a/src/scripting/luascript.h
+++ b/src/scripting/luascript.h
@@ -61,19 +61,37 @@ class LuaScript : public Script
void assignCallback(Ref &function);
static void getQuestCallback(Character *, const std::string &,
- const std::string &, void *);
+ const std::string &, Script *);
static void getPostCallback(Character *, const std::string &,
- const std::string &, void *);
+ const std::string &, Script *);
void processDeathEvent(Being *thing);
void processRemoveEvent(Thing *thing);
+
+ static void setQuestReplyCallback(Script *script)
+ { script->assignCallback(mQuestReplyCallback); }
+
+ static void setPostReplyCallback(Script *script)
+ { script->assignCallback(mPostReplyCallback); }
+
+ static void setDeathNotificationCallback(Script *script)
+ { script->assignCallback(mDeathNotificationCallback); }
+
+ static void setRemoveNotificationCallback(Script *script)
+ { script->assignCallback(mRemoveNotificationCallback); }
+
private:
lua_State *mState;
int nbArgs;
std::string mCurFunction;
+
+ static Ref mQuestReplyCallback;
+ static Ref mPostReplyCallback;
+ static Ref mDeathNotificationCallback;
+ static Ref mRemoveNotificationCallback;
};
static char const registryKey = 0;
diff --git a/src/scripting/script.cpp b/src/scripting/script.cpp
index 66720842..db44bd57 100644
--- a/src/scripting/script.cpp
+++ b/src/scripting/script.cpp
@@ -34,8 +34,6 @@ typedef std::map< std::string, Script::Factory > Engines;
static Engines *engines = NULL;
-Script::Ref Script::NoRef = -1;
-
Script::Script():
mMap(NULL),
mEventListener(&scriptEventDispatch)
diff --git a/src/scripting/script.h b/src/scripting/script.h
index b475a0f0..9cc50a1c 100644
--- a/src/scripting/script.h
+++ b/src/scripting/script.h
@@ -52,13 +52,16 @@ class Script
static Script *create(const std::string &engine);
/**
- * A reference to a script object. It's just an integer, but the
- * typedef makes the purpose of the variable clear.
- *
- * Variables of this type should be initialized to Script::NoRef.
- */
- typedef int Ref;
- static Ref NoRef;
+ * A reference to a script object. It wraps an integer value, but adds
+ * custom initialization and a definition of valid. It also makes the
+ * purpose clear.
+ */
+ class Ref {
+ public:
+ Ref() : value(-1) {}
+ bool isValid() const { return value != -1; }
+ int value;
+ };
Script();