diff options
author | Erik Schilling <ablu.erikschilling@googlemail.com> | 2013-02-20 15:34:28 +0100 |
---|---|---|
committer | Erik Schilling <ablu.erikschilling@googlemail.com> | 2013-02-20 15:34:28 +0100 |
commit | c70c6d19c1cabf46b595591802bceab63d371788 (patch) | |
tree | 1c153d2bfe560171bad5889d528dc5cf110e8533 /src/game-server | |
parent | d707495540581f8c1b9ab3d5007c9c4d1ab83b53 (diff) | |
parent | 587b7682e6bf7dd9e616c1d4789a5ed9aa986e6d (diff) | |
download | manaserv-c70c6d19c1cabf46b595591802bceab63d371788.tar.gz manaserv-c70c6d19c1cabf46b595591802bceab63d371788.tar.bz2 manaserv-c70c6d19c1cabf46b595591802bceab63d371788.tar.xz manaserv-c70c6d19c1cabf46b595591802bceab63d371788.zip |
Merge branch 'master' into lpc2012
Conflicts:
gameserver.cbp
src/account-server/accounthandler.cpp
src/game-server/attack.cpp
src/game-server/attack.h
src/game-server/being.cpp
src/game-server/being.h
src/game-server/character.cpp
src/game-server/character.h
src/game-server/inventory.cpp
src/game-server/item.h
src/game-server/monster.cpp
src/game-server/monster.h
Diffstat (limited to 'src/game-server')
44 files changed, 686 insertions, 779 deletions
diff --git a/src/game-server/actor.h b/src/game-server/actor.h index 324393df..13d4af55 100644 --- a/src/game-server/actor.h +++ b/src/game-server/actor.h @@ -37,7 +37,8 @@ enum UPDATEFLAG_ACTIONCHANGE = 8, UPDATEFLAG_LOOKSCHANGE = 16, UPDATEFLAG_DIRCHANGE = 32, - UPDATEFLAG_HEALTHCHANGE = 64 + UPDATEFLAG_HEALTHCHANGE = 64, + UPDATEFLAG_EMOTE = 128 }; /** diff --git a/src/game-server/attack.cpp b/src/game-server/attack.cpp index 7f539f1a..1825b86a 100644 --- a/src/game-server/attack.cpp +++ b/src/game-server/attack.cpp @@ -20,6 +20,8 @@ #include "attack.h" +#include <cassert> + #include "common/defines.h" #include "game-server/character.h" @@ -28,21 +30,20 @@ AttackInfo *AttackInfo::readAttackNode(xmlNodePtr node) { std::string skill = XML::getProperty(node, "skill", std::string()); + unsigned skillId; if (utils::isNumeric(skill)) - { skillId = utils::stringToInt(skill); - } else - { skillId = skillManager->getId(skill); - if (skillId == 0) - { - LOG_WARN("Error parsing Attack node: Invalid skill " << skill - << " taking default skill"); - skillId = skillManager->getDefaultSkillId(); - } + + if (!skill.empty() && !skillManager->exists(skillId)) + { + LOG_WARN("Error parsing Attack node: Invalid skill " << skill + << " taking default skill"); + skillId = skillManager->getDefaultSkillId(); } + unsigned id = XML::getProperty(node, "id", 0); unsigned priority = XML::getProperty(node, "priority", 0); unsigned warmupTime = XML::getProperty(node, "warmuptime", 0); @@ -118,17 +119,19 @@ void Attacks::startAttack(Attack *attack) attack->getAttackInfo()->getCooldownTime()); } -void Attacks::tick(std::vector<Attack *> *ret) +void Attacks::getUsuableAttacks(std::vector<Attack *> *ret) { + assert(ret != 0); + // we have a current Attack - if (!mAttackTimer.expired() && mCurrentAttack) + if ((!mAttackTimer.expired() && mCurrentAttack)) return; for (std::vector<Attack>::iterator it = mAttacks.begin(); it != mAttacks.end(); ++it) { Attack &attack = *it; - if (ret && attack.isUsuable()) + if (attack.isUsuable()) { ret->push_back(&attack); } diff --git a/src/game-server/attack.h b/src/game-server/attack.h index 7270a007..0bcc361c 100644 --- a/src/game-server/attack.h +++ b/src/game-server/attack.h @@ -175,15 +175,12 @@ class Attacks mCurrentAttack(0) {} - /** - * Whether the being has at least one auto attack that is ready. - */ void add(AttackInfo *); void remove(AttackInfo *); void markAttackAsTriggered(); Attack *getTriggerableAttack(); void startAttack(Attack *attack); - void tick(std::vector<Attack *> *ret); + void getUsuableAttacks(std::vector<Attack *> *ret); /** * Tells the number of attacks available diff --git a/src/game-server/attribute.cpp b/src/game-server/attribute.cpp index 31d743f4..71e5d944 100644 --- a/src/game-server/attribute.cpp +++ b/src/game-server/attribute.cpp @@ -133,7 +133,7 @@ bool durationCompare(const AttributeModifierState *lhs, return lhs->mDuration < rhs->mDuration; } -bool AttributeModifiersEffect::remove(double value, unsigned int id, +bool AttributeModifiersEffect::remove(double value, unsigned id, bool fullCheck) { /* We need to find and check this entry exists, and erase the entry @@ -249,16 +249,17 @@ bool AttributeModifiersEffect::recalculateModifiedValue(double newPrevLayerValue bool Attribute::add(unsigned short duration, double value, - unsigned int layer, int level) + unsigned layer, int id) { assert(mMods.size() > layer); - LOG_DEBUG("Adding modifier to attribute with duration " << duration << - ", value " << value << ", at layer " << layer << " with id " - << level); + LOG_DEBUG("Adding modifier to attribute with duration " << duration + << ", value " << value + << ", at layer " << layer + << " with id " << id); if (mMods.at(layer)->add(duration, value, (layer ? mMods.at(layer - 1)->getCachedModifiedValue() : mBase) - , level)) + , id)) { while (++layer < mMods.size()) { @@ -277,7 +278,7 @@ bool Attribute::add(unsigned short duration, double value, return false; } -bool Attribute::remove(double value, unsigned int layer, +bool Attribute::remove(double value, unsigned layer, int lvl, bool fullcheck) { assert(mMods.size() > layer); @@ -321,7 +322,7 @@ Attribute::Attribute(const AttributeManager::AttributeInfo &info): const std::vector<AttributeModifier> &modifiers = info.modifiers; LOG_DEBUG("Construction of new attribute with '" << modifiers.size() << "' layers."); - for (unsigned int i = 0; i < modifiers.size(); ++i) + for (unsigned i = 0; i < modifiers.size(); ++i) { LOG_DEBUG("Adding layer with stackable type " << modifiers[i].stackableType diff --git a/src/game-server/attribute.h b/src/game-server/attribute.h index 046c8f63..736e54a6 100644 --- a/src/game-server/attribute.h +++ b/src/game-server/attribute.h @@ -31,7 +31,7 @@ class AttributeModifierState public: AttributeModifierState(unsigned short duration, double value, - unsigned int id) + unsigned id) : mDuration(duration) , mValue(value) , mId(id) @@ -48,7 +48,7 @@ class AttributeModifierState * dispells or similar. Exact usage depends on the effect, * origin, etc. */ - const unsigned int mId; + const unsigned mId; friend bool durationCompare(const AttributeModifierState*, const AttributeModifierState*); friend class AttributeModifiersEffect; @@ -75,7 +75,7 @@ class AttributeModifiersEffect /** * remove() - as with Attribute::remove(). */ - bool remove(double value, unsigned int id, bool fullCheck); + bool remove(double value, unsigned id, bool fullCheck); /** * Performs the necessary modifications to mMod when the states change. @@ -132,7 +132,11 @@ class AttributeModifiersEffect class Attribute { public: - Attribute() {throw;} // DEBUG; Find improper constructions + Attribute() + : mBase(0) + , mMinValue(0) + , mMaxValue(0) + {throw;} // DEBUG; Find improper constructions Attribute(const AttributeManager::AttributeInfo &info); @@ -160,7 +164,7 @@ class Attribute * @param id Used to identify this effect. * @return Whether the modified attribute value was changed. */ - bool add(unsigned short duration, double value, unsigned int layer, int id = 0); + bool add(unsigned short duration, double value, unsigned layer, int id = 0); /** * @param value The value of the modifier to be removed. @@ -174,7 +178,7 @@ class Attribute * or only those that are otherwise permanent (ie. duration of 0) * @returns Whether the modified attribute value was changed. */ - bool remove(double value, unsigned int layer, int id, bool fullcheck); + bool remove(double value, unsigned layer, int id, bool fullcheck); /** * clearMods() removes *all* modifications present in this Attribute (!) diff --git a/src/game-server/attributemanager.cpp b/src/game-server/attributemanager.cpp index 3a70fd9a..42c2624d 100644 --- a/src/game-server/attributemanager.cpp +++ b/src/game-server/attributemanager.cpp @@ -33,7 +33,7 @@ void AttributeManager::reload() { mTagMap.clear(); mAttributeMap.clear(); - for (unsigned int i = 0; i < MaxScope; ++i) + for (unsigned i = 0; i < MaxScope; ++i) mAttributeScopes[i].clear(); readAttributesFile(); @@ -43,11 +43,11 @@ void AttributeManager::reload() << ", NonStackableBonus is " << NonStackableBonus << "."); LOG_DEBUG("Additive is " << Additive << ", Multiplicative is " << Multiplicative << "."); const std::string *tag; - unsigned int count = 0; + unsigned count = 0; for (AttributeMap::const_iterator i = mAttributeMap.begin(); i != mAttributeMap.end(); ++i) { - unsigned int lCount = 0; + unsigned lCount = 0; LOG_DEBUG(" "<<i->first<<" : "); for (std::vector<AttributeModifier>::const_iterator j = i->second.modifiers.begin(); @@ -144,13 +144,15 @@ void AttributeManager::readAttributeNode(xmlNodePtr attributeNode) return; } - mAttributeMap[id].modifiers = std::vector<AttributeModifier>(); - mAttributeMap[id].minimum = XML::getFloatProperty(attributeNode, "minimum", - std::numeric_limits<double>::min()); - mAttributeMap[id].maximum = XML::getFloatProperty(attributeNode, "maximum", - std::numeric_limits<double>::max()); - mAttributeMap[id].modifiable = XML::getBoolProperty(attributeNode, "modifiable", - false); + AttributeInfo &attribute = mAttributeMap[id]; + + attribute.modifiers = std::vector<AttributeModifier>(); + attribute.minimum = XML::getFloatProperty(attributeNode, "minimum", + std::numeric_limits<double>::min()); + attribute.maximum = XML::getFloatProperty(attributeNode, "maximum", + std::numeric_limits<double>::max()); + attribute.modifiable = XML::getBoolProperty(attributeNode, "modifiable", + false); for_each_xml_child_node(subNode, attributeNode) { @@ -171,22 +173,19 @@ void AttributeManager::readAttributeNode(xmlNodePtr attributeNode) } else if (scope == "CHARACTER") { - mAttributeScopes[CharacterScope][id] = - &mAttributeMap.at(id); + mAttributeScopes[CharacterScope][id] = &attribute; LOG_DEBUG("Attribute manager: attribute '" << id << "' added to default character scope."); } else if (scope == "MONSTER") { - mAttributeScopes[MonsterScope][id] = - &mAttributeMap.at(id); + mAttributeScopes[MonsterScope][id] = &attribute; LOG_DEBUG("Attribute manager: attribute '" << id << "' added to default monster scope."); } else if (scope == "BEING") { - mAttributeScopes[BeingScope][id] = - &mAttributeMap.at(id); + mAttributeScopes[BeingScope][id] = &attribute; LOG_DEBUG("Attribute manager: attribute '" << id << "' added to default being scope."); } @@ -250,6 +249,15 @@ void AttributeManager::readModifierNode(xmlNodePtr modifierNode, return; } + if (stackableType == NonStackable && effectType == Multiplicative) + { + LOG_WARN("Attribute manager: attribute '" << attributeId + << "' has a non sense modifier. " + << "Having NonStackable and Multiplicative makes no sense! " + << "Skipping modifier!"); + return; + } + mAttributeMap[attributeId].modifiers.push_back( AttributeModifier(stackableType, effectType)); diff --git a/src/game-server/attributemanager.h b/src/game-server/attributemanager.h index 63ebf643..1a55006c 100644 --- a/src/game-server/attributemanager.h +++ b/src/game-server/attributemanager.h @@ -94,7 +94,7 @@ class AttributeManager minimum(std::numeric_limits<double>::min()), maximum(std::numeric_limits<double>::max()), modifiable(false) - {} + {} /** The minimum and maximum permitted attribute values. */ double minimum; diff --git a/src/game-server/being.cpp b/src/game-server/being.cpp index ba45c0fd..2c334b37 100644 --- a/src/game-server/being.cpp +++ b/src/game-server/being.cpp @@ -27,7 +27,6 @@ #include "game-server/attributemanager.h" #include "game-server/character.h" #include "game-server/collisiondetection.h" -#include "game-server/eventlistener.h" #include "game-server/mapcomposite.h" #include "game-server/effect.h" #include "game-server/skillmanager.h" @@ -35,6 +34,11 @@ #include "game-server/statusmanager.h" #include "utils/logger.h" #include "utils/speedconv.h" +#include "scripting/scriptmanager.h" + + +Script::Ref Being::mRecalculateDerivedAttributesCallback; +Script::Ref Being::mRecalculateBaseAttributeCallback; Being::Being(EntityType type): Actor(type), @@ -42,7 +46,8 @@ Being::Being(EntityType type): mTarget(NULL), mGender(GENDER_UNSPECIFIED), mCurrentAttack(0), - mDirection(DOWN) + mDirection(DOWN), + mEmoteId(0) { const AttributeManager::AttributeScope &attr = attributeManager->getAttributeScope(BeingScope); LOG_DEBUG("Being creation: initialisation of " << attr.size() << " attributes."); @@ -58,6 +63,9 @@ Being::Being(EntityType type): Attribute(*it1->second))); } + + signal_inserted.connect(sigc::mem_fun(this, &Being::inserted)); + // TODO: Way to define default base values? // Should this be handled by the virtual modifiedAttribute? // URGENT either way @@ -71,6 +79,14 @@ Being::Being(EntityType type): #endif } +void Being::triggerEmote(int id) +{ + mEmoteId = id; + + if (id > -1) + raiseUpdateFlags(UPDATEFLAG_EMOTE); +} + int Being::damage(Actor * /* source */, const Damage &damage) { if (mAction == DEAD) @@ -111,6 +127,7 @@ int Being::damage(Actor * /* source */, const Damage &damage) "implemented yet and should not be used!"); HPloss = 0; #endif + break; case DAMAGE_DIRECT: break; default: @@ -177,14 +194,7 @@ void Being::died() // reset target mTarget = NULL; - for (Listeners::iterator i = mListeners.begin(), - i_end = mListeners.end(); i != i_end;) - { - const EventListener &l = **i; - ++i; // In case the listener removes itself from the list on the fly. - if (l.dispatch->died) - l.dispatch->died(&l, this); - } + signal_died.emit(this); } void Being::processAttacks() @@ -194,7 +204,7 @@ void Being::processAttacks() // Ticks attacks even when not attacking to permit cooldowns and warmups. std::vector<Attack *> attacksReady; - mAttacks.tick(&attacksReady); + mAttacks.getUsuableAttacks(&attacksReady); if (Attack *triggerableAttack = mAttacks.getTriggerableAttack()) { @@ -203,37 +213,37 @@ void Being::processAttacks() } // Deal with the ATTACK action. - if (!attacksReady.empty()) - { - Attack *highestPriorityAttack = 0; - // Performs all ready attacks. - for (std::vector<Attack *>::iterator it = attacksReady.begin(), - it_end = attacksReady.end(); it != it_end; ++it) - { - // check if target is in range using the pythagorean theorem - int distx = this->getPosition().x - mTarget->getPosition().x; - int disty = this->getPosition().y - mTarget->getPosition().y; - int distSquare = (distx * distx + disty * disty); - AttackInfo *info = (*it)->getAttackInfo(); - int maxDist = info->getDamage().range + getSize(); - - if (distSquare <= maxDist * maxDist && - (!highestPriorityAttack || - info->getPriority() - < info->getPriority())) - { - highestPriorityAttack = *it; - } - } - if (highestPriorityAttack) + if (attacksReady.empty()) + return; + + Attack *highestPriorityAttack = 0; + // Performs all ready attacks. + for (std::vector<Attack *>::const_iterator it = attacksReady.begin(), + it_end = attacksReady.end(); it != it_end; ++it) + { + // check if target is in range using the pythagorean theorem + int distx = this->getPosition().x - mTarget->getPosition().x; + int disty = this->getPosition().y - mTarget->getPosition().y; + int distSquare = (distx * distx + disty * disty); + AttackInfo *info = (*it)->getAttackInfo(); + int maxDist = info->getDamage().range + getSize(); + + if (distSquare <= maxDist * maxDist && + (!highestPriorityAttack || + highestPriorityAttack->getAttackInfo()->getPriority() + < info->getPriority())) { - mAttacks.startAttack(highestPriorityAttack); - mCurrentAttack = highestPriorityAttack; - setDestination(getPosition()); - // TODO: Turn into direction of enemy - raiseUpdateFlags(UPDATEFLAG_ATTACK); + highestPriorityAttack = *it; } } + if (highestPriorityAttack) + { + mAttacks.startAttack(highestPriorityAttack); + mCurrentAttack = highestPriorityAttack; + setDestination(getPosition()); + // TODO: Turn into direction of enemy + raiseUpdateFlags(UPDATEFLAG_ATTACK); + } } void Being::addAttack(AttackInfo *attackInfo) @@ -497,22 +507,27 @@ void Being::setAction(BeingAction action) } } -void Being::applyModifier(unsigned int attr, double value, unsigned int layer, - unsigned int duration, unsigned int id) +void Being::applyModifier(unsigned attr, double value, unsigned layer, + unsigned duration, unsigned id) { mAttributes.at(attr).add(duration, value, layer, id); updateDerivedAttributes(attr); } -bool Being::removeModifier(unsigned int attr, double value, unsigned int layer, - unsigned int id, bool fullcheck) +bool Being::removeModifier(unsigned attr, double value, unsigned layer, + unsigned id, bool fullcheck) { bool ret = mAttributes.at(attr).remove(value, layer, id, fullcheck); updateDerivedAttributes(attr); return ret; } -void Being::setAttribute(unsigned int id, double value) +void Being::setGender(BeingGender gender) +{ + mGender = gender; +} + +void Being::setAttribute(unsigned id, double value) { AttributeMap::iterator ret = mAttributes.find(id); if (ret == mAttributes.end()) @@ -532,7 +547,7 @@ void Being::setAttribute(unsigned int id, double value) } } -double Being::getAttribute(unsigned int id) const +double Being::getAttribute(unsigned id) const { AttributeMap::const_iterator ret = mAttributes.find(id); if (ret == mAttributes.end()) @@ -545,7 +560,7 @@ double Being::getAttribute(unsigned int id) const } -double Being::getModifiedAttribute(unsigned int id) const +double Being::getModifiedAttribute(unsigned id) const { AttributeMap::const_iterator ret = mAttributes.find(id); if (ret == mAttributes.end()) @@ -557,82 +572,71 @@ double Being::getModifiedAttribute(unsigned int id) const return ret->second.getModifiedAttribute(); } -void Being::setModAttribute(unsigned int, double) +void Being::setModAttribute(unsigned, double) { // No-op to satisfy shared structure. // The game-server calculates this manually. return; } -bool Being::recalculateBaseAttribute(unsigned int attr) +void Being::recalculateBaseAttribute(unsigned attr) { LOG_DEBUG("Being: Received update attribute recalculation request for " << attr << "."); if (!mAttributes.count(attr)) { LOG_DEBUG("Being::recalculateBaseAttribute: " << attr << " not found!"); - return false; + return; } - double newBase = getAttribute(attr); - switch (attr) - { - case ATTR_HP_REGEN: - { - double hpPerSec = getModifiedAttribute(ATTR_VIT) * 0.05; - newBase = (hpPerSec * TICKS_PER_HP_REGENERATION / 10); - } - break; - case ATTR_HP: - double diff; - if ((diff = getModifiedAttribute(ATTR_HP) - - getModifiedAttribute(ATTR_MAX_HP)) > 0) - newBase -= diff; - break; - case ATTR_MAX_HP: - newBase = ((getModifiedAttribute(ATTR_VIT) + 3) - * (getModifiedAttribute(ATTR_VIT) + 20)) * 0.125; - break; - case ATTR_MOVE_SPEED_TPS: - newBase = 3.0 + getModifiedAttribute(ATTR_AGI) * 0.08; // Provisional. - break; - case ATTR_MOVE_SPEED_RAW: - newBase = utils::tpsToRawSpeed( - getModifiedAttribute(ATTR_MOVE_SPEED_TPS)); - break; - case ATTR_INV_CAPACITY: - // Provisional - newBase = 2000.0 + getModifiedAttribute(ATTR_STR) * 180.0; - break; - } - if (newBase != getAttribute(attr)) + // Handle speed conversion inside the engine + if (attr == ATTR_MOVE_SPEED_RAW) { - setAttribute(attr, newBase); - return true; + double newBase = utils::tpsToRawSpeed( + getModifiedAttribute(ATTR_MOVE_SPEED_TPS)); + if (newBase != getAttribute(attr)) + setAttribute(attr, newBase); + return; } - LOG_DEBUG("Being: No changes to sync for attribute '" << attr << "'."); - return false; + + if (!mRecalculateBaseAttributeCallback.isValid()) + return; + + Script *script = ScriptManager::currentState(); + script->setMap(getMap()); + script->prepare(mRecalculateBaseAttributeCallback); + script->push(this); + script->push(attr); + script->execute(); } -void Being::updateDerivedAttributes(unsigned int attr) +void Being::updateDerivedAttributes(unsigned attr) { LOG_DEBUG("Being: Updating derived attribute(s) of: " << attr); + + // Handle default actions before handing over to the script engine switch (attr) { case ATTR_MAX_HP: - updateDerivedAttributes(ATTR_HP); case ATTR_HP: raiseUpdateFlags(UPDATEFLAG_HEALTHCHANGE); break; case ATTR_MOVE_SPEED_TPS: - if (getAttribute(attr) > 0.0f) - setAttribute(ATTR_MOVE_SPEED_RAW, utils::tpsToRawSpeed( - getModifiedAttribute(ATTR_MOVE_SPEED_TPS))); - break; - default: - // Do nothing + // Does not make a lot of sense to have in the scripts. + // So handle it here: + recalculateBaseAttribute(ATTR_MOVE_SPEED_RAW); break; } + + if (!mRecalculateDerivedAttributesCallback.isValid()) + return; + + Script *script = ScriptManager::currentState(); + script->setMap(getMap()); + script->prepare(mRecalculateDerivedAttributesCallback); + script->push(this); + script->push(attr); + script->execute(); } void Being::applyStatusEffect(int id, int timer) @@ -743,20 +747,13 @@ void Being::update() processAttacks(); } -void Being::inserted() +void Being::inserted(Entity *) { - Actor::inserted(); - // Reset the old position, since after insertion it is important that it is // in sync with the zone that we're currently present in. mOld = getPosition(); } -void Being::setGender(BeingGender gender) -{ - mGender = gender; -} - void Being::processAttack(Attack &attack) { performAttack(mTarget, attack.getAttackInfo()->getDamage()); diff --git a/src/game-server/being.h b/src/game-server/being.h index eee81470..1d1f4204 100644 --- a/src/game-server/being.h +++ b/src/game-server/being.h @@ -36,7 +36,7 @@ class Being; class MapComposite; class StatusEffect; -typedef std::map< unsigned int, Attribute > AttributeMap; +typedef std::map< unsigned, Attribute > AttributeMap; struct Status { @@ -49,7 +49,7 @@ typedef std::map< int, Status > StatusEffects; /** * Type definition for a list of hits */ -typedef std::vector<unsigned int> Hits; +typedef std::vector<unsigned> Hits; /** * Generic being (living actor). Keeps direction, destination and a few other @@ -192,31 +192,31 @@ class Being : public Actor /** * Sets an attribute. */ - void setAttribute(unsigned int id, double value); + void setAttribute(unsigned id, double value); /** * Gets an attribute. */ - double getAttribute(unsigned int id) const; + double getAttribute(unsigned id) const; /** * Gets an attribute after applying modifiers. */ - double getModifiedAttribute(unsigned int id) const; + double getModifiedAttribute(unsigned id) const; /** * No-op to satisfy shared structure. * @note The game server calculates this manually, so nothing happens * here. */ - void setModAttribute(unsigned int, double); + void setModAttribute(unsigned, double); /** * Checks whether or not an attribute exists in this being. * @returns True if the attribute is present in the being, false otherwise. */ - bool checkAttributeExists(unsigned int id) const + bool checkAttributeExists(unsigned id) const { return mAttributes.count(id); } /** @@ -226,11 +226,11 @@ class Being : public Actor * @param lvl If non-zero, indicates that a temporary modifier can be * dispelled prematuraly by a spell of given level. */ - void applyModifier(unsigned int attr, double value, unsigned int layer, - unsigned int duration = 0, unsigned int id = 0); + void applyModifier(unsigned attr, double value, unsigned layer, + unsigned duration = 0, unsigned id = 0); - bool removeModifier(unsigned int attr, double value, unsigned int layer, - unsigned int id = 0, bool fullcheck = false); + bool removeModifier(unsigned attr, double value, unsigned layer, + unsigned id = 0, bool fullcheck = false); /** * Called when an attribute modifier is changed. @@ -238,14 +238,14 @@ class Being : public Actor * attributes if it has changed. * @returns Whether it was changed. */ - virtual bool recalculateBaseAttribute(unsigned int); + virtual void recalculateBaseAttribute(unsigned); /** * Attribute has changed, recalculate base value of dependant * attributes (and handle other actions for the modified * attribute) */ - virtual void updateDerivedAttributes(unsigned int); + virtual void updateDerivedAttributes(unsigned); /** * Sets a statuseffect on this being @@ -297,10 +297,24 @@ class Being : public Actor void setTarget(Being *target) { mTarget = target; } + static void setUpdateDerivedAttributesCallback(Script *script) + { script->assignCallback(mRecalculateDerivedAttributesCallback); } + + static void setRecalculateBaseAttributeCallback(Script *script) + { script->assignCallback(mRecalculateBaseAttributeCallback); } + + sigc::signal<void, Being *> signal_died; + + /** + * Activate an emote flag on the being. + */ + void triggerEmote(int id); + /** - * Overridden in order to reset the old position upon insertion. + * Tells the last emote used. */ - virtual void inserted(); + int getLastEmote() const + { return mEmoteId; } protected: /** @@ -332,6 +346,11 @@ class Being : public Actor Being(const Being &rhs); Being &operator=(const Being &rhs); + /** + * Connected to signal_inserted to reset the old position. + */ + void inserted(Entity *); + Path mPath; BeingDirection mDirection; /**< Facing direction. */ @@ -340,6 +359,15 @@ class Being : public Actor /** Time until hp is regenerated again */ Timeout mHealthRegenerationTimeout; + + /** The last being emote Id. Used when triggering a being emoticon. */ + int mEmoteId; + + /** Called when derived attributes need to get calculated */ + static Script::Ref mRecalculateDerivedAttributesCallback; + + /** Called when a base attribute needs to get calculated */ + static Script::Ref mRecalculateBaseAttributeCallback; }; #endif // BEING_H diff --git a/src/game-server/buysell.cpp b/src/game-server/buysell.cpp index 78c2bfe0..1a0d8d91 100644 --- a/src/game-server/buysell.cpp +++ b/src/game-server/buysell.cpp @@ -76,7 +76,7 @@ int BuySell::registerPlayerItems() for (InventoryData::const_iterator it = inventoryData.begin(), it_end = inventoryData.end(); it != it_end; ++it) { - unsigned int nb = it->second.amount; + unsigned nb = it->second.amount; if (!nb) continue; diff --git a/src/game-server/buysell.h b/src/game-server/buysell.h index 506dc8ad..38566005 100644 --- a/src/game-server/buysell.h +++ b/src/game-server/buysell.h @@ -76,7 +76,7 @@ class BuySell typedef std::vector< TradedItem > TradedItems; /** The attribute ID of the currency to use. Hardcoded for now (FIXME) */ - unsigned int mCurrencyId; + unsigned mCurrencyId; Character *mChar; /**< Character involved. */ TradedItems mItems; /**< Traded items. */ diff --git a/src/game-server/character.cpp b/src/game-server/character.cpp index 90a261fc..61fb35d1 100644 --- a/src/game-server/character.cpp +++ b/src/game-server/character.cpp @@ -24,7 +24,6 @@ #include "game-server/accountconnection.h" #include "game-server/attributemanager.h" #include "game-server/buysell.h" -#include "game-server/eventlistener.h" #include "game-server/inventory.h" #include "game-server/item.h" #include "game-server/itemmanager.h" @@ -465,98 +464,35 @@ void Character::modifiedAllAttribute() } } -bool Character::recalculateBaseAttribute(unsigned int attr) +void Character::recalculateBaseAttribute(unsigned attr) { - /* - * `attr' may or may not have changed. Recalculate the base value. - */ + // `attr' may or may not have changed. Recalculate the base value. LOG_DEBUG("Received update attribute recalculation request at Character " "for " << attr << "."); if (!mAttributes.count(attr)) - return false; - double newBase = getAttribute(attr); - - /* - * Calculate new base. - */ - switch (attr) - { - case ATTR_ACCURACY: - newBase = getModifiedAttribute(ATTR_DEX); // Provisional - break; - case ATTR_DEFENSE: - newBase = 0.3 * getModifiedAttribute(ATTR_VIT); - break; - case ATTR_DODGE: - newBase = getModifiedAttribute(ATTR_AGI); // Provisional - break; - case ATTR_MAGIC_DODGE: - newBase = 1.0; - // TODO - break; - case ATTR_MAGIC_DEFENSE: - newBase = 0.0; - // TODO - break; - case ATTR_BONUS_ASPD: - newBase = 0.0; - // TODO - break; - case ATTR_STR: - if (mKnuckleAttackInfo) - { - Damage &knuckleDamage = mKnuckleAttackInfo->getDamage(); - knuckleDamage.base = getModifiedAttribute(ATTR_STR); - knuckleDamage.delta = knuckleDamage.base / 2; - } - break; - default: - return Being::recalculateBaseAttribute(attr); - } + return; - if (newBase != getAttribute(attr)) + if (attr == ATTR_STR && mKnuckleAttackInfo) { - setAttribute(attr, newBase); - updateDerivedAttributes(attr); - return true; + // TODO: dehardcode this + Damage &knuckleDamage = mKnuckleAttackInfo->getDamage(); + knuckleDamage.base = getModifiedAttribute(ATTR_STR); + knuckleDamage.delta = knuckleDamage.base / 2; } - LOG_DEBUG("No changes to sync for attribute '" << attr << "'."); - return false; + Being::recalculateBaseAttribute(attr); + } -void Character::updateDerivedAttributes(unsigned int attr) + +void Character::updateDerivedAttributes(unsigned attr) { /* * `attr' has changed, perform updates accordingly. */ flagAttribute(attr); - switch(attr) - { - case ATTR_STR: - recalculateBaseAttribute(ATTR_INV_CAPACITY); - break; - case ATTR_AGI: - recalculateBaseAttribute(ATTR_DODGE); - recalculateBaseAttribute(ATTR_MOVE_SPEED_TPS); - break; - case ATTR_VIT: - recalculateBaseAttribute(ATTR_MAX_HP); - recalculateBaseAttribute(ATTR_HP_REGEN); - recalculateBaseAttribute(ATTR_DEFENSE); - break; - case ATTR_INT: - // TODO - break; - case ATTR_DEX: - recalculateBaseAttribute(ATTR_ACCURACY); - break; - case ATTR_WIL: - // TODO - break; - default: - Being::updateDerivedAttributes(attr); - } + + Being::updateDerivedAttributes(attr); } void Character::flagAttribute(int attr) @@ -776,15 +712,12 @@ void Character::addAttack(AttackInfo *attackInfo) void Character::removeAttack(AttackInfo *attackInfo) { + Being::removeAttack(attackInfo); // Add knuckle attack - if (mAttacks.getNumber() == 1) - { + if (mAttacks.getNumber() == 0) Being::addAttack(mKnuckleAttackInfo); - } - Being::removeAttack(attackInfo); } - void Character::disconnected() { mConnected = false; @@ -795,14 +728,7 @@ void Character::disconnected() else GameState::remove(this); - for (Listeners::iterator i = mListeners.begin(), - i_end = mListeners.end(); i != i_end;) - { - const EventListener &l = **i; - ++i; // In case the listener removes itself from the list on the fly. - if (l.dispatch->disconnected) - l.dispatch->disconnected(&l, this); - } + signal_disconnected.emit(this); } bool Character::takeSpecial(int id) diff --git a/src/game-server/character.h b/src/game-server/character.h index 4dc077e8..830504c7 100644 --- a/src/game-server/character.h +++ b/src/game-server/character.h @@ -45,22 +45,22 @@ class Trade; struct SpecialValue { - SpecialValue(unsigned int currentMana, + SpecialValue(unsigned currentMana, const SpecialManager::SpecialInfo *specialInfo) : currentMana(currentMana) , rechargeSpeed(specialInfo->defaultRechargeSpeed) , specialInfo(specialInfo) {} - unsigned int currentMana; - unsigned int rechargeSpeed; + unsigned currentMana; + unsigned rechargeSpeed; const SpecialManager::SpecialInfo *specialInfo; }; /** * Stores specials by their id. */ -typedef std::map<unsigned int, SpecialValue> SpecialMap; +typedef std::map<unsigned, SpecialValue> SpecialMap; /** * The representation of a player's character in the game world. @@ -251,18 +251,18 @@ class Character : public Being void modifiedAllAttribute(); /** - * Recalculate the base value of an attribute and update derived - * attributes if it has changed. - * @returns Whether it was changed. - */ - bool recalculateBaseAttribute(unsigned int); + * Recalculate the base value of an attribute and update derived + * attributes if it has changed. + */ + void recalculateBaseAttribute(unsigned); + /** * Attribute has changed, recalculate base value of dependant * attributes (and handle other actions for the modified * attribute) */ - void updateDerivedAttributes(unsigned int); + void updateDerivedAttributes(unsigned); /** * Calls all the "disconnected" listener. @@ -428,6 +428,8 @@ class Character : public Being virtual void removeAttack(AttackInfo *attackInfo); + sigc::signal<void, Character *> signal_disconnected; + protected: /** * Gets the way the actor blocks pathfinding for other objects diff --git a/src/game-server/command.cpp b/src/game-server/command.cpp index 5e87f9f6..e80b9f98 100644 --- a/src/game-server/command.cpp +++ b/src/game-server/command.cpp @@ -256,7 +256,7 @@ static void ban(Character *from, Character *ch, const std::string &duration) switch (duration[duration.length() - 1]) { case 'd': d = d * 24; // nobreak - case 'h': d = d * 60; + case 'h': d = d * 60; break; } accountHandler->banCharacter(ch, d); } diff --git a/src/game-server/commandhandler.cpp b/src/game-server/commandhandler.cpp index b48f1188..6de22242 100644 --- a/src/game-server/commandhandler.cpp +++ b/src/game-server/commandhandler.cpp @@ -177,7 +177,7 @@ static void say(const std::string message, Character *player) } /* -static bool checkPermission(Character *player, unsigned int permissions) +static bool checkPermission(Character *player, unsigned permissions) { if (player->getAccountLevel() & permissions) { @@ -196,7 +196,7 @@ static bool checkPermission(Character *player, unsigned int permissions) static std::string playerRights(Character *ch) { std::stringstream str; - str << (unsigned int)ch->getAccountLevel(); + str << (unsigned)ch->getAccountLevel(); str << " ( "; std::list<std::string> classes = PermissionManager::getClassList(ch); diff --git a/src/game-server/emotemanager.cpp b/src/game-server/emotemanager.cpp new file mode 100644 index 00000000..35f0aa47 --- /dev/null +++ b/src/game-server/emotemanager.cpp @@ -0,0 +1,70 @@ +/* + * The Mana Server + * Copyright (C) 2012 The Mana Developers + * + * This file is part of The Mana Server. + * + * The Mana Server 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 Server 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 Server. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "emotemanager.h" + +#include "utils/xml.h" +#include "utils/logger.h" + +void EmoteManager::initialize() +{ + clear(); + + XML::Document doc(mEmoteFile); + xmlNodePtr rootNode = doc.rootNode(); + + if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "emotes")) + { + LOG_ERROR("Emote Manager: " << mEmoteFile + << " is not a valid emote file!"); + return; + } + + LOG_INFO("Loading emote reference: " << mEmoteFile); + + for_each_xml_child_node(emoteNode, rootNode) + { + if (!xmlStrEqual(emoteNode->name, BAD_CAST "emote")) + continue; + + int id = XML::getProperty(emoteNode, "id", -1); + if (id < 0) + { + LOG_WARN("The " << mEmoteFile << " file is containing an invalid id" + "(" << id << ") and will be ignored."); + continue; + } + + mEmoteIds.push_back(id); + } + LOG_INFO(mEmoteIds.size() << " emotes available."); +} + +bool EmoteManager::isIdAvailable(int id) const +{ + std::vector<int>::const_iterator it = mEmoteIds.begin(); + std::vector<int>::const_iterator it_end = mEmoteIds.end(); + for (; it != it_end; ++it) + { + if ((*it) == id) + return true; + } + return false; +} diff --git a/src/game-server/emotemanager.h b/src/game-server/emotemanager.h new file mode 100644 index 00000000..42c71680 --- /dev/null +++ b/src/game-server/emotemanager.h @@ -0,0 +1,64 @@ +/* + * The Mana Server + * Copyright (C) 2011-2012 The Mana Developers + * + * This file is part of The Mana Server. + * + * The Mana Server 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 Server 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 Server. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef EMOTEMANAGER_H +#define EMOTEMANAGER_H + +#include "utils/string.h" +#include "utils/xml.h" + +#include <vector> + +class EmoteManager +{ +public: + + EmoteManager(const std::string &emoteFile): + mEmoteFile(emoteFile) + { } + + ~EmoteManager() + { clear(); } + + /** + * Loads emote reference file. + */ + void initialize(); + + /** + * Tells whether the given id is a valid emote one. + */ + bool isIdAvailable(int id) const; + +private: + /** + * Clears up the emote list. + */ + void clear() + { mEmoteIds.clear(); } + + std::string mEmoteFile; + std::vector<int> mEmoteIds; +}; + +extern EmoteManager *emoteManager; + +#endif // EMOTEMANAGER_H diff --git a/src/game-server/entity.cpp b/src/game-server/entity.cpp index 671ef5e6..6cb61e58 100644 --- a/src/game-server/entity.cpp +++ b/src/game-server/entity.cpp @@ -18,51 +18,4 @@ * along with The Mana Server. If not, see <http://www.gnu.org/licenses/>. */ -#include <cassert> - #include "game-server/entity.h" - -#include "game-server/eventlistener.h" - -Entity::~Entity() -{ - /* As another object will stop listening and call removeListener when it is - deleted, the following assertion ensures that all the calls to - removeListener have been performed will this object was still alive. It - is not strictly necessary, as there are cases where no removal is - performed (e.g. ~SpawnArea). But this is rather exceptional, so keep the - assertion to catch all the other forgotten calls to removeListener. */ - assert(mListeners.empty()); -} - -void Entity::addListener(const EventListener *l) -{ - mListeners.insert(l); -} - -void Entity::removeListener(const EventListener *l) -{ - mListeners.erase(l); -} - -void Entity::inserted() -{ - for (Listeners::iterator i = mListeners.begin(), - i_end = mListeners.end(); i != i_end;) - { - const EventListener &l = **i; - ++i; // In case the listener removes itself from the list on the fly. - if (l.dispatch->inserted) l.dispatch->inserted(&l, this); - } -} - -void Entity::removed() -{ - for (Listeners::iterator i = mListeners.begin(), - i_end = mListeners.end(); i != i_end;) - { - const EventListener &l = **i; - ++i; // In case the listener removes itself from the list on the fly. - if (l.dispatch->removed) l.dispatch->removed(&l, this); - } -} diff --git a/src/game-server/entity.h b/src/game-server/entity.h index 652db7c7..91f13699 100644 --- a/src/game-server/entity.h +++ b/src/game-server/entity.h @@ -23,18 +23,20 @@ #include "common/manaserv_protocol.h" -using namespace ManaServ; - #include <set> -class EventListener; +#include <sigc++/signal.h> +#include <sigc++/trackable.h> + +using namespace ManaServ; + class MapComposite; /** * Base class for in-game objects. Knows only its type and the map it resides * on. Provides listeners. */ -class Entity +class Entity : public sigc::trackable { public: Entity(EntityType type, MapComposite *map = 0) @@ -42,7 +44,7 @@ class Entity mType(type) {} - virtual ~Entity(); + virtual ~Entity() {} /** * Gets type of this entity. @@ -88,29 +90,8 @@ class Entity virtual void setMap(MapComposite *map) { mMap = map; } - /** - * Adds a new listener. - */ - void addListener(const EventListener *); - - /** - * Removes an existing listener. - */ - void removeListener(const EventListener *); - - /** - * Calls all the "inserted" listeners. - */ - virtual void inserted(); - - /** - * Calls all the "removed" listeners. - */ - virtual void removed(); - - protected: - typedef std::set< const EventListener * > Listeners; - Listeners mListeners; /**< List of event listeners. */ + sigc::signal<void, Entity *> signal_inserted; + sigc::signal<void, Entity *> signal_removed; private: MapComposite *mMap; /**< Map the entity is on */ diff --git a/src/game-server/eventlistener.h b/src/game-server/eventlistener.h deleted file mode 100644 index 53d92077..00000000 --- a/src/game-server/eventlistener.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * The Mana Server - * Copyright (C) 2007-2010 The Mana World Development Team - * - * This file is part of The Mana Server. - * - * The Mana Server 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 Server 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 Server. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef GAMESERVER_EVENTLISTENER_H -#define GAMESERVER_EVENTLISTENER_H - -class Entity; -class Being; -class Character; - -struct EventDispatch; - -/** - * Pointer to a dispatch table. - */ -struct EventListener -{ - const EventDispatch *dispatch; - EventListener(const EventDispatch *d): dispatch(d) {} -}; - -/** - * Dispatch table for event notification. - */ -struct EventDispatch -{ - /** - * Called just after something is inserted in a map. - */ - void (*inserted)(const EventListener *, Entity *); - - /** - * Called just before something is removed from a map. - */ - void (*removed)(const EventListener *, Entity *); - - /** - * Called just after a being has died. - */ - void (*died)(const EventListener *, Being *); - - /** - * Called just before a character is deleted. - */ - void (*disconnected)(const EventListener *, Character *); - - /** - * Initializes dispatch methods as missing. - */ - EventDispatch(): - inserted(0), removed(0), died(0), disconnected(0) - {} -}; - -/** - * Helper for using member functions as dispatch methods. The 3-level structure - * is due to default template parameter not being allowed on functions yet. - * Conceptually, this helper takes two parameters: the name of the member - * variable pointing to the dispatch table and the name of the member function - * to call on dispatch. With these two parameters, it creates a dispatch - * method. When called, this free function forwards the call to the member - * function. - * Pseudo-syntax for getting a dispatch method: - * <code>&EventListenerFactory< _, DispatchPointerName >::create< _, MemberFunctionName >::function</code> - * See the start of the spawnarea.cpp file for a complete example. - */ -template< class T, EventListener T::*D > -struct EventListenerFactory -{ - template< class U, void (T::*F)(U *), class V = U > - struct create - { - static void function(const EventListener *d, V *u) - { - /* Get the address of the T object by substracting the offset of D - from the pointer d. */ - T *t = (T *)((char *)d - - ((char *)&(((T *)42)->*D) - (char *)&(*(T *)42))); - // Then call the method F of this T object. - (t->*F)(u); - } - }; -}; - -#endif diff --git a/src/game-server/gamehandler.cpp b/src/game-server/gamehandler.cpp index 8dde8d9a..3b356a5c 100644 --- a/src/game-server/gamehandler.cpp +++ b/src/game-server/gamehandler.cpp @@ -28,6 +28,7 @@ #include "game-server/accountconnection.h" #include "game-server/buysell.h" #include "game-server/commandhandler.h" +#include "game-server/emotemanager.h" #include "game-server/inventory.h" #include "game-server/item.h" #include "game-server/itemmanager.h" @@ -43,7 +44,7 @@ #include "utils/logger.h" #include "utils/tokendispenser.h" -const unsigned int TILES_TO_BE_NEAR = 7; +const unsigned TILES_TO_BE_NEAR = 7; GameHandler::GameHandler(): mTokenCollector(this) @@ -302,6 +303,10 @@ void GameHandler::processMessage(NetComputer *computer, MessageIn &message) handlePartyInvite(client, message); break; + case PGMSG_BEING_EMOTE: + handleTriggerEmoticon(client, message); + break; + default: LOG_WARN("Invalid message type"); client.send(MessageOut(XXMSG_INVALID)); @@ -464,6 +469,7 @@ void GameHandler::handleNpc(GameClient &client, MessageIn &message) case PGMSG_NPC_TALK_NEXT: default: npc->prompt(client.character, message.getId() == PGMSG_NPC_TALK); + break; } } @@ -918,6 +924,13 @@ void GameHandler::handlePartyInvite(GameClient &client, MessageIn &message) client.send(out); } +void GameHandler::handleTriggerEmoticon(GameClient &client, MessageIn &message) +{ + const int id = message.readInt16(); + if (emoteManager->isIdAvailable(id)) + client.character->triggerEmote(id); +} + void GameHandler::sendNpcError(GameClient &client, int id, const std::string &errorMsg) { diff --git a/src/game-server/gamehandler.h b/src/game-server/gamehandler.h index c0d843e9..c05e0087 100644 --- a/src/game-server/gamehandler.h +++ b/src/game-server/gamehandler.h @@ -152,6 +152,8 @@ class GameHandler: public ConnectionHandler void handlePartyInvite(GameClient &client, MessageIn &message); + void handleTriggerEmoticon(GameClient &client, MessageIn &message); + void sendNpcError(GameClient &client, int id, const std::string &errorMsg); diff --git a/src/game-server/inventory.cpp b/src/game-server/inventory.cpp index 4f5e1811..d523c7b8 100644 --- a/src/game-server/inventory.cpp +++ b/src/game-server/inventory.cpp @@ -68,7 +68,7 @@ void Inventory::initialize() /* * Construct a set of item Ids to keep track of duplicate item Ids. */ - std::set<unsigned int> itemIds; + std::set<unsigned> itemIds; /* * Construct a set of itemIds to keep track of duplicate itemIds. @@ -136,19 +136,25 @@ void Inventory::initialize() } } -unsigned int Inventory::getItem(unsigned int slot) const +unsigned Inventory::getItem(unsigned slot) const { InventoryData::iterator item = mPoss->inventory.find(slot); return item != mPoss->inventory.end() ? item->second.itemId : 0; } -unsigned int Inventory::insert(unsigned int itemId, unsigned int amount) +unsigned Inventory::insert(unsigned itemId, unsigned amount) { if (!itemId || !amount) return 0; MessageOut invMsg(GPMSG_INVENTORY); - unsigned int maxPerSlot = itemManager->getItem(itemId)->getMaxPerSlot(); + ItemClass *item = itemManager->getItem(itemId); + if (!item) { + LOG_ERROR("Inventory: Trying to insert invalid item id " << itemId + << " (amount: " << amount << ")"); + return amount; + } + unsigned maxPerSlot = item->getMaxPerSlot(); LOG_DEBUG("Inventory: Inserting " << amount << " item(s) Id: " << itemId << " for character '" << mCharacter->getName() << "'."); @@ -210,7 +216,6 @@ unsigned int Inventory::insert(unsigned int itemId, unsigned int amount) break; } - ItemClass *item = itemManager->getItem(itemId); if (item) { // EVIL HACK!! This allows to prevent sending the item to client. @@ -227,10 +232,10 @@ unsigned int Inventory::insert(unsigned int itemId, unsigned int amount) return amount; } -unsigned int Inventory::count(unsigned int itemId, +unsigned Inventory::count(unsigned itemId, bool inInventory, bool inEquipment) const { - unsigned int nb = 0; + unsigned nb = 0; if (inInventory) { for (InventoryData::iterator it = mPoss->inventory.begin(), @@ -258,7 +263,7 @@ unsigned int Inventory::count(unsigned int itemId, return nb; } -int Inventory::getFirstSlot(unsigned int itemId) +int Inventory::getFirstSlot(unsigned itemId) { for (InventoryData::iterator it = mPoss->inventory.begin(), it_end = mPoss->inventory.end(); it != it_end; ++it) @@ -267,7 +272,7 @@ int Inventory::getFirstSlot(unsigned int itemId) return -1; } -unsigned int Inventory::remove(unsigned int itemId, unsigned int amount) +unsigned Inventory::remove(unsigned itemId, unsigned amount) { if (!itemId || !amount) return amount; @@ -286,7 +291,7 @@ unsigned int Inventory::remove(unsigned int itemId, unsigned int amount) { if (amount) { - unsigned int sub = std::min(amount, it->second.amount); + unsigned sub = std::min(amount, it->second.amount); amount -= sub; it->second.amount -= sub; invMsg.writeInt16(it->first); @@ -329,8 +334,8 @@ unsigned int Inventory::remove(unsigned int itemId, unsigned int amount) return amount; } -unsigned int Inventory::move(unsigned int slot1, unsigned int slot2, - unsigned int amount) +unsigned Inventory::move(unsigned slot1, unsigned slot2, + unsigned amount) { LOG_DEBUG(amount << " item(s) requested to move from: " << slot1 << " to " << slot2 << " for character: '" << mCharacter->getName() << "'."); @@ -347,7 +352,7 @@ unsigned int Inventory::move(unsigned int slot1, unsigned int slot2, MessageOut invMsg(GPMSG_INVENTORY); - unsigned int nb = std::min(amount, it1->second.amount); + unsigned nb = std::min(amount, it1->second.amount); if (it2 == inv_end) { // Slot2 does not yet exist. @@ -360,7 +365,7 @@ unsigned int Inventory::move(unsigned int slot1, unsigned int slot2, amount -= nb; //Save the itemId in case of deletion of the iterator - unsigned int itemId = it1->second.itemId; + unsigned itemId = it1->second.itemId; invMsg.writeInt16(slot1); // Slot if (it1->second.amount) { @@ -390,8 +395,8 @@ unsigned int Inventory::move(unsigned int slot1, unsigned int slot2, // and when all the amount of slot 1 is moving onto slot 2. if (amount >= it1->second.amount) { - unsigned int itemId = it1->second.itemId; - unsigned int amount = it1->second.amount; + unsigned itemId = it1->second.itemId; + unsigned amount = it1->second.amount; it1->second.itemId = it2->second.itemId; it1->second.amount = it2->second.amount; it2->second.itemId = itemId; @@ -453,7 +458,7 @@ unsigned int Inventory::move(unsigned int slot1, unsigned int slot2, return amount; } -unsigned int Inventory::removeFromSlot(unsigned int slot, unsigned int amount) +unsigned Inventory::removeFromSlot(unsigned slot, unsigned amount) { InventoryData::iterator it = mPoss->inventory.find(slot); @@ -484,7 +489,7 @@ unsigned int Inventory::removeFromSlot(unsigned int slot, unsigned int amount) if (!exists && it->second.itemId) lastSlotOfItemRemaining = true; - unsigned int sub = std::min(amount, it->second.amount); + unsigned sub = std::min(amount, it->second.amount); amount -= sub; it->second.amount -= sub; invMsg.writeInt16(it->first); @@ -513,7 +518,7 @@ unsigned int Inventory::removeFromSlot(unsigned int slot, unsigned int amount) } -void Inventory::updateEquipmentTrigger(unsigned int oldId, unsigned int newId) +void Inventory::updateEquipmentTrigger(unsigned oldId, unsigned newId) { if (!oldId && !newId) return; @@ -535,7 +540,7 @@ void Inventory::updateEquipmentTrigger(ItemClass *oldI, ItemClass *newI) newI->useTrigger(mCharacter, ITT_EQUIP); } -unsigned int Inventory::getNewEquipItemInstance() +unsigned Inventory::getNewEquipItemInstance() { std::set<int> alreadyUsed; for (EquipData::const_iterator it = mPoss->equipSlots.begin(); @@ -544,15 +549,15 @@ unsigned int Inventory::getNewEquipItemInstance() alreadyUsed.insert(it->second.itemInstance); } - unsigned int itemInstance = 1; + unsigned itemInstance = 1; while (alreadyUsed.count(itemInstance)) itemInstance++; return itemInstance; } -bool Inventory::checkEquipmentCapacity(unsigned int equipmentSlot, - unsigned int capacityRequested) +bool Inventory::checkEquipmentCapacity(unsigned equipmentSlot, + unsigned capacityRequested) { int capacity = itemManager->getEquipSlotCapacity(equipmentSlot); @@ -606,7 +611,7 @@ bool Inventory::equip(int inventorySlot) } // List of potential unique itemInstances to unequip first. - std::set<unsigned int> equipInstancesToUnequipFirst; + std::set<unsigned> equipInstancesToUnequipFirst; // We first check the equipment slots for: // - 1. whether enough total equip slot space is available. @@ -653,7 +658,7 @@ bool Inventory::equip(int inventorySlot) } // Potential Pre-unequipment process - for (std::set<unsigned int>::const_iterator it3 = + for (std::set<unsigned>::const_iterator it3 = equipInstancesToUnequipFirst.begin(); it3 != equipInstancesToUnequipFirst.end(); ++it3) { @@ -676,8 +681,8 @@ bool Inventory::equip(int inventorySlot) // Compute an unique equip item Instance id (unicity is per character only.) int itemInstance = getNewEquipItemInstance(); - unsigned int capacityLeft = equipReq.capacityRequired; - unsigned int capacityUsed = 0; + unsigned capacityLeft = equipReq.capacityRequired; + unsigned capacityUsed = 0; // Apply equipment changes for (EquipData::iterator it4 = mPoss->equipSlots.begin(), it4_end = mPoss->equipSlots.end(); it4 != it4_end; ++it4) @@ -707,7 +712,7 @@ bool Inventory::equip(int inventorySlot) // Hence, we add them back if(capacityLeft) { - unsigned int maxCapacity = + unsigned maxCapacity = itemManager->getEquipSlotCapacity(equipReq.equipSlotId); // A should never happen case @@ -717,7 +722,7 @@ bool Inventory::equip(int inventorySlot) { EquipmentItem equipItem(it->second.itemId, itemInstance); mPoss->equipSlots.insert( - std::make_pair<unsigned int, EquipmentItem> + std::make_pair<unsigned, EquipmentItem> (equipReq.equipSlotId, equipItem)); --capacityLeft; } @@ -744,7 +749,7 @@ bool Inventory::equip(int inventorySlot) return true; } -unsigned int Inventory::getSlotItemInstance(unsigned int slot) +unsigned Inventory::getSlotItemInstance(unsigned slot) { EquipData::iterator it = mPoss->equipSlots.find(slot); if (it != mPoss->equipSlots.end()) @@ -752,7 +757,7 @@ unsigned int Inventory::getSlotItemInstance(unsigned int slot) return 0; } -bool Inventory::unequipItem(unsigned int itemId) +bool Inventory::unequipItem(unsigned itemId) { std::set<unsigned> itemInstances; for (EquipData::iterator it = mPoss->equipSlots.begin(), @@ -775,14 +780,14 @@ bool Inventory::unequipItem(unsigned int itemId) return true; } -bool Inventory::unequip(unsigned int itemInstance) +bool Inventory::unequip(unsigned itemInstance) { if (!itemInstance) return false; // The itemId to unequip - unsigned int itemId = 0; - unsigned int slotTypeId = 0; + unsigned itemId = 0; + unsigned slotTypeId = 0; bool addedToInventory = false; @@ -831,7 +836,7 @@ bool Inventory::unequip(unsigned int itemInstance) return true; } -void Inventory::checkLookchanges(unsigned int slotTypeId) +void Inventory::checkLookchanges(unsigned slotTypeId) { if (itemManager->isEquipSlotVisible(slotTypeId)) mCharacter->raiseUpdateFlags(UPDATEFLAG_LOOKSCHANGE); diff --git a/src/game-server/inventory.h b/src/game-server/inventory.h index 3dacb919..42856bff 100644 --- a/src/game-server/inventory.h +++ b/src/game-server/inventory.h @@ -70,64 +70,64 @@ class Inventory * @returns whether all item id could be unequipped. * @note returns true when no item with given ids were equipped. */ - bool unequipItem(unsigned int itemId); + bool unequipItem(unsigned itemId); /** * Unequips item from given equipment slot. * @param itemInstance The item instance id used to know what to unequip * @returns Whether it was unequipped. */ - bool unequip(unsigned int itemInstance); + bool unequip(unsigned itemInstance); /** * Gets the item instance from the given equipment slot. * Return 0 if none. */ - unsigned int getSlotItemInstance(unsigned int slot); + unsigned getSlotItemInstance(unsigned slot); /** * Inserts some items into the inventory. * @return number of items not inserted (to be dropped on floor?). */ - unsigned int insert(unsigned int itemId, unsigned int amount); + unsigned insert(unsigned itemId, unsigned amount); /** * Removes some items from inventory. * @return number of items not removed. */ - unsigned int remove(unsigned int itemId, unsigned int amount); + unsigned remove(unsigned itemId, unsigned amount); /** * Moves some items from the first slot to the second one. * @returns number of items not moved. */ - unsigned int move(unsigned int slot1, unsigned int slot2, - unsigned int amount); + unsigned move(unsigned slot1, unsigned slot2, + unsigned amount); /** * Removes some items from inventory. * @return number of items not removed. */ - unsigned int removeFromSlot(unsigned int slot, unsigned int amount); + unsigned removeFromSlot(unsigned slot, unsigned amount); /** * Counts number of items with given Id. * @param inInventory Search in player's inventory. * @param inEquipment Search in player's equipment. */ - unsigned int count(unsigned int itemId, bool inInventory = true, + unsigned count(unsigned itemId, bool inInventory = true, bool inEquipment = true) const; /** * Gets the ID of the items in a given slot. */ - unsigned int getItem(unsigned int slot) const; + unsigned getItem(unsigned slot) const; /** * Returns the first inventory slot with the given item Id. * Returns -1 otherwise. */ - int getFirstSlot(unsigned int itemId); + int getFirstSlot(unsigned itemId); private: /** @@ -135,15 +135,15 @@ class Inventory * @param equipmentSlot the slot in equipement to check. * @param capacityRequested the capacity needed. */ - bool checkEquipmentCapacity(unsigned int equipmentSlot, - unsigned int capacityRequested); + bool checkEquipmentCapacity(unsigned equipmentSlot, + unsigned capacityRequested); /** * Test whether the inventory has enough space to welcome * the willing-to-be equipment slot. * @todo */ - bool hasInventoryEnoughSpace(unsigned int /* equipmentSlot */) + bool hasInventoryEnoughSpace(unsigned /* equipmentSlot */) { return true; } /** @@ -151,14 +151,14 @@ class Inventory * This is especially useful for scripted equipment. * @todo */ - bool testUnequipScriptRequirements(unsigned int /* equipementSlot */) + bool testUnequipScriptRequirements(unsigned /* equipementSlot */) { return true; } /** * Test the items equipment for scripted requirements. * @todo */ - bool testEquipScriptRequirements(unsigned int /* itemId */) + bool testEquipScriptRequirements(unsigned /* itemId */) { return true; } /** @@ -167,7 +167,7 @@ class Inventory * This is used to differenciate some items that can be equipped * multiple times, like one-handed weapons for instance. */ - unsigned int getNewEquipItemInstance(); + unsigned getNewEquipItemInstance(); /** * Check the inventory is within the slot limit and capacity. @@ -179,12 +179,12 @@ class Inventory /** * Check potential visible character sprite changes. */ - void checkLookchanges(unsigned int slotTypeId); + void checkLookchanges(unsigned slotTypeId); /** * Apply equipment triggers. */ - void updateEquipmentTrigger(unsigned int oldId, unsigned int itemId); + void updateEquipmentTrigger(unsigned oldId, unsigned itemId); void updateEquipmentTrigger(ItemClass *oldI, ItemClass *newI); Possessions *mPoss; /**< Pointer to the modified possessions. */ diff --git a/src/game-server/item.h b/src/game-server/item.h index 7004a2d8..54112c4a 100644 --- a/src/game-server/item.h +++ b/src/game-server/item.h @@ -37,7 +37,7 @@ struct ItemEquipRequirement { capacityRequired(0) {} - unsigned int equipSlotId, capacityRequired; + unsigned equipSlotId, capacityRequired; }; /** @@ -73,7 +73,7 @@ enum ItemTriggerType ITT_NULL = 0, ITT_IN_INVY, // Associated effects apply when the item is in the inventory ITT_ACTIVATE, // Associated effects apply when the item is activated - ITT_EQUIP, // Assosciated effects apply when the item is equipped + ITT_EQUIP, // Associated effects apply when the item is equipped ITT_LEAVE_INVY, // Associated effects apply when the item leaves the inventory ITT_UNEQUIP, // Associated effects apply when the item is unequipped ITT_EQUIPCHG // When the item is still equipped, but in a different way @@ -110,8 +110,8 @@ class ItemEffectInfo class ItemEffectAttrMod : public ItemEffectInfo { public: - ItemEffectAttrMod(unsigned int attrId, unsigned int layer, double value, - unsigned int id, unsigned int duration = 0) : + ItemEffectAttrMod(unsigned attrId, unsigned layer, double value, + unsigned id, unsigned duration = 0) : mAttributeId(attrId), mAttributeLayer(layer), mMod(value), mDuration(duration), mId(id) {} @@ -120,11 +120,11 @@ class ItemEffectAttrMod : public ItemEffectInfo void dispell(Being *itemUser); private: - unsigned int mAttributeId; - unsigned int mAttributeLayer; + unsigned mAttributeId; + unsigned mAttributeLayer; double mMod; - unsigned int mDuration; - unsigned int mId; + unsigned mDuration; + unsigned mId; }; class ItemEffectAttack : public ItemEffectInfo @@ -178,7 +178,7 @@ class ItemEffectScript : public ItemEffectInfo class ItemClass { public: - ItemClass(int id, unsigned int maxperslot): + ItemClass(int id, unsigned maxperslot): mDatabaseID(id), mName("unnamed"), mSpriteID(0), @@ -215,7 +215,7 @@ class ItemClass /** * Gets max item per slot. */ - unsigned int getMaxPerSlot() const + unsigned getMaxPerSlot() const { return mMaxPerSlot; } bool hasTrigger(ItemTriggerType id) @@ -273,7 +273,7 @@ class ItemClass unsigned short mSpriteID; unsigned short mCost; /**< Unit cost the item. */ /** Max item amount per slot in inventory. */ - unsigned int mMaxPerSlot; + unsigned mMaxPerSlot; std::multimap< ItemTriggerType, ItemEffectInfo * > mEffects; std::multimap< ItemTriggerType, ItemEffectInfo * > mDispells; diff --git a/src/game-server/itemmanager.cpp b/src/game-server/itemmanager.cpp index 946815ad..4837ce98 100644 --- a/src/game-server/itemmanager.cpp +++ b/src/game-server/itemmanager.cpp @@ -54,7 +54,7 @@ void ItemManager::deinitialize() delete i->second; } - for (std::map< unsigned int, EquipSlotInfo* >::iterator it = + for (std::map< unsigned, EquipSlotInfo* >::iterator it = mEquipSlotsInfo.begin(), it_end = mEquipSlotsInfo.end(); it != it_end; ++it) { @@ -76,24 +76,24 @@ ItemClass *ItemManager::getItemByName(const std::string &name) const return mItemClassesByName.value(name); } -unsigned int ItemManager::getDatabaseVersion() const +unsigned ItemManager::getDatabaseVersion() const { return mItemDatabaseVersion; } -unsigned int ItemManager::getEquipSlotIdFromName(const std::string &name) const +unsigned ItemManager::getEquipSlotIdFromName(const std::string &name) const { EquipSlotInfo *slotInfo = mNamedEquipSlotsInfo.value(name); return slotInfo ? slotInfo->slotId : 0; } -unsigned int ItemManager::getEquipSlotCapacity(unsigned int id) const +unsigned ItemManager::getEquipSlotCapacity(unsigned id) const { EquipSlotsInfo::const_iterator i = mEquipSlotsInfo.find(id); return i != mEquipSlotsInfo.end() ? i->second->slotCapacity : 0; } -bool ItemManager::isEquipSlotVisible(unsigned int id) const +bool ItemManager::isEquipSlotVisible(unsigned id) const { EquipSlotsInfo::const_iterator i = mEquipSlotsInfo.find(id); return i != mEquipSlotsInfo.end() ? i->second->visibleSlot : false; @@ -160,7 +160,7 @@ void ItemManager::readEquipSlotsFile() EquipSlotInfo *equipSlotInfo = new EquipSlotInfo(slotId, name, capacity, visible); mEquipSlotsInfo.insert( - std::make_pair<unsigned int, EquipSlotInfo*>(slotId, equipSlotInfo)); + std::make_pair<unsigned, EquipSlotInfo*>(slotId, equipSlotInfo)); mNamedEquipSlotsInfo.insert(name, equipSlotInfo); totalCapacity += capacity; @@ -222,7 +222,7 @@ void ItemManager::readItemNode(xmlNodePtr itemNode) return; } - unsigned int maxPerSlot = XML::getProperty(itemNode, "max-per-slot", 0); + unsigned maxPerSlot = XML::getProperty(itemNode, "max-per-slot", 0); if (!maxPerSlot) { LOG_WARN("Item Manager: Missing max-per-slot property for " @@ -373,7 +373,7 @@ void ItemManager::readEffectNode(xmlNodePtr effectNode, ItemClass *item) "but no attribute specified!"); continue; } - unsigned int duration = XML::getProperty(subNode, + unsigned duration = XML::getProperty(subNode, "duration", 0); ModifierLocation location = attributeManager->getLocation(tag); diff --git a/src/game-server/itemmanager.h b/src/game-server/itemmanager.h index cc4fb0ae..6a1f459b 100644 --- a/src/game-server/itemmanager.h +++ b/src/game-server/itemmanager.h @@ -36,14 +36,14 @@ struct EquipSlotInfo slotId(0), slotCapacity(0), visibleSlot(false) {} - EquipSlotInfo(unsigned int id, const std::string &name, - unsigned int capacity, bool visible): + EquipSlotInfo(unsigned id, const std::string &name, + unsigned capacity, bool visible): slotId(id), slotName(name), slotCapacity(capacity), visibleSlot(visible) {} - unsigned int slotId; + unsigned slotId; std::string slotName; - unsigned int slotCapacity; + unsigned slotCapacity; bool visibleSlot; }; @@ -92,16 +92,16 @@ class ItemManager /** * Gets the version of the loaded item database. */ - unsigned int getDatabaseVersion() const; + unsigned getDatabaseVersion() const; - unsigned int getEquipSlotIdFromName(const std::string &name) const; + unsigned getEquipSlotIdFromName(const std::string &name) const; - unsigned int getEquipSlotCapacity(unsigned int id) const; + unsigned getEquipSlotCapacity(unsigned id) const; - unsigned int getVisibleEquipSlotCount() const + unsigned getVisibleEquipSlotCount() const { return mVisibleEquipSlotCount; } - bool isEquipSlotVisible(unsigned int id) const; + bool isEquipSlotVisible(unsigned id) const; private: /** Loads the equip slots that a character has available to them. */ @@ -118,9 +118,9 @@ class ItemManager utils::NameMap<ItemClass*> mItemClassesByName; // Map an equip slot id with the equip slot info. - typedef std::map< unsigned int, EquipSlotInfo* > EquipSlotsInfo; + typedef std::map< unsigned, EquipSlotInfo* > EquipSlotsInfo; // Reference to the vector position of equipSlots - typedef std::vector< unsigned int > VisibleEquipSlots; + typedef std::vector< unsigned > VisibleEquipSlots; EquipSlotsInfo mEquipSlotsInfo; // Map a string (name of slot) with (str-id, max-per-equip-slot) @@ -129,10 +129,10 @@ class ItemManager std::string mItemsFile; std::string mEquipSlotsFile; - unsigned int mVisibleEquipSlotCount; // Cache + unsigned mVisibleEquipSlotCount; // Cache /** Version of the loaded items database file.*/ - unsigned int mItemDatabaseVersion; + unsigned mItemDatabaseVersion; }; extern ItemManager *itemManager; diff --git a/src/game-server/main-game.cpp b/src/game-server/main-game.cpp index 406e7c5b..f76189f9 100644 --- a/src/game-server/main-game.cpp +++ b/src/game-server/main-game.cpp @@ -25,6 +25,7 @@ #include "game-server/accountconnection.h" #include "game-server/attributemanager.h" #include "game-server/gamehandler.h" +#include "game-server/emotemanager.h" #include "game-server/itemmanager.h" #include "game-server/mapmanager.h" #include "game-server/monstermanager.h" @@ -53,6 +54,7 @@ #ifdef __MINGW32__ #include <windows.h> +#include "common/winver.h" #define usleep(usec) (Sleep ((usec) / 1000), 0) #endif @@ -74,6 +76,7 @@ using utils::Logger; #define DEFAULT_PERMISSION_FILE "permissions.xml" #define DEFAULT_MAIN_SCRIPT_FILE "scripts/main.lua" #define DEFAULT_SPECIALSDB_FILE "specials.xml" +#define DEFAULT_EMOTESDB_FILE "emotes.xml" static int const WORLD_TICK_SKIP = 2; /** tolerance for lagging behind in world calculation) **/ @@ -89,6 +92,7 @@ ItemManager *itemManager = new ItemManager(DEFAULT_ITEMSDB_FILE, DEFAULT_EQUIPDB MonsterManager *monsterManager = new MonsterManager(DEFAULT_MONSTERSDB_FILE); SkillManager *skillManager = new SkillManager(DEFAULT_SKILLSDB_FILE); SpecialManager *specialManager = new SpecialManager(DEFAULT_SPECIALSDB_FILE); +EmoteManager *emoteManager = new EmoteManager(DEFAULT_EMOTESDB_FILE); /** Core game message handler */ GameHandler *gameHandler; @@ -141,6 +145,7 @@ static void initializeServer() specialManager->initialize(); itemManager->initialize(); monsterManager->initialize(); + emoteManager->initialize(); StatusManager::initialize(DEFAULT_STATUSDB_FILE); PermissionManager::initialize(DEFAULT_PERMISSION_FILE); @@ -196,6 +201,7 @@ static void deinitializeServer() delete monsterManager; monsterManager = 0; delete skillManager; skillManager = 0; delete itemManager; itemManager = 0; + delete emoteManager; emoteManager = 0; MapManager::deinitialize(); StatusManager::deinitialize(); ScriptManager::deinitialize(); diff --git a/src/game-server/map.cpp b/src/game-server/map.cpp index e372f03d..b4e66e02 100644 --- a/src/game-server/map.cpp +++ b/src/game-server/map.cpp @@ -35,7 +35,11 @@ class PathInfo { public: PathInfo() - : whichList(0) + : Gcost(0) + , Hcost(0) + , whichList(0) + , parentX(0) + , parentY(0) {} int Gcost; /**< Cost from start to this location */ diff --git a/src/game-server/mapcomposite.cpp b/src/game-server/mapcomposite.cpp index cdea12a8..4c7dc66a 100644 --- a/src/game-server/mapcomposite.cpp +++ b/src/game-server/mapcomposite.cpp @@ -92,6 +92,7 @@ void MapZone::insert(Actor *obj) default: { objects.push_back(obj); + break; } } } @@ -117,6 +118,7 @@ void MapZone::remove(Actor *obj) { i = objects.begin() + nbMovingObjects; i_end = objects.end(); + break; } } i = std::find(i, i_end, obj); @@ -464,7 +466,8 @@ MapComposite::MapComposite(int id, const std::string &name): mMap(0), mContent(0), mName(name), - mID(id) + mID(id), + mPvPRules(PVP_NONE) { } diff --git a/src/game-server/monster.cpp b/src/game-server/monster.cpp index 2bc542cd..47246005 100644 --- a/src/game-server/monster.cpp +++ b/src/game-server/monster.cpp @@ -35,18 +35,6 @@ #include <cmath> -struct MonsterTargetEventDispatch: EventDispatch -{ - MonsterTargetEventDispatch() - { - typedef EventListenerFactory<Monster, &Monster::mTargetListener> Factory; - removed = &Factory::create< Entity, &Monster::forgetTarget >::function; - died = &Factory::create<Entity, &Monster::forgetTarget, Being>::function; - } -}; - -static MonsterTargetEventDispatch monsterTargetEventDispatch; - MonsterClass::~MonsterClass() { for (std::vector<AttackInfo *>::iterator it = mAttacks.begin(), @@ -56,7 +44,7 @@ MonsterClass::~MonsterClass() } } -float MonsterClass::getVulnerability(Element element) const +double MonsterClass::getVulnerability(Element element) const { Vulnerabilities::const_iterator it = mVulnerabilities.find(element); if (it == mVulnerabilities.end()) @@ -67,7 +55,6 @@ float MonsterClass::getVulnerability(Element element) const Monster::Monster(MonsterClass *specy): Being(OBJECT_MONSTER), mSpecy(specy), - mTargetListener(&monsterTargetEventDispatch), mOwner(NULL) { LOG_DEBUG("Monster spawned! (id: " << mSpecy->getId() << ")."); @@ -83,7 +70,7 @@ Monster::Monster(MonsterClass *specy): for (AttributeManager::AttributeScope::const_iterator it = mobAttr.begin(), it_end = mobAttr.end(); it != it_end; ++it) { - mAttributes.insert(std::pair< unsigned int, Attribute > + mAttributes.insert(std::pair< unsigned, Attribute > (it->first, Attribute(*it->second))); } @@ -105,13 +92,13 @@ Monster::Monster(MonsterClass *specy): setAttribute(it2->first, mutation ? - attr * (100 + (rand()%(mutation << 1)) - mutation) / 100.0 : + attr * (100 + (rand() % (mutation * 2)) - mutation) / 100.0 : attr); } } mDamageMutation = mutation ? - (100 + (rand()%(mutation << 1)) - mutation) / 100.0 : 1; + (100 + (rand() % (mutation * 2)) - mutation) / 100.0 : 1; setSize(specy->getSize()); setGender(specy->getGender()); @@ -130,19 +117,10 @@ Monster::Monster(MonsterClass *specy): { addAttack(*it); } - - // Load default script - loadScript(specy->getScript()); } Monster::~Monster() { - // Remove death listeners. - for (std::map<Being *, int>::iterator i = mAnger.begin(), - i_end = mAnger.end(); i != i_end; ++i) - { - i->first->removeListener(&mTargetListener); - } } void Monster::update() @@ -229,11 +207,11 @@ void Monster::refreshTarget() // Determine how much we hate the target int targetPriority = 0; - std::map<Being *, int, std::greater<Being *> >::iterator angerIterator; - angerIterator = mAnger.find(target); + std::map<Being *, AggressionInfo>::iterator angerIterator = mAnger.find(target); if (angerIterator != mAnger.end()) { - targetPriority = angerIterator->second; + const AggressionInfo &aggressionInfo = angerIterator->second; + targetPriority = aggressionInfo.anger; } else if (mSpecy->isAggressive()) { @@ -307,25 +285,6 @@ void Monster::processAttack(Attack &attack) } } -void Monster::loadScript(const std::string &scriptName) -{ - if (scriptName.length() == 0) - return; - - std::stringstream filename; - filename << "scripts/monster/" << scriptName; - if (ResourceManager::exists(filename.str())) - { - LOG_INFO("Loading monster script: " << filename.str()); - ScriptManager::currentState()->loadFile(filename.str()); - } - else - { - LOG_WARN("Could not find script file \"" - << filename.str() << "\" for monster"); - } -} - int Monster::calculatePositionPriority(Point position, int targetPriority) { Point thisPos = getPosition(); @@ -359,11 +318,15 @@ int Monster::calculatePositionPriority(Point position, int targetPriority) } } -void Monster::forgetTarget(Entity *t) +void Monster::forgetTarget(Entity *entity) { - Being *b = static_cast< Being * >(t); + Being *b = static_cast< Being * >(entity); + { + AggressionInfo &aggressionInfo = mAnger[b]; + aggressionInfo.removedConnection.disconnect(); + aggressionInfo.diedConnection.disconnect(); + } mAnger.erase(b); - b->removeListener(&mTargetListener); if (b->getType() == OBJECT_CHARACTER) { @@ -375,20 +338,42 @@ void Monster::forgetTarget(Entity *t) void Monster::changeAnger(Actor *target, int amount) { - if (target && (target->getType() == OBJECT_MONSTER - || target->getType() == OBJECT_CHARACTER)) + const EntityType type = target->getType(); + if (type != OBJECT_MONSTER && type != OBJECT_CHARACTER) + return; + + Being *being = static_cast< Being * >(target); + + if (mAnger.find(being) != mAnger.end()) { - Being *t = static_cast< Being * >(target); - if (mAnger.find(t) != mAnger.end()) - { - mAnger[t] += amount; - } - else - { - mAnger[t] = amount; - t->addListener(&mTargetListener); - } + mAnger[being].anger += amount; } + else + { + AggressionInfo &aggressionInfo = mAnger[being]; + aggressionInfo.anger = amount; + + // Forget target either when it's removed or died, whichever + // happens first. + aggressionInfo.removedConnection = + being->signal_removed.connect(sigc::mem_fun(this, &Monster::forgetTarget)); + aggressionInfo.diedConnection = + being->signal_died.connect(sigc::mem_fun(this, &Monster::forgetTarget)); + } +} + +std::map<Being *, int> Monster::getAngerList() const +{ + std::map<Being *, int> result; + std::map<Being *, AggressionInfo>::const_iterator i, i_end; + + for (i = mAnger.begin(), i_end = mAnger.end(); i != i_end; ++i) + { + const AggressionInfo &aggressionInfo = i->second; + result.insert(std::make_pair(i->first, aggressionInfo.anger)); + } + + return result; } int Monster::damage(Actor *source, const Damage &damage) @@ -399,9 +384,7 @@ int Monster::damage(Actor *source, const Damage &damage) newDamage.delta = newDamage.delta * factor; int HPLoss = Being::damage(source, newDamage); if (source) - { changeAnger(source, HPLoss); - } if (HPLoss && source && source->getType() == OBJECT_CHARACTER) { @@ -466,14 +449,14 @@ void Monster::died() iChar++) { Character *character = (*iChar).first; - std::set<size_t> *skillSet = &(*iChar).second; + const std::set<size_t> &skillSet = (*iChar).second; if (mLegalExpReceivers.find(character) == mLegalExpReceivers.end() - || skillSet->size() < 1) + || skillSet.empty()) continue; - int expPerSkill = int(expPerChar / skillSet->size()); - for (iSkill = skillSet->begin(); iSkill != skillSet->end(); + int expPerSkill = int(expPerChar / skillSet.size()); + for (iSkill = skillSet.begin(); iSkill != skillSet.end(); iSkill++) { character->receiveExperience(*iSkill, expPerSkill, @@ -483,44 +466,3 @@ void Monster::died() } } } - -bool Monster::recalculateBaseAttribute(unsigned int attr) -{ - LOG_DEBUG("Monster: Received update attribute recalculation request for " - << attr << "."); - if (!mAttributes.count(attr)) - { - LOG_DEBUG("Monster::recalculateBaseAttribute: " - << attr << " not found!"); - return false; - } - double newBase = getAttribute(attr); - - switch (attr) - { - // Those a set only at load time. - case ATTR_MAX_HP: - case ATTR_DODGE: - case ATTR_MAGIC_DODGE: - case ATTR_ACCURACY: - case ATTR_DEFENSE: - case ATTR_MAGIC_DEFENSE: - case ATTR_HP_REGEN: - case ATTR_MOVE_SPEED_TPS: - case ATTR_INV_CAPACITY: - // nothing to do. - break; - - // Only HP and Speed Raw updated for monsters - default: - Being::recalculateBaseAttribute(attr); - break; - } - if (newBase != getAttribute(attr)) - { - setAttribute(attr, newBase); - return true; - } - LOG_DEBUG("Monster: No changes to sync for attribute '" << attr << "'."); - return false; -} diff --git a/src/game-server/monster.h b/src/game-server/monster.h index a1a82eb5..b924b371 100644 --- a/src/game-server/monster.h +++ b/src/game-server/monster.h @@ -22,7 +22,6 @@ #define MONSTER_H #include "game-server/being.h" -#include "game-server/eventlistener.h" #include "common/defines.h" #include "scripting/script.h" #include "utils/string.h" @@ -31,6 +30,9 @@ #include <vector> #include <string> +#include <sigc++/connection.h> + +class Character; class ItemClass; class Script; @@ -62,7 +64,7 @@ struct MonsterAttack std::string scriptEvent; }; -typedef std::map<Element, float> Vulnerabilities; +typedef std::map<Element, double> Vulnerabilities; /** * Class describing the characteristics of a generic monster. @@ -195,16 +197,10 @@ class MonsterClass /** Returns all attacks of the monster. */ std::vector<AttackInfo *> &getAttackInfos() { return mAttacks; } - void setVulnerability(Element element, float factor) + void setVulnerability(Element element, double factor) { mVulnerabilities[element] = factor; } - float getVulnerability(Element element) const; - - /** sets the script file for the monster */ - void setScript(const std::string &filename) { mScript = filename; } - - /** Returns script filename */ - const std::string &getScript() const { return mScript; } + double getVulnerability(Element element) const; void setUpdateCallback(Script *script) { script->assignCallback(mUpdateCallback); } @@ -237,7 +233,6 @@ class MonsterClass int mOptimalLevel; std::vector<AttackInfo *> mAttacks; Vulnerabilities mVulnerabilities; - std::string mScript; /** * A reference to the script function that is called each update. @@ -301,11 +296,6 @@ class Monster : public Being virtual void processAttack(Attack &attack); /** - * Loads a script file for this monster - */ - void loadScript(const std::string &scriptName); - - /** * Kills the being. */ void died(); @@ -315,8 +305,7 @@ class Monster : public Being */ void changeAnger(Actor *target, int amount); - const std::map<Being *, int> &getAngerList() const - { return mAnger; } + std::map<Being *, int> getAngerList() const; /** * Calls the damage function in Being and updates the aggro list @@ -326,15 +315,7 @@ class Monster : public Being /** * Removes a being from the anger list. */ - void forgetTarget(Entity *being); - - /** - * Called when an attribute modifier is changed. - * Recalculate the base value of an attribute and update derived - * attributes if it has changed. - * @returns Whether it was changed. - */ - virtual bool recalculateBaseAttribute(unsigned int); + void forgetTarget(Entity *entity); protected: /** @@ -351,10 +332,16 @@ class Monster : public Being MonsterClass *mSpecy; /** Aggression towards other beings. */ - std::map<Being *, int> mAnger; - - /** Listener for updating the anger list. */ - EventListener mTargetListener; + struct AggressionInfo { + AggressionInfo() + : anger(0) + {} + + int anger; + sigc::connection removedConnection; + sigc::connection diedConnection; + }; + std::map<Being *, AggressionInfo> mAnger; /** * Character who currently owns this monster (killsteal protection). diff --git a/src/game-server/monstermanager.cpp b/src/game-server/monstermanager.cpp index cfe540d8..0fb62da0 100644 --- a/src/game-server/monstermanager.cpp +++ b/src/game-server/monstermanager.cpp @@ -258,11 +258,12 @@ void MonsterManager::initialize() } } - else if (xmlStrEqual(subnode->name, BAD_CAST "script")) + else if (xmlStrEqual(subnode->name, BAD_CAST "vulnerability")) { - xmlChar *filename = subnode->xmlChildrenNode->content; - std::string val = (char *)filename; - monster->setScript(val); + Element element = elementFromString( + XML::getProperty(subnode, "element", std::string())); + double factor = XML::getFloatProperty(subnode, "factor", 1.0); + monster->setVulnerability(element, factor); } else if (xmlStrEqual(subnode->name, BAD_CAST "vulnerability")) { diff --git a/src/game-server/npc.cpp b/src/game-server/npc.cpp index 82cd6a51..ce6ac32e 100644 --- a/src/game-server/npc.cpp +++ b/src/game-server/npc.cpp @@ -54,6 +54,8 @@ void NPC::update() return; Script *script = ScriptManager::currentState(); + script->setMap(getMap()); + script->prepare(mUpdateCallback); script->push(this); script->execute(); diff --git a/src/game-server/quest.cpp b/src/game-server/quest.cpp index 4d659227..c28a4213 100644 --- a/src/game-server/quest.cpp +++ b/src/game-server/quest.cpp @@ -18,24 +18,27 @@ * along with The Mana Server. If not, see <http://www.gnu.org/licenses/>. */ -#include <cassert> -#include <list> -#include <map> -#include <string> - #include "game-server/quest.h" #include "game-server/accountconnection.h" #include "game-server/character.h" -#include "game-server/eventlistener.h" #include "utils/logger.h" +#include <cassert> +#include <list> +#include <map> +#include <string> + +#include <sigc++/connection.h> + typedef std::list< QuestCallback * > QuestCallbacks; typedef std::map< std::string, QuestCallbacks > PendingVariables; struct PendingQuest { Character *character; + sigc::connection removedConnection; + sigc::connection disconnectedConnection; PendingVariables variables; }; @@ -72,22 +75,6 @@ void setQuestVar(Character *ch, const std::string &name, accountHandler->updateCharacterVar(ch, name, value); } -/** - * Listener for deleting related quests when a character disappears. - */ -struct QuestDeathListener: EventDispatch -{ - static void partialRemove(const EventListener *, Entity *); - - static void fullRemove(const EventListener *, Character *); - - QuestDeathListener() - { - removed = &partialRemove; - disconnected = &fullRemove; - } -}; - void QuestRefCallback::triggerCallback(Character *ch, const std::string &value) const { @@ -103,10 +90,7 @@ void QuestRefCallback::triggerCallback(Character *ch, s->execute(); } -static QuestDeathListener questDeathDummy; -static EventListener questDeathListener(&questDeathDummy); - -void QuestDeathListener::partialRemove(const EventListener *, Entity *t) +static void partialRemove(Entity *t) { int id = static_cast< Character * >(t)->getDatabaseID(); PendingVariables &variables = pendingQuests[id].variables; @@ -119,11 +103,18 @@ void QuestDeathListener::partialRemove(const EventListener *, Entity *t) // The listener is kept in case a fullRemove is needed later. } -void QuestDeathListener::fullRemove(const EventListener *, Character *ch) +static void fullRemove(Character *ch) { - ch->removeListener(&questDeathListener); + int id = ch->getDatabaseID(); + + { + PendingQuest &pendingQuest = pendingQuests[id]; + pendingQuest.removedConnection.disconnect(); + pendingQuest.disconnectedConnection.disconnect(); + } + // Remove anything related to this character. - pendingQuests.erase(ch->getDatabaseID()); + pendingQuests.erase(id); } void recoverQuestVar(Character *ch, const std::string &name, @@ -134,11 +125,19 @@ void recoverQuestVar(Character *ch, const std::string &name, PendingQuests::iterator i = pendingQuests.lower_bound(id); if (i == pendingQuests.end() || i->first != id) { - i = pendingQuests.insert(i, std::make_pair(id, PendingQuest())); - i->second.character = ch; - /* Register a listener, because we cannot afford to get invalid - pointers, when we finally recover the variable. */ - ch->addListener(&questDeathListener); + PendingQuest pendingQuest; + pendingQuest.character = ch; + + /* Connect to removed and disconnected signals, because we cannot + * afford to get invalid pointers, when we finally recover the + * variable. + */ + pendingQuest.removedConnection = + ch->signal_removed.connect(sigc::ptr_fun(partialRemove)); + pendingQuest.disconnectedConnection = + ch->signal_disconnected.connect(sigc::ptr_fun(fullRemove)); + + i = pendingQuests.insert(i, std::make_pair(id, pendingQuest)); } i->second.variables[name].push_back(f); accountHandler->requestCharacterVar(ch, name); @@ -149,12 +148,14 @@ void recoveredQuestVar(int id, const std::string &value) { PendingQuests::iterator i = pendingQuests.find(id); - if (i == pendingQuests.end()) return; + if (i == pendingQuests.end()) + return; - Character *ch = i->second.character; - ch->removeListener(&questDeathListener); + PendingQuest &pendingQuest = i->second; + pendingQuest.removedConnection.disconnect(); + pendingQuest.disconnectedConnection.disconnect(); - PendingVariables &variables = i->second.variables; + PendingVariables &variables = pendingQuest.variables; PendingVariables::iterator j = variables.find(name); if (j == variables.end()) { @@ -162,6 +163,7 @@ void recoveredQuestVar(int id, return; } + Character *ch = pendingQuest.character; ch->questCache[name] = value; // Call the registered callbacks. diff --git a/src/game-server/quest.h b/src/game-server/quest.h index 05caa6ab..0d130789 100644 --- a/src/game-server/quest.h +++ b/src/game-server/quest.h @@ -42,23 +42,21 @@ class QuestCallback class QuestThreadCallback : public QuestCallback { public: - QuestThreadCallback(void (*handler)(Character *, - const std::string &value, - Script *mScript), + typedef void (*Handler)(Character *, + const std::string &value, + Script *mScript); + + QuestThreadCallback(Handler handler, Script *script) : mHandler(handler), mScript(script) { } - virtual void triggerCallback(Character *ch, - const std::string &value) const + void triggerCallback(Character *ch, const std::string &value) const { mHandler(ch, value, mScript); } private: - void (*mHandler)(Character *, - const std::string &value, - Script *mScript); - + Handler mHandler; Script *mScript; }; @@ -69,8 +67,7 @@ class QuestRefCallback : public QuestCallback mQuestName(questName) { script->assignCallback(mRef); } - virtual void triggerCallback(Character *ch, - const std::string &value) const; + void triggerCallback(Character *ch, const std::string &value) const; private: Script::Ref mRef; diff --git a/src/game-server/skillmanager.cpp b/src/game-server/skillmanager.cpp index b5a94cbe..2e78194c 100644 --- a/src/game-server/skillmanager.cpp +++ b/src/game-server/skillmanager.cpp @@ -131,7 +131,7 @@ void SkillManager::readSkillNode(xmlNodePtr skillNode, } mSkillsInfo.insert( - std::make_pair<unsigned int, SkillInfo*>(skillInfo->id, skillInfo)); + std::make_pair<unsigned, SkillInfo*>(skillInfo->id, skillInfo)); std::string keyName = setName + "_" + skillInfo->skillName; mNamedSkillsInfo.insert(keyName, skillInfo); @@ -167,27 +167,33 @@ void SkillManager::printDebugSkillTable() } } -unsigned int SkillManager::getId(const std::string &set, - const std::string &name) const +unsigned SkillManager::getId(const std::string &set, + const std::string &name) const { std::string key = utils::toLower(set) + "_" + utils::toLower(name); return getId(key); } -unsigned int SkillManager::getId(const std::string &skillName) const +unsigned SkillManager::getId(const std::string &skillName) const { SkillInfo *skillInfo = mNamedSkillsInfo.value(skillName); return skillInfo ? skillInfo->id : 0; } -const std::string SkillManager::getSkillName(unsigned int id) const +const std::string SkillManager::getSkillName(unsigned id) const { SkillsInfo::const_iterator it = mSkillsInfo.find(id); return it != mSkillsInfo.end() ? it->second->skillName : ""; } -const std::string SkillManager::getSetName(unsigned int id) const +const std::string SkillManager::getSetName(unsigned id) const { SkillsInfo::const_iterator it = mSkillsInfo.find(id); return it != mSkillsInfo.end() ? it->second->setName : ""; } + +bool SkillManager::exists(unsigned id) const +{ + SkillsInfo::const_iterator it = mSkillsInfo.find(id); + return it != mSkillsInfo.end(); +} diff --git a/src/game-server/skillmanager.h b/src/game-server/skillmanager.h index 36e2485e..85f7f42e 100644 --- a/src/game-server/skillmanager.h +++ b/src/game-server/skillmanager.h @@ -49,18 +49,20 @@ class SkillManager /** * Gets the skill Id from a set and a skill string. */ - unsigned int getId(const std::string &set, const std::string &name) const; + unsigned getId(const std::string &set, const std::string &name) const; /** * Gets the skill Id from a string formatted in this way: * "setname_skillname" */ - unsigned int getId(const std::string &skillName) const; + unsigned getId(const std::string &skillName) const; - const std::string getSkillName(unsigned int id) const; - const std::string getSetName(unsigned int id) const; + const std::string getSkillName(unsigned id) const; + const std::string getSetName(unsigned id) const; - unsigned int getDefaultSkillId() const + bool exists(unsigned id) const; + + unsigned getDefaultSkillId() const { return mDefaultSkillId; } private: struct SkillInfo { @@ -68,7 +70,7 @@ class SkillManager id(0) {} - unsigned int id; + unsigned id; std::string setName; std::string skillName; }; @@ -86,13 +88,13 @@ class SkillManager std::string mSkillFile; // The skill map - typedef std::map<unsigned int, SkillInfo*> SkillsInfo; + typedef std::map<unsigned, SkillInfo*> SkillsInfo; SkillsInfo mSkillsInfo; // A map used to get skills per name. utils::NameMap<SkillInfo*> mNamedSkillsInfo; // The default skill id - unsigned int mDefaultSkillId; + unsigned mDefaultSkillId; }; extern SkillManager *skillManager; diff --git a/src/game-server/spawnarea.cpp b/src/game-server/spawnarea.cpp index 155d4c0d..73dca6b2 100644 --- a/src/game-server/spawnarea.cpp +++ b/src/game-server/spawnarea.cpp @@ -25,18 +25,6 @@ #include "game-server/state.h" #include "utils/logger.h" -struct SpawnAreaEventDispatch : EventDispatch -{ - SpawnAreaEventDispatch() - { - typedef EventListenerFactory< SpawnArea, &SpawnArea::mSpawnedListener > - Factory; - removed = &Factory::create< Entity, &SpawnArea::decrease >::function; - } -}; - -static SpawnAreaEventDispatch spawnAreaEventDispatch; - SpawnArea::SpawnArea(MapComposite *map, MonsterClass *specy, const Rectangle &zone, @@ -44,7 +32,6 @@ SpawnArea::SpawnArea(MapComposite *map, int spawnRate): Entity(OBJECT_OTHER, map), mSpecy(specy), - mSpawnedListener(&spawnAreaEventDispatch), mZone(zone), mMaxBeings(maxBeings), mSpawnRate(spawnRate), @@ -102,7 +89,9 @@ void SpawnArea::update() if (c) { - being->addListener(&mSpawnedListener); + being->signal_removed.connect( + sigc::mem_fun(this, &SpawnArea::decrease)); + being->setMap(map); being->setPosition(position); being->clearDestination(); @@ -125,8 +114,7 @@ void SpawnArea::update() } } -void SpawnArea::decrease(Entity *t) +void SpawnArea::decrease(Entity *) { --mNumBeings; - t->removeListener(&mSpawnedListener); } diff --git a/src/game-server/spawnarea.h b/src/game-server/spawnarea.h index cc0642f1..628c072e 100644 --- a/src/game-server/spawnarea.h +++ b/src/game-server/spawnarea.h @@ -21,7 +21,6 @@ #ifndef SPAWNAREA_H #define SPAWNAREA_H -#include "game-server/eventlistener.h" #include "game-server/entity.h" #include "utils/point.h" @@ -47,7 +46,6 @@ class SpawnArea : public Entity private: MonsterClass *mSpecy; /**< Specy of monster that spawns in this area. */ - EventListener mSpawnedListener; /**< Tracking of spawned monsters. */ Rectangle mZone; int mMaxBeings; /**< Maximum population of this area. */ int mSpawnRate; /**< Number of beings spawning per minute. */ diff --git a/src/game-server/specialmanager.cpp b/src/game-server/specialmanager.cpp index 32669bca..39616faa 100644 --- a/src/game-server/specialmanager.cpp +++ b/src/game-server/specialmanager.cpp @@ -143,14 +143,14 @@ void SpecialManager::clear() mNamedSpecialsInfo.clear(); } -unsigned int SpecialManager::getId(const std::string &set, - const std::string &name) const +unsigned SpecialManager::getId(const std::string &set, + const std::string &name) const { std::string key = utils::toLower(set) + "_" + utils::toLower(name); return getId(key); } -unsigned int SpecialManager::getId(const std::string &specialName) const +unsigned SpecialManager::getId(const std::string &specialName) const { if (mNamedSpecialsInfo.contains(specialName)) return mNamedSpecialsInfo.value(specialName)->id; diff --git a/src/game-server/specialmanager.h b/src/game-server/specialmanager.h index b7a4f54b..e9203a34 100644 --- a/src/game-server/specialmanager.h +++ b/src/game-server/specialmanager.h @@ -48,12 +48,12 @@ public: target(TARGET_BEING) {} - unsigned int id; + unsigned id; std::string name; std::string setName; bool rechargeable; int defaultRechargeSpeed; - unsigned int neededMana; + unsigned neededMana; TargetMode target; Script::Ref rechargedCallback; Script::Ref useCallback; @@ -79,13 +79,13 @@ public: /** * Gets the specials Id from a set and a special string. */ - unsigned int getId(const std::string &set, const std::string &name) const; + unsigned getId(const std::string &set, const std::string &name) const; /** * Gets the specials Id from a string formatted in this way: * "setname_skillname" */ - unsigned int getId(const std::string &specialName) const; + unsigned getId(const std::string &specialName) const; const std::string getSpecialName(int id) const; const std::string getSetName(int id) const; @@ -102,7 +102,7 @@ private: const std::string &setName); std::string mSpecialFile; - typedef std::map<unsigned int, SpecialInfo*> SpecialsInfo; + typedef std::map<unsigned, SpecialInfo*> SpecialsInfo; SpecialsInfo mSpecialsInfo; typedef utils::NameMap<SpecialInfo*> NamedSpecialsInfo; NamedSpecialsInfo mNamedSpecialsInfo; diff --git a/src/game-server/state.cpp b/src/game-server/state.cpp index 249040a8..5353a236 100644 --- a/src/game-server/state.cpp +++ b/src/game-server/state.cpp @@ -84,11 +84,11 @@ static void serializeLooks(Character *ch, MessageOut &msg) // We'll use a set to check whether we already sent the update for the given // item instance. - std::set<unsigned int> itemInstances; + std::set<unsigned> itemInstances; // The map storing the info about the look changes to send //{ slot type id, item id } - std::map <unsigned int, unsigned int> lookChanges; + std::map <unsigned, unsigned> lookChanges; // Note that we can send several updates on the same slot type as different // items may have been equipped. @@ -105,8 +105,8 @@ static void serializeLooks(Character *ch, MessageOut &msg) // we encounter the item, so we can send the look change. // We also send empty slots for unequipment handling. lookChanges.insert( - std::make_pair<unsigned int, unsigned int>(it->first, - it->second.itemId)); + std::make_pair<unsigned, unsigned>(it->first, + it->second.itemId)); } } @@ -115,7 +115,7 @@ static void serializeLooks(Character *ch, MessageOut &msg) // Number of look changes to send msg.writeInt8(lookChanges.size()); - for (std::map<unsigned int, unsigned int>::const_iterator it2 = + for (std::map<unsigned, unsigned>::const_iterator it2 = lookChanges.begin(), it2_end = lookChanges.end(); it2 != it2_end; ++it2) { @@ -193,6 +193,19 @@ static void informPlayer(MapComposite *map, Character *p) gameHandler->sendTo(p, LooksMsg); } + // Send emote messages. + if (oflags & UPDATEFLAG_EMOTE) + { + int emoteId = o->getLastEmote(); + if (emoteId > -1) + { + MessageOut EmoteMsg(GPMSG_BEING_EMOTE); + EmoteMsg.writeInt16(oid); + EmoteMsg.writeInt16(emoteId); + gameHandler->sendTo(p, EmoteMsg); + } + } + // Send direction change messages. if (oflags & UPDATEFLAG_DIRCHANGE) { @@ -271,6 +284,7 @@ static void informPlayer(MapComposite *map, Character *p) default: assert(false); // TODO + break; } gameHandler->sendTo(p, enterMsg); } @@ -500,7 +514,7 @@ bool GameState::insert(Entity *ptr) if (!ptr->isVisible()) { map->insert(ptr); - ptr->inserted(); + ptr->signal_inserted.emit(ptr); return true; } @@ -525,7 +539,7 @@ bool GameState::insert(Entity *ptr) return false; } - obj->inserted(); + obj->signal_inserted.emit(obj); // DEBUG INFO switch (obj->getType()) @@ -558,6 +572,7 @@ bool GameState::insert(Entity *ptr) case OBJECT_OTHER: default: LOG_DEBUG("Entity inserted: " << obj->getType()); + break; } obj->raiseUpdateFlags(UPDATEFLAG_NEW_ON_MAP); @@ -598,7 +613,7 @@ void GameState::remove(Entity *ptr) MapComposite *map = ptr->getMap(); int visualRange = Configuration::getValue("game_visualRange", 448); - ptr->removed(); + ptr->signal_removed.emit(ptr); // DEBUG INFO switch (ptr->getType()) @@ -631,6 +646,7 @@ void GameState::remove(Entity *ptr) case OBJECT_OTHER: default: LOG_DEBUG("Entity removed: " << ptr->getType()); + break; } if (ptr->canMove()) diff --git a/src/game-server/trade.h b/src/game-server/trade.h index d425767a..43b674fb 100644 --- a/src/game-server/trade.h +++ b/src/game-server/trade.h @@ -101,7 +101,7 @@ class Trade TradedItems mItems1, mItems2; /**< Traded items. */ int mMoney1, mMoney2; /**< Traded money. */ TradeState mState; /**< State of transaction. */ - unsigned int mCurrencyId; /**< The attribute to use as currency. */ + unsigned mCurrencyId; /**< The attribute to use as currency. */ }; #endif |