diff options
author | Chuck Miller <shadowmil@gmail.com> | 2009-07-17 14:11:30 -0400 |
---|---|---|
committer | Chuck Miller <shadowmil@gmail.com> | 2009-07-17 14:11:30 -0400 |
commit | 1923fcab4fc9aefd3eaa97fd9ca9b1c507bb4bcb (patch) | |
tree | 9400828ce46de3dd8246f012d78af6bf8f4d744b /src | |
parent | 053d2fa151ae209fe15c0a38fddb10abf1f6ad8a (diff) | |
download | manaserv-1923fcab4fc9aefd3eaa97fd9ca9b1c507bb4bcb.tar.gz manaserv-1923fcab4fc9aefd3eaa97fd9ca9b1c507bb4bcb.tar.bz2 manaserv-1923fcab4fc9aefd3eaa97fd9ca9b1c507bb4bcb.tar.xz manaserv-1923fcab4fc9aefd3eaa97fd9ca9b1c507bb4bcb.zip |
Adds scripted status effects
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/game-server/being.cpp | 38 | ||||
-rw-r--r-- | src/game-server/being.hpp | 20 | ||||
-rw-r--r-- | src/game-server/main-game.cpp | 4 | ||||
-rw-r--r-- | src/game-server/statuseffect.cpp | 48 | ||||
-rw-r--r-- | src/game-server/statuseffect.hpp | 47 | ||||
-rw-r--r-- | src/game-server/statusmanager.cpp | 141 | ||||
-rw-r--r-- | src/game-server/statusmanager.hpp | 52 | ||||
-rw-r--r-- | src/scripting/lua.cpp | 39 |
9 files changed, 393 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index d4fdd662..47ce13c8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -137,6 +137,10 @@ tmwserv_game_SOURCES = \ game-server/spawnarea.cpp \ game-server/state.hpp \ game-server/state.cpp \ + game-server/statuseffect.hpp \ + game-server/statuseffect.cpp \ + game-server/statusmanager.hpp \ + game-server/statusmanager.cpp \ game-server/thing.hpp \ game-server/thing.cpp \ game-server/trade.hpp \ diff --git a/src/game-server/being.cpp b/src/game-server/being.cpp index bbe3ac91..a68ed1f5 100644 --- a/src/game-server/being.cpp +++ b/src/game-server/being.cpp @@ -28,6 +28,8 @@ #include "game-server/eventlistener.hpp" #include "game-server/mapcomposite.hpp" #include "game-server/effect.hpp" +#include "game-server/statuseffect.hpp" +#include "game-server/statusmanager.hpp" #include "utils/logger.h" Being::Being(ThingType type): @@ -294,6 +296,25 @@ int Being::getModifiedAttribute(int attr) const return res <= 0 ? 0 : res; } +void Being::applyStatusEffect(int id, int timer) +{ + Status newStatus; + newStatus.status = StatusManager::getStatus(id); + newStatus.time = timer; + mStatus.push_back(newStatus); +} + +bool Being::hasStatusEffect(int id) +{ + StatusEffects::iterator it = mStatus.begin(); + while (it != mStatus.end()) + { + if (it->status->getId() == id) + return true; + } + return false; +} + void Being::update() { int oldHP = getModifiedAttribute(BASE_ATTR_HP); @@ -333,6 +354,23 @@ void Being::update() ++i; } + // Update and run status effects + StatusEffects::iterator it = mStatus.begin(); + while (it != mStatus.end()) + { + it->time--; + if (it->time > 0 && mAction != DEAD) + { + it->status->tick(this, it->time); + } + else + { + it = mStatus.erase(it); + continue; + } + it++; + } + // Check if being died if (getModifiedAttribute(BASE_ATTR_HP) <= 0 && mAction != DEAD) { diff --git a/src/game-server/being.hpp b/src/game-server/being.hpp index 89134c7c..5c431503 100644 --- a/src/game-server/being.hpp +++ b/src/game-server/being.hpp @@ -32,6 +32,7 @@ class Being; class MapComposite; class AttackZone; +class StatusEffect; /** * Beings and actors directions @@ -69,6 +70,7 @@ struct Damage std::list<size_t> usedSkills; /**< Skills used by source (needed for exp calculation) */ }; + /** * Holds the base value of an attribute and the sum of all its modifiers. * While base + mod may be negative, the modified attribute is not. @@ -94,6 +96,13 @@ struct AttributeModifier unsigned char level; }; +struct Status +{ + StatusEffect *status; + unsigned time; // Number of ticks +}; + +typedef std::vector< Status > StatusEffects; typedef std::vector< AttributeModifier > AttributeModifiers; /** @@ -270,6 +279,16 @@ class Being : public Actor */ virtual void modifiedAttribute(int) {} + /** + * Sets a statuseffect on this being + */ + void applyStatusEffect(int id, int time); + + /** + * Returns true if the being has a status effect + */ + bool hasStatusEffect(int id); + /** Gets the name of the being. */ const std::string &getName() const { return mName; } @@ -314,6 +333,7 @@ class Being : public Actor std::string mName; Hits mHitsTaken; /**< List of punches taken since last update. */ AttributeModifiers mModifiers; /**< Currently modified attributes. */ + StatusEffects mStatus; int mHpRegenTimer; /**< Timer for hp regeneration. */ }; diff --git a/src/game-server/main-game.cpp b/src/game-server/main-game.cpp index 03c6aa71..12b8c78c 100644 --- a/src/game-server/main-game.cpp +++ b/src/game-server/main-game.cpp @@ -35,6 +35,7 @@ #include "game-server/itemmanager.hpp" #include "game-server/mapmanager.hpp" #include "game-server/monstermanager.hpp" +#include "game-server/statusmanager.hpp" #include "game-server/postman.hpp" #include "game-server/resourcemanager.hpp" #include "game-server/state.hpp" @@ -55,6 +56,7 @@ using utils::Logger; #define DEFAULT_ITEMSDB_FILE "items.xml" #define DEFAULT_MAPSDB_FILE "maps.xml" #define DEFAULT_MONSTERSDB_FILE "monsters.xml" +#define DEFAULT_STATUSDB_FILE "tmw-status-effect.xml" utils::Timer worldTimer(100, false); /**< Timer for world tics set to 100 ms */ int worldTime = 0; /**< Current world time in 100ms ticks */ @@ -150,6 +152,7 @@ void initialize() MapManager::initialize(DEFAULT_MAPSDB_FILE); ItemManager::initialize(DEFAULT_ITEMSDB_FILE); MonsterManager::initialize(DEFAULT_MONSTERSDB_FILE); + StatusManager::initialize(DEFAULT_STATUSDB_FILE); // --- Initialize the global handlers // FIXME: Make the global handlers global vars or part of a bigger @@ -201,6 +204,7 @@ void deinitialize() MonsterManager::deinitialize(); ItemManager::deinitialize(); MapManager::deinitialize(); + StatusManager::deinitialize(); PHYSFS_deinit(); } diff --git a/src/game-server/statuseffect.cpp b/src/game-server/statuseffect.cpp new file mode 100644 index 00000000..a8179a17 --- /dev/null +++ b/src/game-server/statuseffect.cpp @@ -0,0 +1,48 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * The Mana World is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "game-server/statuseffect.hpp" + +#include "scripting/script.hpp" +#include "game-server/being.hpp" + +StatusEffect::StatusEffect(int id) +{ + mId = id; + mScript = NULL; +} + +StatusEffect::~StatusEffect() +{ + if (mScript) delete mScript; +} + +void StatusEffect::tick(Being *target, int count) +{ + if (mScript) + { + mScript->setMap(target->getMap()); + mScript->prepare("tick"); + mScript->push(target); + mScript->push(count); + mScript->execute(); + } +} diff --git a/src/game-server/statuseffect.hpp b/src/game-server/statuseffect.hpp new file mode 100644 index 00000000..46af13ce --- /dev/null +++ b/src/game-server/statuseffect.hpp @@ -0,0 +1,47 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * The Mana World is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _TMW_STATUSEFFECT_H +#define _TMW_STATUSEFFECT_H + +class Script; +class Being; + +class StatusEffect +{ + public: + StatusEffect(int); + ~StatusEffect(); + + void tick(Being *target, int count); + + int getId() const + { return mId; } + + void setScript(Script *script) + { mScript = script; }; + + private: + int mId; + Script *mScript; +}; + +#endif diff --git a/src/game-server/statusmanager.cpp b/src/game-server/statusmanager.cpp new file mode 100644 index 00000000..ea96a226 --- /dev/null +++ b/src/game-server/statusmanager.cpp @@ -0,0 +1,141 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * The Mana World is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <map> +#include <set> + +#include "game-server/statusmanager.hpp" + +#include "defines.h" +#include "game-server/statuseffect.hpp" +#include "game-server/resourcemanager.hpp" +#include "scripting/script.hpp" +#include "utils/logger.h" +#include "utils/xml.hpp" + +#include <sstream> + +typedef std::map< int, StatusEffect * > StatusEffects; +static StatusEffects statusEffects; +static std::string statusReferenceFile; + +void StatusManager::initialize(const std::string &file) +{ + statusReferenceFile = file; + reload(); +} + +void StatusManager::reload() +{ + int size; + char *data = ResourceManager::loadFile(statusReferenceFile, size); + + if (!data) { + LOG_ERROR("Status Manager: Could not find " << statusReferenceFile << "!"); + free(data); + return; + } + + xmlDocPtr doc = xmlParseMemory(data, size); + free(data); + + if (!doc) + { + LOG_ERROR("Status Manager: Error while parsing status database (" + << statusReferenceFile << ")!"); + return; + } + + xmlNodePtr node = xmlDocGetRootElement(doc); + if (!node || !xmlStrEqual(node->name, BAD_CAST "status-effects")) + { + LOG_ERROR("Status Manager: " << statusReferenceFile + << " is not a valid database file!"); + xmlFreeDoc(doc); + return; + } + + LOG_INFO("Loading status reference..."); + for (node = node->xmlChildrenNode; node != NULL; node = node->next) + { + if (!xmlStrEqual(node->name, BAD_CAST "status-effect")) + { + continue; + } + + int id = XML::getProperty(node, "id", 0); + if (id == 0) + { + LOG_WARN("Status Manager: An (ignored) Status has no ID in " + << statusReferenceFile << "!"); + continue; + } + + std::string scriptFile = XML::getProperty(node, "script", ""); + //TODO: Get these modifiers +/* + modifiers.setAttributeValue(BASE_ATTR_PHY_ATK_MIN, XML::getProperty(node, "attack-min", 0)); + modifiers.setAttributeValue(BASE_ATTR_PHY_ATK_DELTA, XML::getProperty(node, "attack-delta", 0)); + modifiers.setAttributeValue(BASE_ATTR_HP, XML::getProperty(node, "hp", 0)); + modifiers.setAttributeValue(BASE_ATTR_PHY_RES, XML::getProperty(node, "defense", 0)); + modifiers.setAttributeValue(CHAR_ATTR_STRENGTH, XML::getProperty(node, "strength", 0)); + modifiers.setAttributeValue(CHAR_ATTR_AGILITY, XML::getProperty(node, "agility", 0)); + modifiers.setAttributeValue(CHAR_ATTR_DEXTERITY, XML::getProperty(node, "dexterity", 0)); + modifiers.setAttributeValue(CHAR_ATTR_VITALITY, XML::getProperty(node, "vitality", 0)); + 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); + if (scriptFile != "") + { + std::stringstream filename; + filename << "scripts/status/" << scriptFile; + if (ResourceManager::exists(filename.str())) // file exists! + { + LOG_INFO("Loading status script: " << filename.str()); + Script *s = Script::create("lua"); + s->loadFile(filename.str()); + statusEffect->setScript(s); + } else { + LOG_WARN("Could not find script file \"" << filename.str() << "\" for status #"<<id); + } + } + statusEffects[id] = statusEffect; + } + + xmlFreeDoc(doc); +} + +void StatusManager::deinitialize() +{ + for (StatusEffects::iterator i = statusEffects.begin(), i_end = statusEffects.end(); i != i_end; ++i) + { + delete i->second; + } + statusEffects.clear(); +} + +StatusEffect *StatusManager::getStatus(int statusId) +{ + StatusEffects::const_iterator i = statusEffects.find(statusId); + return i != statusEffects.end() ? i->second : NULL; +} + diff --git a/src/game-server/statusmanager.hpp b/src/game-server/statusmanager.hpp new file mode 100644 index 00000000..6f8f7358 --- /dev/null +++ b/src/game-server/statusmanager.hpp @@ -0,0 +1,52 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * The Mana World is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _TMW_STATUSMANAGER_H +#define _TMW_STATUSMANAGER_H + +#include <string> + +class StatusEffect; + +namespace StatusManager +{ + /** + * Loads status reference file. + */ + void initialize(const std::string &); + + /** + * Reloads status reference file. + */ + void reload(); + + /** + * Destroy status classes. + */ + void deinitialize(); + + /** + * Gets the status having the given ID. + */ + StatusEffect *getStatus(int statusId); +} + +#endif diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp index d5c12c76..230c8a3c 100644 --- a/src/scripting/lua.cpp +++ b/src/scripting/lua.cpp @@ -482,6 +482,42 @@ static int npc_trade(lua_State *s) } /** + * Applies a status effect with id to the being given for a amount of time + * tmw.being_apply_status(Being *being, int id, int time) + */ + +static int being_apply_status(lua_State *s) +{ + if (!lua_isuserdata(s, 1) || !lua_isnumber(s, 2) || !lua_isnumber(s, 3)) + { + raiseScriptError(s, "being_apply_status called with incorrect parameters."); + return 0; + } + Being *being = getBeing(s, 1); + int id = lua_tointeger(s, 2); + int time = lua_tointeger(s, 3); + being->applyStatusEffect(id, time); + return 1; +} + +/** + * Returns true if a being has a status effect + * tmw.being_has_status(Being *being, int id) + */ +static int being_has_status(lua_State *s) +{ + if (!lua_isuserdata(s, 1) || !lua_isnumber(s, 2)) + { + raiseScriptError(s, "being_has_status called with incorrect parameters."); + return 0; + } + Being *being = getBeing(s, 1); + lua_pushboolean(s, being->hasStatusEffect(lua_tointeger(s,2))); + return 1; +} + + +/** * Returns the Thing type of the given Being * tmw.being_type(Being *being) */ @@ -499,6 +535,7 @@ static int being_type(lua_State *s) return 1; } + /** * Function for making a being walk to a position * being_walk(Being *being, int x, int y, int speed) @@ -1245,6 +1282,8 @@ LuaScript::LuaScript(): { "chr_get_hair_color", &chr_get_hair_color }, { "exp_for_level", &exp_for_level }, { "monster_create", &monster_create }, + { "being_apply_status", &being_apply_status }, + { "being_has_status", &being_has_status }, { "being_type", &being_type }, { "being_walk", &being_walk }, { "being_say", &being_say }, |