diff options
Diffstat (limited to 'src/game-server')
-rw-r--r-- | src/game-server/item.cpp | 20 | ||||
-rw-r--r-- | src/game-server/item.h | 31 | ||||
-rw-r--r-- | src/game-server/itemmanager.cpp | 51 | ||||
-rw-r--r-- | src/game-server/monster.cpp | 34 | ||||
-rw-r--r-- | src/game-server/monster.h | 27 | ||||
-rw-r--r-- | src/game-server/monstermanager.cpp | 5 | ||||
-rw-r--r-- | src/game-server/statuseffect.cpp | 17 | ||||
-rw-r--r-- | src/game-server/statuseffect.h | 8 | ||||
-rw-r--r-- | src/game-server/statusmanager.cpp | 31 | ||||
-rw-r--r-- | src/game-server/statusmanager.h | 5 |
10 files changed, 139 insertions, 90 deletions
diff --git a/src/game-server/item.cpp b/src/game-server/item.cpp index 979a1bc3..888c90ad 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 8cd3ce64..2677589f 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 b334760a..8c74680e 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 21eeea7c..b82f4638 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 37bbe355..5ccabfa9 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 bebb74a3..7612ddc1 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 32e0d621..c101bc02 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 2b7a36f8..7da5fdf9 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 15203d65..7769ef0f 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 fc09adb5..8ab321d1 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 |