summaryrefslogtreecommitdiffstats
path: root/src/scripting
diff options
context:
space:
mode:
authorErik Schilling <ablu.erikschilling@googlemail.com>2012-04-03 13:29:05 +0200
committerErik Schilling <ablu.erikschilling@googlemail.com>2012-04-04 16:22:11 +0200
commitf8e816d9185c09d1c17d921b775e483d132982e5 (patch)
tree3ab299ab6057db3bfd8feb24130a6fcb7e64a60d /src/scripting
parente4baa92aae537921dd17873328a95ab17afcfdfc (diff)
downloadmanaserv-f8e816d9185c09d1c17d921b775e483d132982e5.tar.gz
manaserv-f8e816d9185c09d1c17d921b775e483d132982e5.tar.xz
manaserv-f8e816d9185c09d1c17d921b775e483d132982e5.zip
Enhanced special support
- Made the current charge being saved. - Added script binds: - chr_set_special_recharge_speed - chr_get_special_recharge_speed - chr_set_special_mana - chr_get_special_mana - get_special_info - Added special info lua class. Functions: - name - needed_mana - rechargeable - on_use - on_recharged - category Further the engine no longer sets charge to 0 after using of specials this allows more flexbilillity (like failing specials). Changes on the xml database: - recharge renamed to rechargeable (needed by client and server) - needed - the needed mana to trigger a special (server only) - rechargespeed - the defailt recharge speed in mana per tick (server only) - target - the type of target (either being or point) (server and client) I also made the lua engine pushing nil instead of a 0 light userdata when the pointer was 0. Database update needed. Change is tested. Mana-Mantis: #167, #156 Reviewed-by: bjorn.
Diffstat (limited to 'src/scripting')
-rw-r--r--src/scripting/lua.cpp140
-rw-r--r--src/scripting/luascript.cpp5
-rw-r--r--src/scripting/luautil.cpp23
-rw-r--r--src/scripting/luautil.h4
-rw-r--r--src/scripting/scriptmanager.cpp33
-rw-r--r--src/scripting/scriptmanager.h3
6 files changed, 162 insertions, 46 deletions
diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp
index 2d98c71..4767265 100644
--- a/src/scripting/lua.cpp
+++ b/src/scripting/lua.cpp
@@ -1819,9 +1819,10 @@ static int chr_give_special(lua_State *s)
{
// cost_type is ignored until we have more than one cost type
Character *c = checkCharacter(s, 1);
- const int special = luaL_checkint(s, 2);
+ const int special = checkSpecial(s, 2);
+ const int currentMana = luaL_optint(s, 3, 0);
- c->giveSpecial(special);
+ c->giveSpecial(special, currentMana);
return 0;
}
@@ -1853,6 +1854,70 @@ static int chr_take_special(lua_State *s)
}
/**
+ * chr_set_special_recharge_speed(Character*, int special, int speed)
+ * Sets recharge speed for a special.
+ */
+static int chr_set_special_recharge_speed(lua_State *s)
+{
+ Character *c = checkCharacter(s, 1);
+ const int special = checkSpecial(s, 2);
+ const int speed = luaL_checkint(s, 3);
+
+ if (c->setSpecialRechargeSpeed(special, speed))
+ raiseScriptError(s, "chr_set_special_mana called with special "
+ "that is not owned by character.");
+ return 0;
+}
+
+/**
+ * chr_get_special_recharge_speed(Character*, int special)
+ * Gets recharge speed of a special.
+ */
+static int chr_get_special_recharge_speed(lua_State *s)
+{
+ Character *c = checkCharacter(s, 1);
+ const int special = checkSpecial(s, 2);
+
+ SpecialMap::iterator it = c->findSpecial(special);
+
+ luaL_argcheck(s, it != c->getSpecialEnd(), 2,
+ "character does not have special");
+
+ lua_pushinteger(s, it->second.rechargeSpeed);
+ return 1;
+}
+
+/**
+ * chr_set_special_mana(Character*, int special, int mana)
+ * Sets the current charge of the special.
+ */
+static int chr_set_special_mana(lua_State *s)
+{
+ Character *c = checkCharacter(s, 1);
+ const int special = checkSpecial(s, 2);
+ const int mana = luaL_checkint(s, 3);
+ if (!c->setSpecialMana(special, mana))
+ raiseScriptError(s, "chr_set_special_mana called with special "
+ "that is not owned by character.");
+ return 0;
+}
+
+/**
+ * chr_get_special_mana(Character*, int special): int
+ * Gets the current charge of a special.
+ */
+static int chr_get_special_mana(lua_State *s)
+{
+ Character *c = checkCharacter(s, 1);
+ const int special = checkSpecial(s, 2);
+ SpecialMap::iterator it = c->findSpecial(special);
+ luaL_argcheck(s, it != c->getSpecialEnd(), 2,
+ "character does not have special");
+ lua_pushinteger(s, it->second.currentMana);
+ return 1;
+}
+
+/**
* chr_get_rights(Character*): int
* Returns the rights level of a character.
*/
@@ -2207,6 +2272,61 @@ static int announce(lua_State *s)
return 0;
}
+static int get_special_info(lua_State *s)
+{
+ const int special = checkSpecial(s, 1);
+ SpecialManager::SpecialInfo *info = specialManager->getSpecialInfo(special);
+ luaL_argcheck(s, info, 1, "invalid special");
+ LuaSpecialInfo::push(s, info);
+ return 1;
+}
+
+static int specialinfo_get_name(lua_State *s)
+{
+ SpecialManager::SpecialInfo *info = LuaSpecialInfo::check(s, 1);
+ lua_pushstring(s, info->name.c_str());
+ return 1;
+}
+
+static int specialinfo_get_needed_mana(lua_State *s)
+{
+ SpecialManager::SpecialInfo *info = LuaSpecialInfo::check(s, 1);
+ lua_pushinteger(s, info->neededMana);
+ return 1;
+}
+
+static int specialinfo_is_rechargeable(lua_State *s)
+{
+ SpecialManager::SpecialInfo *info = LuaSpecialInfo::check(s, 1);
+ lua_pushboolean(s, info->rechargeable);
+ return 1;
+}
+
+static int specialinfo_get_category(lua_State *s)
+{
+ SpecialManager::SpecialInfo *info = LuaSpecialInfo::check(s, 1);
+ lua_pushstring(s, info->setName.c_str());
+ return 1;
+}
+
+static int specialinfo_on_recharged(lua_State *s)
+{
+ SpecialManager::SpecialInfo *info = LuaSpecialInfo::check(s, 1);
+ Script *script = getScript(s);
+ luaL_checktype(s, 2, LUA_TFUNCTION);
+ script->assignCallback(info->rechargedCallback);
+ return 0;
+}
+
+static int specialinfo_on_use(lua_State *s)
+{
+ SpecialManager::SpecialInfo *info = LuaSpecialInfo::check(s, 1);
+ Script *script = getScript(s);
+ luaL_checktype(s, 2, LUA_TFUNCTION);
+ script->assignCallback(info->useCallback);
+ return 0;
+}
+
static int require_loader(lua_State *s)
{
// Add .lua extension (maybe only do this when it doesn't have it already)
@@ -2292,6 +2412,10 @@ LuaScript::LuaScript():
{ "chr_give_special", &chr_give_special },
{ "chr_has_special", &chr_has_special },
{ "chr_take_special", &chr_take_special },
+ { "chr_set_special_recharge_speed", &chr_set_special_recharge_speed },
+ { "chr_get_special_recharge_speed", &chr_get_special_recharge_speed },
+ { "chr_set_special_mana", &chr_set_special_mana },
+ { "chr_get_special_mana", &chr_get_special_mana },
{ "chr_kick", &chr_kick },
{ "exp_for_level", &exp_for_level },
{ "monster_create", &monster_create },
@@ -2346,6 +2470,7 @@ LuaScript::LuaScript():
{ "get_distance", &get_distance },
{ "map_get_objects", &map_get_objects },
{ "announce", &announce },
+ { "get_special_info", &get_special_info },
{ NULL, NULL }
};
lua_pushvalue(mRootState, LUA_GLOBALSINDEX);
@@ -2376,10 +2501,21 @@ LuaScript::LuaScript():
{ NULL, NULL }
};
+ static luaL_Reg const members_SpecialInfo[] = {
+ { "name", &specialinfo_get_name },
+ { "needed_mana", &specialinfo_get_needed_mana },
+ { "rechargeable", &specialinfo_is_rechargeable },
+ { "on_use", &specialinfo_on_use },
+ { "on_recharged", &specialinfo_on_recharged },
+ { "category", &specialinfo_get_category },
+ { NULL, NULL}
+ };
+
LuaItemClass::registerType(mRootState, "ItemClass", members_ItemClass);
LuaMapObject::registerType(mRootState, "MapObject", members_MapObject);
LuaMonsterClass::registerType(mRootState, "MonsterClass", members_MonsterClass);
LuaStatusEffect::registerType(mRootState, "StatusEffect", members_StatusEffect);
+ LuaSpecialInfo::registerType(mRootState, "SpecialInfo", members_SpecialInfo);
// Make script object available to callback functions.
lua_pushlightuserdata(mRootState, const_cast<char *>(&registryKey));
diff --git a/src/scripting/luascript.cpp b/src/scripting/luascript.cpp
index 36adb91..3a45b3f 100644
--- a/src/scripting/luascript.cpp
+++ b/src/scripting/luascript.cpp
@@ -89,7 +89,10 @@ void LuaScript::push(const std::string &v)
void LuaScript::push(Thing *v)
{
assert(nbArgs >= 0);
- lua_pushlightuserdata(mCurrentState, v);
+ if (v)
+ lua_pushlightuserdata(mCurrentState, v);
+ else
+ lua_pushnil(mCurrentState);
++nbArgs;
}
diff --git a/src/scripting/luautil.cpp b/src/scripting/luautil.cpp
index 67dd739..feed756 100644
--- a/src/scripting/luautil.cpp
+++ b/src/scripting/luautil.cpp
@@ -255,13 +255,22 @@ NPC *checkNPC(lua_State *s, int p)
int checkSkill(lua_State *s, int p)
{
- if (lua_isstring(s, p))
- {
- int id = skillManager->getId(luaL_checkstring(s, p));
- luaL_argcheck(s, id != 0, p, "invalid skill name");
- return id;
- }
- return luaL_checkint(s, 2);
+ if (lua_isnumber(s, p))
+ return luaL_checkint(s, p);
+
+ int id = skillManager->getId(luaL_checkstring(s, p));
+ luaL_argcheck(s, id != 0, p, "invalid special name");
+ return id;
+}
+
+int checkSpecial(lua_State *s, int p)
+{
+ if (lua_isnumber(s, p))
+ return luaL_checkint(s, p);
+
+ int id = specialManager->getId(luaL_checkstring(s, p));
+ luaL_argcheck(s, id != 0, p, "invalid special name");
+ return id;
}
diff --git a/src/scripting/luautil.h b/src/scripting/luautil.h
index a0eac12..86a748a 100644
--- a/src/scripting/luautil.h
+++ b/src/scripting/luautil.h
@@ -34,6 +34,8 @@ extern "C" {
#include <set>
#include <vector>
+#include "game-server/specialmanager.h"
+
class Being;
class Character;
class ItemClass;
@@ -152,6 +154,7 @@ typedef LuaUserData<ItemClass> LuaItemClass;
typedef LuaUserData<MapObject> LuaMapObject;
typedef LuaUserData<MonsterClass> LuaMonsterClass;
typedef LuaUserData<StatusEffect> LuaStatusEffect;
+typedef LuaUserData<SpecialManager::SpecialInfo> LuaSpecialInfo;
Script * getScript(lua_State *s);
@@ -169,6 +172,7 @@ Monster * checkMonster(lua_State *s, int p);
MonsterClass * checkMonsterClass(lua_State *s, int p);
NPC * checkNPC(lua_State *s, int p);
int checkSkill(lua_State *s, int p);
+int checkSpecial(lua_State *s, int p);
MapComposite * checkCurrentMap(lua_State *s, Script *script = 0);
Script::Thread* checkCurrentThread(lua_State *s, Script *script = 0);
diff --git a/src/scripting/scriptmanager.cpp b/src/scripting/scriptmanager.cpp
index c133a5e..76c4dae 100644
--- a/src/scripting/scriptmanager.cpp
+++ b/src/scripting/scriptmanager.cpp
@@ -51,39 +51,6 @@ Script *ScriptManager::currentState()
return _currentState;
}
-// TODO: Have some generic event mechanism rather than calling global functions
-
-void ScriptManager::addDataToSpecial(int id, Special *special)
-{
- /* currently only gets the recharge cost.
- TODO: get any other info in a similar way, but
- first we have to agree on what other
- info we actually want to provide.
- */
- if (special && _getSpecialRechargeCostCallback.isValid())
- {
- _currentState->prepare(_getSpecialRechargeCostCallback);
- _currentState->push(id);
- int scriptReturn = _currentState->execute();
- special->neededMana = scriptReturn;
- }
-}
-
-bool ScriptManager::performSpecialAction(int specialId, Being *caster)
-{
- if (!_specialCallback.isValid())
- {
- LOG_WARN("No callback for specials set! Specials disabled.");
- return false;
- }
-
- _currentState->prepare(_specialCallback);
- _currentState->push(caster);
- _currentState->push(specialId);
- _currentState->execute();
- return true;
-}
-
bool ScriptManager::performCraft(Being *crafter,
const std::list<InventoryItem> &recipe)
{
diff --git a/src/scripting/scriptmanager.h b/src/scripting/scriptmanager.h
index d0d0370..03b6e64 100644
--- a/src/scripting/scriptmanager.h
+++ b/src/scripting/scriptmanager.h
@@ -26,7 +26,6 @@
#include <string>
class Script;
-class Special;
/**
* Manages the script states. In fact at the moment it simply provides access
@@ -56,8 +55,6 @@ bool loadMainScript(const std::string &file);
*/
Script *currentState();
-void addDataToSpecial(int specialId, Special *special);
-bool performSpecialAction(int specialId, Being *caster);
bool performCraft(Being *crafter, const std::list<InventoryItem> &recipe);
void setCraftCallback(Script *script);