summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--example/items.xml2
-rw-r--r--example/monsters.xml2
-rw-r--r--example/scripts/items/candy.lua8
-rw-r--r--example/scripts/main.lua3
-rw-r--r--example/scripts/monster/testmonster.lua8
-rw-r--r--example/scripts/status/jump.lua4
-rw-r--r--example/scripts/status/plague.lua4
-rw-r--r--src/game-server/item.cpp20
-rw-r--r--src/game-server/item.h31
-rw-r--r--src/game-server/itemmanager.cpp51
-rw-r--r--src/game-server/monster.cpp34
-rw-r--r--src/game-server/monster.h27
-rw-r--r--src/game-server/monstermanager.cpp5
-rw-r--r--src/game-server/statuseffect.cpp17
-rw-r--r--src/game-server/statuseffect.h8
-rw-r--r--src/game-server/statusmanager.cpp31
-rw-r--r--src/game-server/statusmanager.h5
-rw-r--r--src/scripting/lua.cpp111
-rw-r--r--src/scripting/luautil.h23
-rw-r--r--src/utils/string.h5
20 files changed, 263 insertions, 136 deletions
diff --git a/example/items.xml b/example/items.xml
index 730e572..cdbc3e4 100644
--- a/example/items.xml
+++ b/example/items.xml
@@ -68,7 +68,7 @@
max-per-slot="30"
value="15">
<effect trigger="activation">
- <script src="candy.lua" function="use_candy" />
+ <scriptevent activate="use" />
<consumes />
</effect>
</item>
diff --git a/example/monsters.xml b/example/monsters.xml
index f036191..962b137 100644
--- a/example/monsters.xml
+++ b/example/monsters.xml
@@ -78,7 +78,7 @@ exp<TAG>: Tells how much experience point a monster is giving up
damage-factor="1"
range="32"
animation="attack"
- script-function="on_maggot_strike"
+ script-event="strike"
/>
<script>testmonster.lua</script> <!-- only Proof of Concept-->
</monster>
diff --git a/example/scripts/items/candy.lua b/example/scripts/items/candy.lua
index a9c59fe..f60e687 100644
--- a/example/scripts/items/candy.lua
+++ b/example/scripts/items/candy.lua
@@ -2,12 +2,14 @@
Example item script.
- Makes the player character say "*munch*munch*munch*" when using this item.
+ Makes the player character say "*munch*munch*munch*" when using a candy.
The HP regeneration effect is handled separately based on the heal value in
items.xml.
--]]
-function use_candy(user)
+local candy = mana.get_item_class("candy")
+
+candy:on("use", function(user)
mana.being_say(user, "*munch*munch*munch*")
-end
+end)
diff --git a/example/scripts/main.lua b/example/scripts/main.lua
index aeaca63..6d8207e 100644
--- a/example/scripts/main.lua
+++ b/example/scripts/main.lua
@@ -9,3 +9,6 @@
require "scripts/global_events"
require "scripts/special_actions"
require "scripts/crafting"
+
+require "scripts/items/candy"
+require "scripts/monster/testmonster"
diff --git a/example/scripts/monster/testmonster.lua b/example/scripts/monster/testmonster.lua
index 2701d24..63b2917 100644
--- a/example/scripts/monster/testmonster.lua
+++ b/example/scripts/monster/testmonster.lua
@@ -7,14 +7,14 @@
--]]
-function update_monster(mob)
+local function update(mob)
local r = math.random(0, 200);
if r == 0 then
mana.being_say(mob, "Roar! I am a boss")
end
end
-function on_maggot_strike(mob, victim, hit)
+local function strike(mob, victim, hit)
if hit > 0 then
mana.being_say(mob, "Take this! "..hit.." damage!")
mana.being_say(victim, "Oh Noez!")
@@ -23,3 +23,7 @@ function on_maggot_strike(mob, victim, hit)
mana.being_say(victim, "Whew...")
end
end
+
+local maggot = mana.get_monster_class("maggot")
+maggot:on_update(update)
+maggot:on("strike", strike)
diff --git a/example/scripts/status/jump.lua b/example/scripts/status/jump.lua
index 10ad928..166c90d 100644
--- a/example/scripts/status/jump.lua
+++ b/example/scripts/status/jump.lua
@@ -12,7 +12,7 @@
----------------------------------------------------------------------------------
-function tick_jump(target, ticknumber)
+local function tick(target, ticknumber)
if (ticknumber % 10 == 0) then
mana.being_say(target, "I have the jumping bug!")
end
@@ -51,3 +51,5 @@ function tick_jump(target, ticknumber)
mana.being_apply_status(victim, 2, 6000)
mana.being_say(victim, "Now I have the jumping bug")
end
+
+mana.get_status_effect("jumping status"):on_tick(tick)
diff --git a/example/scripts/status/plague.lua b/example/scripts/status/plague.lua
index 5f33eb8..a43b9d4 100644
--- a/example/scripts/status/plague.lua
+++ b/example/scripts/status/plague.lua
@@ -12,7 +12,7 @@
-- Software Foundation; either version 2 of the License, or any later version. --
----------------------------------------------------------------------------------
-function tick_plague(target, ticknumber)
+local function tick(target, ticknumber)
if (ticknumber % 10 == 0) then
mana.being_say(target, "I have the plague! :( = " .. ticknumber)
end
@@ -26,3 +26,5 @@ function tick_plague(target, ticknumber)
i = i + 1
end
end
+
+mana.get_status_effect("plague"):on_tick(tick)
diff --git a/src/game-server/item.cpp b/src/game-server/item.cpp
index 979a1bc..888c90a 100644
--- a/src/game-server/item.cpp
+++ b/src/game-server/item.cpp
@@ -64,13 +64,17 @@ ItemEffectScript::~ItemEffectScript()
bool ItemEffectScript::apply(Being *itemUser)
{
- if (!mActivateFunctionName.empty())
+ if (mActivateEventName.empty())
+ return false;
+
+ Script::Ref function = mItemClass->getEventCallback(mActivateEventName);
+ if (function.isValid())
{
Script *script = ScriptManager::currentState();
script->setMap(itemUser->getMap());
- script->prepare(mActivateFunctionName);
+ script->prepare(function);
script->push(itemUser);
- script->push(mItemId);
+ script->push(mItemClass->getDatabaseID());
script->execute(); // TODO return depending on script execution success.
return true;
}
@@ -79,13 +83,17 @@ bool ItemEffectScript::apply(Being *itemUser)
void ItemEffectScript::dispell(Being *itemUser)
{
- if (!mDispellFunctionName.empty())
+ if (mDispellEventName.empty())
+ return;
+
+ Script::Ref function = mItemClass->getEventCallback(mDispellEventName);
+ if (function.isValid())
{
Script *script = ScriptManager::currentState();
script->setMap(itemUser->getMap());
- script->prepare(mDispellFunctionName);
+ script->prepare(function);
script->push(itemUser);
- script->push(mItemId);
+ script->push(mItemClass->getDatabaseID());
script->execute();
}
}
diff --git a/src/game-server/item.h b/src/game-server/item.h
index 8cd3ce6..2677589 100644
--- a/src/game-server/item.h
+++ b/src/game-server/item.h
@@ -24,8 +24,10 @@
#include <vector>
#include "game-server/actor.h"
+#include "scripting/script.h"
class Being;
+class ItemClass;
// Indicates the equip slot "cost" to equip an item.
struct ItemEquipRequirement {
@@ -143,12 +145,12 @@ class ItemEffectConsumes : public ItemEffectInfo
class ItemEffectScript : public ItemEffectInfo
{
public:
- ItemEffectScript(int itemId,
- const std::string& activateFunctionName,
- const std::string& dispellFunctionName):
- mItemId(itemId),
- mActivateFunctionName(activateFunctionName),
- mDispellFunctionName(dispellFunctionName)
+ ItemEffectScript(ItemClass *itemClass,
+ const std::string &activateEventName,
+ const std::string &dispellEventName):
+ mItemClass(itemClass),
+ mActivateEventName(activateEventName),
+ mDispellEventName(dispellEventName)
{}
~ItemEffectScript();
@@ -157,9 +159,9 @@ class ItemEffectScript : public ItemEffectInfo
void dispell(Being *itemUser);
private:
- int mItemId;
- std::string mActivateFunctionName;
- std::string mDispellFunctionName;
+ ItemClass *mItemClass;
+ std::string mActivateEventName;
+ std::string mDispellEventName;
};
@@ -234,6 +236,12 @@ class ItemClass
const ItemEquipRequirement &getItemEquipRequirement() const
{ return mEquipReq; }
+ void setEventCallback(const std::string &event, Script *script)
+ { script->assignCallback(mEventCallbacks[event]); }
+
+ Script::Ref getEventCallback(const std::string &event) const
+ { return mEventCallbacks.value(event); }
+
private:
/**
* Add an effect to a trigger
@@ -282,6 +290,11 @@ class ItemClass
*/
ItemEquipRequirement mEquipReq;
+ /**
+ * Named event callbacks. Can be used in custom item effects.
+ */
+ utils::NameMap<Script::Ref> mEventCallbacks;
+
friend class ItemManager;
};
diff --git a/src/game-server/itemmanager.cpp b/src/game-server/itemmanager.cpp
index b334760..8c74680 100644
--- a/src/game-server/itemmanager.cpp
+++ b/src/game-server/itemmanager.cpp
@@ -404,50 +404,25 @@ void ItemManager::readEffectNode(xmlNodePtr effectNode, ItemClass *item)
{
item->addEffect(new ItemEffectConsumes, triggerTypes.first);
}
- else if (xmlStrEqual(subNode->name, BAD_CAST "script"))
+ else if (xmlStrEqual(subNode->name, BAD_CAST "scriptevent"))
{
- std::string activateFunctionName = XML::getProperty(subNode,
- "function",
- std::string());
- if (activateFunctionName.empty())
- {
- LOG_WARN("Item Manager: Empty function definition "
- "for script effect, skipping!");
- continue;
- }
-
- std::string src = XML::getProperty(subNode, "src", std::string());
- if (src.empty())
- {
- LOG_WARN("Item Manager: Empty src definition for script effect,"
- " skipping!");
- continue;
- }
- std::stringstream filename;
- filename << "scripts/items/" << src;
- if (!ResourceManager::exists(filename.str()))
- {
- LOG_WARN("Could not find script file \"" << filename.str()
- << "\" for item #" << item->mDatabaseID);
- continue;
- }
-
- LOG_INFO("Loading item script: " << filename.str());
- Script *script = ScriptManager::currentState();
- if (!script->loadFile(filename.str()))
+ std::string activateEventName = XML::getProperty(subNode,
+ "activate",
+ std::string());
+ if (activateEventName.empty())
{
- LOG_WARN("Could not load script file \"" << filename.str()
- << "\" for item #" << item->mDatabaseID);
+ LOG_WARN("Item Manager: Empty name for 'activate' item script "
+ "event, skipping effect!");
continue;
}
- std::string dispellFunctionName = XML::getProperty(subNode,
- "dispell-function",
- std::string());
+ std::string dispellEventName = XML::getProperty(subNode,
+ "dispell",
+ std::string());
- item->addEffect(new ItemEffectScript(item->mDatabaseID,
- activateFunctionName,
- dispellFunctionName),
+ item->addEffect(new ItemEffectScript(item,
+ activateEventName,
+ dispellEventName),
triggerTypes.first,
triggerTypes.second);
}
diff --git a/src/game-server/monster.cpp b/src/game-server/monster.cpp
index 21eeea7..b82f463 100644
--- a/src/game-server/monster.cpp
+++ b/src/game-server/monster.cpp
@@ -28,7 +28,6 @@
#include "game-server/item.h"
#include "game-server/mapcomposite.h"
#include "game-server/state.h"
-#include "scripting/script.h"
#include "scripting/scriptmanager.h"
#include "utils/logger.h"
#include "utils/speedconv.h"
@@ -140,16 +139,20 @@ void Monster::perform()
int hit = performAttack(mTarget, dmg);
- if (! mCurrentAttack->scriptFunction.empty()
+ if (! mCurrentAttack->scriptEvent.empty()
&& hit > -1)
{
- Script *script = ScriptManager::currentState();
- script->setMap(getMap());
- script->prepare(mCurrentAttack->scriptFunction);
- script->push(this);
- script->push(mTarget);
- script->push(hit);
- script->execute();
+ Script::Ref function = mSpecy->getEventCallback(mCurrentAttack->scriptEvent);
+ if (function.isValid())
+ {
+ Script *script = ScriptManager::currentState();
+ script->setMap(getMap());
+ script->prepare(function);
+ script->push(this);
+ script->push(mTarget);
+ script->push(hit);
+ script->execute();
+ }
}
}
}
@@ -180,11 +183,14 @@ void Monster::update()
return;
}
- Script *script = ScriptManager::currentState();
- script->setMap(getMap());
- script->prepare("update_monster");
- script->push(this);
- script->execute();
+ if (mSpecy->getUpdateCallback().isValid())
+ {
+ Script *script = ScriptManager::currentState();
+ script->setMap(getMap());
+ script->prepare(mSpecy->getUpdateCallback());
+ script->push(this);
+ script->execute();
+ }
// Cancel the rest when we are currently performing an attack
if (isTimerRunning(T_M_ATTACK_TIME))
diff --git a/src/game-server/monster.h b/src/game-server/monster.h
index 37bbe35..5ccabfa 100644
--- a/src/game-server/monster.h
+++ b/src/game-server/monster.h
@@ -28,6 +28,8 @@
#include "game-server/being.h"
#include "game-server/eventlistener.h"
#include "common/defines.h"
+#include "scripting/script.h"
+#include "utils/string.h"
class ItemClass;
class Script;
@@ -57,7 +59,7 @@ struct MonsterAttack
int preDelay;
int aftDelay;
int range;
- std::string scriptFunction;
+ std::string scriptEvent;
};
typedef std::vector< MonsterAttack *> MonsterAttacks;
@@ -197,6 +199,18 @@ class MonsterClass
/** Returns script filename */
const std::string &getScript() const { return mScript; }
+ void setUpdateCallback(Script *script)
+ { script->assignCallback(mUpdateCallback); }
+
+ void setEventCallback(const std::string &event, Script *script)
+ { script->assignCallback(mEventCallbacks[event]); }
+
+ Script::Ref getUpdateCallback() const
+ { return mUpdateCallback; }
+
+ Script::Ref getEventCallback(const std::string &event) const
+ { return mEventCallbacks.value(event); }
+
private:
unsigned short mId;
std::string mName;
@@ -217,6 +231,17 @@ class MonsterClass
MonsterAttacks mAttacks;
std::string mScript;
+ /**
+ * A reference to the script function that is called each update.
+ */
+ Script::Ref mUpdateCallback;
+
+ /**
+ * Named event callbacks. Currently only used for custom attack
+ * callbacks.
+ */
+ utils::NameMap<Script::Ref> mEventCallbacks;
+
friend class MonsterManager;
friend class Monster;
};
diff --git a/src/game-server/monstermanager.cpp b/src/game-server/monstermanager.cpp
index bebb74a..7612ddc 100644
--- a/src/game-server/monstermanager.cpp
+++ b/src/game-server/monstermanager.cpp
@@ -243,9 +243,8 @@ void MonsterManager::initialize()
att->preDelay = XML::getProperty(subnode, "pre-delay", 1);
att->aftDelay = XML::getProperty(subnode, "aft-delay", 0);
att->range = XML::getProperty(subnode, "range", 0);
- att->scriptFunction = XML::getProperty(subnode,
- "script-function",
- std::string());
+ att->scriptEvent = XML::getProperty(subnode, "script-event",
+ std::string());
std::string sElement = XML::getProperty(subnode,
"element", "neutral");
att->element = elementFromString(sElement);
diff --git a/src/game-server/statuseffect.cpp b/src/game-server/statuseffect.cpp
index 32e0d62..c101bc0 100644
--- a/src/game-server/statuseffect.cpp
+++ b/src/game-server/statuseffect.cpp
@@ -20,9 +20,8 @@
#include "game-server/statuseffect.h"
-#include "scripting/script.h"
-#include "scripting/scriptmanager.h"
#include "game-server/being.h"
+#include "scripting/scriptmanager.h"
StatusEffect::StatusEffect(int id):
mId(id)
@@ -35,13 +34,13 @@ StatusEffect::~StatusEffect()
void StatusEffect::tick(Being *target, int count)
{
- if (!mTickFunction.empty())
+ if (mTickCallback.isValid())
{
- Script *script = ScriptManager::currentState();
- script->setMap(target->getMap());
- script->prepare(mTickFunction);
- script->push(target);
- script->push(count);
- script->execute();
+ Script *s = ScriptManager::currentState();
+ s->setMap(target->getMap());
+ s->prepare(mTickCallback);
+ s->push(target);
+ s->push(count);
+ s->execute();
}
}
diff --git a/src/game-server/statuseffect.h b/src/game-server/statuseffect.h
index 2b7a36f..7da5fdf 100644
--- a/src/game-server/statuseffect.h
+++ b/src/game-server/statuseffect.h
@@ -21,7 +21,7 @@
#ifndef STATUSEFFECT_H
#define STATUSEFFECT_H
-#include <string>
+#include "scripting/script.h"
class Being;
@@ -36,12 +36,12 @@ class StatusEffect
int getId() const
{ return mId; }
- void setTickFunction(const std::string &tickFunction)
- { mTickFunction = tickFunction; }
+ void setTickCallback(Script *script)
+ { script->assignCallback(mTickCallback); }
private:
int mId;
- std::string mTickFunction;
+ Script::Ref mTickCallback;
};
#endif
diff --git a/src/game-server/statusmanager.cpp b/src/game-server/statusmanager.cpp
index 15203d6..7769ef0 100644
--- a/src/game-server/statusmanager.cpp
+++ b/src/game-server/statusmanager.cpp
@@ -33,6 +33,7 @@
typedef std::map< int, StatusEffect * > StatusEffectsMap;
static StatusEffectsMap statusEffects;
+static utils::NameMap<StatusEffect*> statusEffectsByName;
static std::string statusReferenceFile;
void StatusManager::initialize(const std::string &file)
@@ -59,7 +60,7 @@ void StatusManager::reload()
if (!xmlStrEqual(node->name, BAD_CAST "status-effect"))
continue;
- int id = XML::getProperty(node, "id", 0);
+ const int id = XML::getProperty(node, "id", 0);
if (id < 1)
{
LOG_WARN("Status Manager: The status ID: " << id << " in "
@@ -68,9 +69,24 @@ void StatusManager::reload()
continue;
}
+ StatusEffect *statusEffect = new StatusEffect(id);
+
+ const std::string name = XML::getProperty(node, "name",
+ std::string());
+ if (!name.empty())
+ {
+ if (statusEffectsByName.contains(name))
+ {
+ LOG_WARN("StatusManager: name not unique for status effect "
+ << id);
+ }
+ else
+ {
+ statusEffectsByName.insert(name, statusEffect);
+ }
+ }
+
std::string scriptFile = XML::getProperty(node, "script", std::string());
- std::string tickFunction = XML::getProperty(node, "tick-function",
- std::string());
//TODO: Get these modifiers
/*
modifiers.setAttributeValue(BASE_ATTR_PHY_ATK_MIN, XML::getProperty(node, "attack-min", 0));
@@ -84,8 +100,6 @@ void StatusManager::reload()
modifiers.setAttributeValue(CHAR_ATTR_INTELLIGENCE, XML::getProperty(node, "intelligence", 0));
modifiers.setAttributeValue(CHAR_ATTR_WILLPOWER, XML::getProperty(node, "willpower", 0));
*/
- StatusEffect *statusEffect = new StatusEffect(id);
- statusEffect->setTickFunction(tickFunction);
if (!scriptFile.empty())
{
std::stringstream filename;
@@ -112,11 +126,16 @@ void StatusManager::deinitialize()
delete i->second;
}
statusEffects.clear();
+ statusEffectsByName.clear();
}
StatusEffect *StatusManager::getStatus(int statusId)
{
StatusEffectsMap::const_iterator i = statusEffects.find(statusId);
- return i != statusEffects.end() ? i->second : NULL;
+ return i != statusEffects.end() ? i->second : 0;
}
+StatusEffect *StatusManager::getStatusByName(const std::string &name)
+{
+ return statusEffectsByName.value(name);
+}
diff --git a/src/game-server/statusmanager.h b/src/game-server/statusmanager.h
index fc09adb..8ab321d 100644
--- a/src/game-server/statusmanager.h
+++ b/src/game-server/statusmanager.h
@@ -46,6 +46,11 @@ namespace StatusManager
* Gets the status having the given ID.
*/
StatusEffect *getStatus(int statusId);
+
+ /**
+ * Gets the status having the given name.
+ */
+ StatusEffect *getStatusByName(const std::string &name);
}
#endif // STATUSMANAGER_H
diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp
index 3d59ab9..c6a75d9 100644
--- a/src/scripting/lua.cpp
+++ b/src/scripting/lua.cpp
@@ -46,6 +46,8 @@ extern "C" {
#include "game-server/postman.h"
#include "game-server/quest.h"
#include "game-server/state.h"
+#include "game-server/statuseffect.h"
+#include "game-server/statusmanager.h"
#include "game-server/trigger.h"
#include "net/messageout.h"
#include "scripting/luautil.h"
@@ -210,6 +212,27 @@ static int on_get_special_recharge_cost(lua_State *s)
return 0;
}
+static int get_item_class(lua_State *s)
+{
+ const char *name = luaL_checkstring(s, 1);
+ LuaItemClass::push(s, itemManager->getItemByName(name));
+ return 1;
+}
+
+static int get_monster_class(lua_State *s)
+{
+ const char *name = luaL_checkstring(s, 1);
+ LuaMonsterClass::push(s, monsterManager->getMonsterByName(name));
+ return 1;
+}
+
+static int get_status_effect(lua_State *s)
+{
+ const char *name = luaL_checkstring(s, 1);
+ LuaStatusEffect::push(s, StatusManager::getStatusByName(name));
+ return 1;
+}
+
/**
* mana.npc_message(NPC*, Character*, string): void
* Callback for sending a NPC_MESSAGE.
@@ -1507,6 +1530,23 @@ static int posY(lua_State *s)
return 0;
}
+static int monster_class_on_update(lua_State *s)
+{
+ MonsterClass *monsterClass = LuaMonsterClass::check(s, 1);
+ luaL_checktype(s, 2, LUA_TFUNCTION);
+ monsterClass->setUpdateCallback(getScript(s));
+ return 0;
+}
+
+static int monster_class_on(lua_State *s)
+{
+ MonsterClass *monsterClass = LuaMonsterClass::check(s, 1);
+ const char *event = luaL_checkstring(s, 2);
+ luaL_checktype(s, 3, LUA_TFUNCTION);
+ monsterClass->setEventCallback(event, getScript(s));
+ return 0;
+}
+
/**
* mana.monster_create(int id || string name, int x, int y): Monster*
* Callback for creating a monster on the current map.
@@ -1620,32 +1660,6 @@ static int monster_remove(lua_State *s)
}
/**
- * mana.monster_load_script(Monster*, string script_filename): void
- * loads a LUA script for the given monster.
- */
-static int monster_load_script(lua_State *s)
-{
- Monster *m = getMonster(s, 1);
- if (!m)
- {
- raiseScriptError(s, "monster_load_script called "
- "for a nonexistent monster.");
- return 0;
- }
-
- const char *scriptName = luaL_checkstring(s, 2);
- if (scriptName[0] == 0)
- {
- raiseScriptError(s, "monster_load_script called "
- "with empty script file name.");
- return 0;
- }
-
- m->loadScript(scriptName);
- return 0;
-}
-
-/**
* mana.chr_get_chest(Character*, string): nil or string
* Callback for getting a quest variable. Starts a recovery and returns
* immediatly, if the variable is not known yet.
@@ -1959,9 +1973,8 @@ static int chr_get_post(lua_State *s)
/**
* mana.being_register(Being*): void
- * Makes the server call the lua functions deathEvent
- * and removeEvent when the being dies or is removed
- * from the map.
+ * Makes the server call the on_being_death and on_being_remove callbacks
+ * when the being dies or is removed from the map.
*/
static int being_register(lua_State *s)
{
@@ -2453,6 +2466,15 @@ static int is_walkable(lua_State *s)
return 1;
}
+static int item_class_on(lua_State *s)
+{
+ ItemClass *itemClass = LuaItemClass::check(s, 1);
+ const char *event = luaL_checkstring(s, 2);
+ luaL_checktype(s, 3, LUA_TFUNCTION);
+ itemClass->setEventCallback(event, getScript(s));
+ return 0;
+}
+
/**
* mana.drop_item(int x, int y, int id || string name[, int number]): bool
* Creates an item stack on the floor.
@@ -2651,6 +2673,14 @@ static int map_object_get_type(lua_State *s)
return 1;
}
+static int status_effect_on_tick(lua_State *s)
+{
+ StatusEffect *statusEffect = LuaStatusEffect::check(s, 1);
+ luaL_checktype(s, 2, LUA_TFUNCTION);
+ statusEffect->setTickCallback(getScript(s));
+ return 0;
+}
+
/**
* mana.announce(text [, sender])
* Does a global announce
@@ -2719,6 +2749,9 @@ LuaScript::LuaScript():
{ "on_craft", &on_craft },
{ "on_use_special", &on_use_special },
{ "on_get_special_recharge_cost", &on_get_special_recharge_cost },
+ { "get_item_class", &get_item_class },
+ { "get_monster_class", &get_monster_class },
+ { "get_status_effect", &get_status_effect },
{ "npc_create", &npc_create },
{ "npc_message", &npc_message },
{ "npc_choice", &npc_choice },
@@ -2761,7 +2794,6 @@ LuaScript::LuaScript():
{ "monster_get_name", &monster_get_name },
{ "monster_change_anger", &monster_change_anger },
{ "monster_remove", &monster_remove },
- { "monster_load_script", &monster_load_script },
{ "being_apply_status", &being_apply_status },
{ "being_remove_status", &being_remove_status },
{ "being_has_status", &being_has_status },
@@ -2809,6 +2841,11 @@ LuaScript::LuaScript():
luaL_register(mState, "mana", callbacks);
lua_pop(mState, 1); // pop the 'mana' table
+ static luaL_Reg const members_ItemClass[] = {
+ { "on", &item_class_on },
+ { NULL, NULL }
+ };
+
static luaL_Reg const members_MapObject[] = {
{ "property", &map_object_get_property },
{ "bounds", &map_object_get_bounds },
@@ -2817,7 +2854,21 @@ LuaScript::LuaScript():
{ NULL, NULL }
};
+ static luaL_Reg const members_MonsterClass[] = {
+ { "on_update", &monster_class_on_update },
+ { "on", &monster_class_on },
+ { NULL, NULL }
+ };
+
+ static luaL_Reg const members_StatusEffect[] = {
+ { "on_tick", &status_effect_on_tick },
+ { NULL, NULL }
+ };
+
+ LuaItemClass::registerType(mState, "ItemClass", members_ItemClass);
LuaMapObject::registerType(mState, "MapObject", members_MapObject);
+ LuaMonsterClass::registerType(mState, "MonsterClass", members_MonsterClass);
+ LuaStatusEffect::registerType(mState, "StatusEffect", members_StatusEffect);
// Make script object available to callback functions.
lua_pushlightuserdata(mState, const_cast<char *>(&registryKey));
diff --git a/src/scripting/luautil.h b/src/scripting/luautil.h
index 049276f..2fc7543 100644
--- a/src/scripting/luautil.h
+++ b/src/scripting/luautil.h
@@ -31,12 +31,14 @@ extern "C" {
#include <set>
#include <vector>
-#include "game-server/map.h"
-
class Being;
-class NPC;
class Character;
+class ItemClass;
+class MapObject;
class Monster;
+class MonsterClass;
+class NPC;
+class StatusEffect;
class Thing;
// Report script errors and interrupt the script.
@@ -105,10 +107,16 @@ public:
/**
* Pushes a userdata reference to the given object on the stack. Either by
* creating one, or reusing an existing one.
+ *
+ * When a null-pointer is passed for \a object, the value 'nil' is pushed.
*/
- static int push(lua_State *s, T *object)
+ static void push(lua_State *s, T *object)
{
- if (!UserDataCache::retrieve(s, object))
+ if (!object)
+ {
+ lua_pushnil(s);
+ }
+ else if (!UserDataCache::retrieve(s, object))
{
void *userData = lua_newuserdata(s, sizeof(T*));
* static_cast<T**>(userData) = object;
@@ -118,8 +126,6 @@ public:
UserDataCache::insert(s, object);
}
-
- return 1;
}
/**
@@ -138,7 +144,10 @@ private:
template <typename T> const char * LuaUserData<T>::mTypeName;
+typedef LuaUserData<ItemClass> LuaItemClass;
typedef LuaUserData<MapObject> LuaMapObject;
+typedef LuaUserData<MonsterClass> LuaMonsterClass;
+typedef LuaUserData<StatusEffect> LuaStatusEffect;
NPC *getNPC(lua_State *s, int p);
diff --git a/src/utils/string.h b/src/utils/string.h
index a21081d..882b1b0 100644
--- a/src/utils/string.h
+++ b/src/utils/string.h
@@ -105,6 +105,11 @@ namespace utils
return result != mMap.end() ? result->second : mDefault;
}
+ T &operator[](const std::string &name)
+ {
+ return mMap[toLower(name)];
+ }
+
bool contains(const std::string &name) const
{
return mMap.find(toLower(name)) != mMap.end();