summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/test.lua9
-rw-r--r--src/game-server/testing.cpp21
-rw-r--r--src/scripting/lua.cpp53
-rw-r--r--src/scripting/script.hpp18
4 files changed, 75 insertions, 26 deletions
diff --git a/data/test.lua b/data/test.lua
index 2c756165..109e3dc3 100644
--- a/data/test.lua
+++ b/data/test.lua
@@ -1,24 +1,23 @@
+function initialize()
+ tmw.obj_create_npc(110, 50 * 32 + 16, 19 * 32 + 16)
+end
+
function npc_start(npc, ch)
tmw.msg_npc_message(npc, ch, "What do you want?")
- return 0
end
function npc_next(npc, ch)
tmw.msg_npc_choice(npc, ch, "Guns! Lots of guns!:Nothing")
- return 0
end
function npc_choose(npc, ch, v)
if v == 1 then
tmw.msg_npc_message(npc, ch, "Sorry, this is a heroic-fantasy game, I do not have any gun.")
end
- return 0
end
function npc_update(npc)
- return 0
end
function update()
- return 0
end
diff --git a/src/game-server/testing.cpp b/src/game-server/testing.cpp
index 19156203..d08f2ee6 100644
--- a/src/game-server/testing.cpp
+++ b/src/game-server/testing.cpp
@@ -10,18 +10,10 @@
#include "game-server/itemmanager.hpp"
#include "game-server/mapcomposite.hpp"
#include "game-server/mapmanager.hpp"
-#include "game-server/npc.hpp"
#include "game-server/state.hpp"
#include "net/messageout.hpp"
#include "scripting/script.hpp"
-// For testing purpose only, the NPC class is not meant to be inherited!!
-struct DummyNPC: NPC
-{
- DummyNPC(): NPC(110, Script::create("lua", "test.lua"))
- {}
-};
-
static void dropItem(MapComposite *map, int x, int y, int type)
{
ItemClass *ic = ItemManager::getItem(type);
@@ -43,11 +35,14 @@ void testingMap(MapComposite *map)
dropItem(map, 58 * 32 + 16, 20 * 32 + 16, 508);
dropItem(map, 58 * 32 + 16, 21 * 32 + 16, 524);
- // Add an NPC
- NPC *q = new DummyNPC;
- q->setMap(map);
- q->setPosition(Point(50 * 32 + 16, 19 * 32 + 16));
- GameState::insert(q);
+ // Associate a script
+ Script *s = Script::create("lua", "test.lua");
+ if (s)
+ {
+ s->setMap(map);
+ s->prepare("initialize");
+ s->execute();
+ }
} break;
}
}
diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp
index f9575b68..9cac37d0 100644
--- a/src/scripting/lua.cpp
+++ b/src/scripting/lua.cpp
@@ -33,6 +33,7 @@ extern "C" {
#include "game-server/character.hpp"
#include "game-server/gamehandler.hpp"
#include "game-server/npc.hpp"
+#include "game-server/state.hpp"
#include "net/messageout.hpp"
#include "scripting/script.hpp"
#include "utils/logger.h"
@@ -62,6 +63,8 @@ class LuaScript: public Script
int nbArgs;
};
+static char const registryKey = 0;
+
/* Functions below are unsafe, as they assume the script has passed pointers
to objects which have not yet been destroyed. If the script never keeps
pointers around, there will be no problem. In order to be safe, the engine
@@ -128,6 +131,34 @@ static int LuaMsg_NpcChoice(lua_State *s)
return 0;
}
+/**
+ * Callback for creating a NPC on the current map with the current script
+ * (1: int) (2: int) (3: int).
+ */
+static int LuaObj_CreateNpc(lua_State *s)
+{
+ if (!lua_isnumber(s, 1) || !lua_isnumber(s, 2) || !lua_isnumber(s, 3))
+ {
+ LOG_WARN("LuaObj_CreateNpc called with incorrect parameters.");
+ return 0;
+ }
+ lua_pushlightuserdata(s, (void *)&registryKey);
+ lua_gettable(s, LUA_REGISTRYINDEX);
+ Script *t = static_cast<Script *>(lua_touserdata(s, -1));
+ NPC *q = new NPC(lua_tointeger(s, 1), t);
+ MapComposite *m = t->getMap();
+ if (!m)
+ {
+ LOG_WARN("LuaObj_CreateNpc called outside a map.");
+ return 0;
+ }
+ q->setMap(m);
+ q->setPosition(Point(lua_tointeger(s, 2), lua_tointeger(s, 3)));
+ GameState::insert(q);
+ lua_pushlightuserdata(s, q);
+ return 1;
+}
+
LuaScript::LuaScript(lua_State *s):
mState(s),
nbArgs(-1)
@@ -138,18 +169,26 @@ LuaScript::LuaScript(lua_State *s):
if (res)
{
LOG_ERROR("Failure while initializing Lua script: "
- << lua_tostring(mState, 1));
- lua_pop(mState, 1);
+ << lua_tostring(mState, -1));
+ lua_settop(s, 0);
return;
}
+ // Put some callback functions in the scripting environment.
static luaL_reg const callbacks[] = {
- { "msg_npc_message", &LuaMsg_NpcMessage },
- { "msg_npc_choice", &LuaMsg_NpcChoice },
+ { "msg_npc_message", &LuaMsg_NpcMessage },
+ { "msg_npc_choice", &LuaMsg_NpcChoice },
+ { "obj_create_npc", &LuaObj_CreateNpc },
{ NULL, NULL }
};
luaL_register(mState, "tmw", callbacks);
- lua_pop(mState, 1);
+
+ // Make script object available to callback functions.
+ lua_pushlightuserdata(mState, (void *)&registryKey);
+ lua_pushlightuserdata(mState, this);
+ lua_settable(mState, LUA_REGISTRYINDEX);
+
+ lua_settop(s, 0);
}
LuaScript::~LuaScript()
@@ -183,7 +222,7 @@ int LuaScript::execute()
assert(nbArgs >= 0);
int res = lua_pcall(mState, nbArgs, 1, 0);
nbArgs = -1;
- if (res || !lua_isnumber(mState, 1))
+ if (res || !(lua_isnil(mState, 1) || lua_isnumber(mState, 1)))
{
char const *s = lua_tostring(mState, 1);
LOG_WARN("Failure while calling Lua function: error=" << res
@@ -228,5 +267,3 @@ struct LuaRegister
};
static LuaRegister dummy;
-
-
diff --git a/src/scripting/script.hpp b/src/scripting/script.hpp
index 5862e50c..8ab89c25 100644
--- a/src/scripting/script.hpp
+++ b/src/scripting/script.hpp
@@ -26,6 +26,7 @@
#include <string>
+class MapComposite;
class Thing;
/**
@@ -47,6 +48,8 @@ class Script
*/
static Script *create(std::string const &engine, std::string const &file);
+ Script(): mMap(NULL) {}
+
virtual ~Script() {}
/**
@@ -79,6 +82,21 @@ class Script
* @return the value returned by the script.
*/
virtual int execute() = 0;
+
+ /**
+ * Sets associated map.
+ */
+ void setMap(MapComposite *m)
+ { mMap = m; }
+
+ /**
+ * Gets associated map.
+ */
+ MapComposite *getMap() const
+ { return mMap; }
+
+ private:
+ MapComposite *mMap;
};
#endif