diff options
author | Erik Schilling <ablu.erikschilling@googlemail.com> | 2013-04-06 21:36:50 +0200 |
---|---|---|
committer | Erik Schilling <ablu.erikschilling@googlemail.com> | 2013-04-11 13:43:00 +0200 |
commit | aa04597c5f8bb806996d604699fc8ebff6d53bdd (patch) | |
tree | 20e6a79a873605b62c80011fd5c80351f60df6fb /src | |
parent | d95fccfca8575d8fb06988e558a338e37776961a (diff) | |
download | manaserv-aa04597c5f8bb806996d604699fc8ebff6d53bdd.tar.gz manaserv-aa04597c5f8bb806996d604699fc8ebff6d53bdd.tar.bz2 manaserv-aa04597c5f8bb806996d604699fc8ebff6d53bdd.tar.xz manaserv-aa04597c5f8bb806996d604699fc8ebff6d53bdd.zip |
Converted the Character class into a component
A CharacterData was created as a proxy class in order to allow using the
old serialization method.
Diffstat (limited to 'src')
42 files changed, 1178 insertions, 760 deletions
diff --git a/src/account-server/character.h b/src/account-server/character.h index a6ac43ed..a9aa810b 100644 --- a/src/account-server/character.h +++ b/src/account-server/character.h @@ -47,6 +47,12 @@ struct AttributeValue double base; /**< Base value of the attribute. */ double modified; /**< Value after various modifiers have been applied. */ + + double getBase() const + { return base; } + + double getModifiedAttribute() const + { return modified; } }; struct SpecialValue @@ -62,6 +68,15 @@ struct SpecialValue unsigned currentMana; }; +struct Status +{ + Status() + : time(0) + {} + + unsigned time; +}; + /** * Stores attributes by their id. */ @@ -76,7 +91,7 @@ class CharacterData { public: - CharacterData(const std::string &name, int id = -1); + CharacterData(const std::string &name, int id = -1); /** * Gets the database id of the character. @@ -154,6 +169,9 @@ class CharacterData void setModAttribute(unsigned id, double value) { mAttributes[id].modified = value; } + const AttributeMap &getAttributes() const + { return mAttributes; } + int getSkillSize() const { return mExperience.size(); } @@ -176,15 +194,15 @@ class CharacterData * Get / Set a status effects */ void applyStatusEffect(int id, int time) - { mStatusEffects[id] = time; } + { mStatusEffects[id].time = time; } int getStatusEffectSize() const { return mStatusEffects.size(); } - const std::map<int, int>::const_iterator getStatusEffectBegin() const + const std::map<int, Status>::const_iterator getStatusEffectBegin() const { return mStatusEffects.begin(); } - const std::map<int, int>::const_iterator getStatusEffectEnd() const + const std::map<int, Status>::const_iterator getStatusEffectEnd() const { return mStatusEffects.end(); } /** @@ -283,7 +301,7 @@ class CharacterData Point mPos; //!< Position the being is at. AttributeMap mAttributes; //!< Attributes. std::map<int, int> mExperience; //!< Skill Experience. - std::map<int, int> mStatusEffects; //!< Status Effects + std::map<int, Status> mStatusEffects; //!< Status Effects std::map<int, int> mKillCount; //!< Kill Count SpecialMap mSpecials; unsigned short mMapId; //!< Map the being is on. @@ -299,9 +317,6 @@ class CharacterData //!< belongs to. friend class AccountHandler; friend class Storage; - // Set as a friend, but still a lot of redundant accessors. FIXME. - template< class T > - friend void serializeCharacterData(const T &data, MessageOut &msg); }; /** diff --git a/src/account-server/storage.cpp b/src/account-server/storage.cpp index 5275f0b0..dd8cf9ac 100644 --- a/src/account-server/storage.cpp +++ b/src/account-server/storage.cpp @@ -910,12 +910,12 @@ bool Storage::updateCharacter(CharacterData *character) } try { - std::map<int, int>::const_iterator status_it; + std::map<int, Status>::const_iterator status_it; for (status_it = character->getStatusEffectBegin(); status_it != character->getStatusEffectEnd(); status_it++) { insertStatusEffect(character->getDatabaseID(), - status_it->first, status_it->second); + status_it->first, status_it->second.time); } } catch (const dal::DbSqlQueryExecFailure& e) diff --git a/src/common/permissionmanager.cpp b/src/common/permissionmanager.cpp index 5510fd7c..ee970bd9 100644 --- a/src/common/permissionmanager.cpp +++ b/src/common/permissionmanager.cpp @@ -105,9 +105,10 @@ void PermissionManager::reload() } -PermissionManager::Result PermissionManager::checkPermission(const Character* character, std::string permission) +PermissionManager::Result PermissionManager::checkPermission(const Being* character, std::string permission) { - return checkPermission(character->getAccountLevel(), permission); + return checkPermission(character->getComponent<CharacterComponent>() + ->getAccountLevel(), permission); } PermissionManager::Result PermissionManager::checkPermission(unsigned char level, std::string permission) @@ -139,12 +140,13 @@ unsigned char PermissionManager::getMaskFromAlias(const std::string &alias) } } -std::list<std::string> PermissionManager::getPermissionList(const Character* character) +std::list<std::string> PermissionManager::getPermissionList(const Being* character) { std::list<std::string> result; std::map<std::string, unsigned char>::iterator i; - unsigned char mask = character->getAccountLevel(); + unsigned char mask = character->getComponent<CharacterComponent>() + ->getAccountLevel(); for (i = permissions.begin(); i != permissions.end(); i++) { @@ -157,12 +159,13 @@ std::list<std::string> PermissionManager::getPermissionList(const Character* cha return result; } -std::list<std::string> PermissionManager::getClassList(const Character* character) +std::list<std::string> PermissionManager::getClassList(const Being* character) { std::list<std::string> result; std::map<std::string, unsigned char>::iterator i; - unsigned char mask = character->getAccountLevel(); + unsigned char mask = character->getComponent<CharacterComponent>() + ->getAccountLevel(); for (i = aliases.begin(); i != aliases.end(); i++) { diff --git a/src/common/permissionmanager.h b/src/common/permissionmanager.h index bf36f658..a78f581d 100644 --- a/src/common/permissionmanager.h +++ b/src/common/permissionmanager.h @@ -25,7 +25,7 @@ #include <map> #include <string> -class Character; +class Being; namespace PermissionManager { @@ -48,7 +48,7 @@ namespace PermissionManager /** * Returns if the characters account has the given permission */ - Result checkPermission(const Character* character, std::string permission); + Result checkPermission(const Being* character, std::string permission); Result checkPermission(unsigned char level, std::string permission); /** @@ -59,12 +59,12 @@ namespace PermissionManager /** * Gets a list of all permissions the character is having */ - std::list<std::string> getPermissionList(const Character* character); + std::list<std::string> getPermissionList(const Being* character); /** * Gets a list of all permissions classes the character is having */ - std::list<std::string> getClassList(const Character* character); + std::list<std::string> getClassList(const Being* character); } // namespace PermissionManager diff --git a/src/game-server/accountconnection.cpp b/src/game-server/accountconnection.cpp index 44858fcd..bdf44b4e 100644 --- a/src/game-server/accountconnection.cpp +++ b/src/game-server/accountconnection.cpp @@ -102,11 +102,12 @@ bool AccountConnection::start(int gameServerPort) return true; } -void AccountConnection::sendCharacterData(Character *p) +void AccountConnection::sendCharacterData(Entity *p) { MessageOut msg(GAMSG_PLAYER_DATA); - msg.writeInt32(p->getDatabaseID()); - serializeCharacterData(*p, msg); + auto *characterComponent = p->getComponent<CharacterComponent>(); + msg.writeInt32(characterComponent->getDatabaseID()); + serializeCharacterData(*characterComponent->getCharacterData(), msg); send(msg); } @@ -154,8 +155,9 @@ void AccountConnection::processMessage(MessageIn &msg) case AGMSG_PLAYER_ENTER: { std::string token = msg.readString(MAGIC_TOKEN_LENGTH); - Character *ptr = new Character(msg); - gameHandler->addPendingCharacter(token, ptr); + Being *character = new Being(OBJECT_CHARACTER); + character->addComponent(new CharacterComponent(*character, msg)); + gameHandler->addPendingCharacter(token, character); } break; case AGMSG_ACTIVE_MAP: @@ -241,7 +243,7 @@ void AccountConnection::processMessage(MessageIn &msg) case CGMSG_POST_RESPONSE: { // get the character - Character *character = postMan->getCharacter(msg.readInt32()); + Being *character = postMan->getCharacter(msg.readInt32()); // check character is still valid if (!character) @@ -259,7 +261,7 @@ void AccountConnection::processMessage(MessageIn &msg) case CGMSG_STORE_POST_RESPONSE: { // get character - Character *character = postMan->getCharacter(msg.readInt32()); + Being *character = postMan->getCharacter(msg.readInt32()); // check character is valid if (!character) @@ -288,21 +290,21 @@ void AccountConnection::playerReconnectAccount(int id, send(msg); } -void AccountConnection::requestCharacterVar(Character *ch, +void AccountConnection::requestCharacterVar(Entity *ch, const std::string &name) { MessageOut msg(GAMSG_GET_VAR_CHR); - msg.writeInt32(ch->getDatabaseID()); + msg.writeInt32(ch->getComponent<CharacterComponent>()->getDatabaseID()); msg.writeString(name); send(msg); } -void AccountConnection::updateCharacterVar(Character *ch, +void AccountConnection::updateCharacterVar(Entity *ch, const std::string &name, const std::string &value) { MessageOut msg(GAMSG_SET_VAR_CHR); - msg.writeInt32(ch->getDatabaseID()); + msg.writeInt32(ch->getComponent<CharacterComponent>()->getDatabaseID()); msg.writeString(name); msg.writeString(value); send(msg); @@ -328,10 +330,10 @@ void AccountConnection::updateWorldVar(const std::string &name, send(msg); } -void AccountConnection::banCharacter(Character *ch, int duration) +void AccountConnection::banCharacter(Entity *ch, int duration) { MessageOut msg(GAMSG_BAN_PLAYER); - msg.writeInt32(ch->getDatabaseID()); + msg.writeInt32(ch->getComponent<CharacterComponent>()->getDatabaseID()); msg.writeInt32(duration); send(msg); } @@ -357,9 +359,12 @@ void AccountConnection::sendStatistics() switch (t->getType()) { case OBJECT_CHARACTER: - players.push_back - (static_cast< Character * >(t)->getDatabaseID()); + { + auto *characterComponent = + t->getComponent<CharacterComponent>(); + players.push_back(characterComponent->getDatabaseID()); break; + } case OBJECT_MONSTER: ++nbMonsters; break; @@ -379,13 +384,13 @@ void AccountConnection::sendStatistics() send(msg); } -void AccountConnection::sendPost(Character *c, MessageIn &msg) +void AccountConnection::sendPost(Entity *c, MessageIn &msg) { // send message to account server with id of sending player, // the id of receiving player, the letter receiver and contents, and attachments LOG_DEBUG("Sending GCMSG_STORE_POST."); MessageOut out(GCMSG_STORE_POST); - out.writeInt32(c->getDatabaseID()); + out.writeInt32(c->getComponent<CharacterComponent>()->getDatabaseID()); out.writeString(msg.readString()); // name of receiver out.writeString(msg.readString()); // content of letter while (msg.getUnreadLength()) // attachments @@ -397,7 +402,7 @@ void AccountConnection::sendPost(Character *c, MessageIn &msg) send(out); } -void AccountConnection::getPost(Character *c) +void AccountConnection::getPost(Entity *c) { // let the postman know to expect some post for this character postMan->addCharacter(c); @@ -405,14 +410,14 @@ void AccountConnection::getPost(Character *c) // send message to account server with id of retrieving player LOG_DEBUG("Sending GCMSG_REQUEST_POST"); MessageOut out(GCMSG_REQUEST_POST); - out.writeInt32(c->getDatabaseID()); + out.writeInt32(c->getComponent<CharacterComponent>()->getDatabaseID()); send(out); } -void AccountConnection::changeAccountLevel(Character *c, int level) +void AccountConnection::changeAccountLevel(Entity *c, int level) { MessageOut msg(GAMSG_CHANGE_ACCOUNT_LEVEL); - msg.writeInt32(c->getDatabaseID()); + msg.writeInt32(c->getComponent<CharacterComponent>()->getDatabaseID()); msg.writeInt16(level); send(msg); } diff --git a/src/game-server/accountconnection.h b/src/game-server/accountconnection.h index a144a1d1..2ad79dd2 100644 --- a/src/game-server/accountconnection.h +++ b/src/game-server/accountconnection.h @@ -24,7 +24,7 @@ #include "net/messageout.h" #include "net/connection.h" -class Character; +class Entity; class MapComposite; /** @@ -45,7 +45,7 @@ class AccountConnection : public Connection /** * Sends data of a given character. */ - void sendCharacterData(Character *); + void sendCharacterData(Entity *); /** * Prepares the account server for a reconnecting player @@ -55,19 +55,19 @@ class AccountConnection : public Connection /** * Requests the value of a character-bound variable from the database. */ - void requestCharacterVar(Character *, const std::string &); + void requestCharacterVar(Entity *, const std::string &); /** * Pushes a new character-bound value to the database. */ - void updateCharacterVar(Character *, const std::string &name, - const std::string &value); + void updateCharacterVar(Entity *, const std::string &name, + const std::string &value); /** * Pushes a new value of a map variable to the account server. */ void updateMapVar(MapComposite *, const std::string &name, - const std::string &value); + const std::string &value); /** * Pushes a new value of a world variable to the account server. @@ -78,7 +78,7 @@ class AccountConnection : public Connection /** * Sends ban message. */ - void banCharacter(Character *, int); + void banCharacter(Entity *, int); /** * Gathers statistics and sends them. @@ -88,17 +88,17 @@ class AccountConnection : public Connection /** * Send letter */ - void sendPost(Character *, MessageIn &); + void sendPost(Entity *, MessageIn &); /** * Get post */ - void getPost(Character *); + void getPost(Entity *); /** * Change Account Level */ - void changeAccountLevel(Character *, int); + void changeAccountLevel(Entity *, int); /** * Sends all changed player data to the account server to minimize diff --git a/src/game-server/attack.cpp b/src/game-server/attack.cpp index a1300e4d..6ca85fb8 100644 --- a/src/game-server/attack.cpp +++ b/src/game-server/attack.cpp @@ -72,13 +72,13 @@ AttackInfo *AttackInfo::readAttackNode(xmlNodePtr node) return attack; } -void Attacks::add(AttackInfo *attackInfo) +void Attacks::add(CombatComponent *combatComponent, AttackInfo *attackInfo) { mAttacks.push_back(Attack(attackInfo)); - attack_added.emit(*mAttacks.rbegin()); + attack_added.emit(combatComponent, *mAttacks.rbegin()); } -void Attacks::remove(AttackInfo *attackInfo) +void Attacks::remove(CombatComponent *combatComponent, AttackInfo *attackInfo) { for (std::vector<Attack>::iterator it = mAttacks.begin(), it_end = mAttacks.end(); it != it_end; ++it) @@ -87,7 +87,7 @@ void Attacks::remove(AttackInfo *attackInfo) { if (mCurrentAttack && mCurrentAttack->getAttackInfo() == attackInfo) mCurrentAttack = 0; - attack_removed.emit(*it); + attack_removed.emit(combatComponent, *it); mAttacks.erase(it); return; } diff --git a/src/game-server/attack.h b/src/game-server/attack.h index cecb4fd5..348a94bb 100644 --- a/src/game-server/attack.h +++ b/src/game-server/attack.h @@ -35,6 +35,8 @@ #include "game-server/timeout.h" +class CombatComponent; + /** * Structure that describes the severity and nature of an attack a being can * be hit by. @@ -68,7 +70,7 @@ struct Damage * Class that stores information about an auto-attack */ -class Character; +class CharacterComponent; struct AttackInfo { @@ -178,8 +180,8 @@ class Attacks : public sigc::trackable mCurrentAttack(0) {} - void add(AttackInfo *); - void remove(AttackInfo *); + void add(CombatComponent *combatComponent, AttackInfo *); + void remove(CombatComponent *combatComponent, AttackInfo *); void markAttackAsTriggered(); Attack *getTriggerableAttack(); void startAttack(Attack *attack); @@ -191,8 +193,8 @@ class Attacks : public sigc::trackable unsigned getNumber() { return mAttacks.size(); } - sigc::signal<void, Attack &> attack_added; - sigc::signal<void, Attack &> attack_removed; + sigc::signal<void, CombatComponent *, Attack &> attack_added; + sigc::signal<void, CombatComponent *, Attack &> attack_removed; private: std::vector<Attack> mAttacks; diff --git a/src/game-server/being.cpp b/src/game-server/being.cpp index 2237f6a6..b50a5fac 100644 --- a/src/game-server/being.cpp +++ b/src/game-server/being.cpp @@ -483,6 +483,8 @@ void Being::recalculateBaseAttribute(unsigned attr) void Being::updateDerivedAttributes(unsigned attr) { + signal_attribute_changed.emit(this, attr); + LOG_DEBUG("Being: Updating derived attribute(s) of: " << attr); // Handle default actions before handing over to the script engine diff --git a/src/game-server/being.h b/src/game-server/being.h index 41be5fff..de30ad60 100644 --- a/src/game-server/being.h +++ b/src/game-server/being.h @@ -153,6 +153,9 @@ class Being : public Actor */ const Attribute *getAttribute(unsigned id) const; + const AttributeMap &getAttributes() const + { return mAttributes; } + /** * Gets an attribute base. */ @@ -197,14 +200,14 @@ class Being : public Actor * attributes if it has changed. * @returns Whether it was changed. */ - virtual void recalculateBaseAttribute(unsigned); + void recalculateBaseAttribute(unsigned); /** * Attribute has changed, recalculate base value of dependant * attributes (and handle other actions for the modified * attribute) */ - virtual void updateDerivedAttributes(unsigned); + void updateDerivedAttributes(unsigned); /** * Sets a statuseffect on this being @@ -221,6 +224,9 @@ class Being : public Actor */ bool hasStatusEffect(int id) const; + const StatusEffects &getStatusEffects() const + { return mStatus; } + /** * Returns the time of the status effect if in effect, or 0 if not */ @@ -251,6 +257,7 @@ class Being : public Actor { script->assignCallback(mRecalculateBaseAttributeCallback); } sigc::signal<void, Being *> signal_died; + sigc::signal<void, Being *, unsigned> signal_attribute_changed; /** * Activate an emote flag on the being. diff --git a/src/game-server/buysell.cpp b/src/game-server/buysell.cpp index 1e63d523..e73e13c5 100644 --- a/src/game-server/buysell.cpp +++ b/src/game-server/buysell.cpp @@ -30,15 +30,15 @@ #include <algorithm> -BuySell::BuySell(Character *c, bool sell): +BuySell::BuySell(Being *c, bool sell): mCurrencyId(ATTR_GP), mChar(c), mSell(sell) { - c->setBuySell(this); + c->getComponent<CharacterComponent>()->setBuySell(this); } BuySell::~BuySell() { - mChar->setBuySell(NULL); + mChar->getComponent<CharacterComponent>()->setBuySell(nullptr); } void BuySell::cancel() @@ -75,7 +75,9 @@ int BuySell::registerPlayerItems() // We parse the player inventory and add all item // in a sell list. - const InventoryData &inventoryData = mChar->getPossessions().getInventory(); + auto *component = mChar->getComponent<CharacterComponent>(); + const InventoryData &inventoryData = + component->getPossessions().getInventory(); for (InventoryData::const_iterator it = inventoryData.begin(), it_end = inventoryData.end(); it != it_end; ++it) { @@ -144,7 +146,7 @@ bool BuySell::start(Actor *actor) msg.writeInt16(i->amount); msg.writeInt16(i->cost); } - mChar->getClient()->send(msg); + mChar->getComponent<CharacterComponent>()->getClient()->send(msg); return true; } diff --git a/src/game-server/buysell.h b/src/game-server/buysell.h index 72da2ce6..8450aff1 100644 --- a/src/game-server/buysell.h +++ b/src/game-server/buysell.h @@ -23,7 +23,7 @@ #include <vector> -class Character; +class Being; class Actor; class BuySell @@ -33,7 +33,7 @@ class BuySell /** * Sets up a trade between a character and an NPC. */ - BuySell(Character *, bool sell); + BuySell(Being *, bool sell); /** * Cancels the trade. @@ -80,7 +80,7 @@ class BuySell /** The attribute ID of the currency to use. Hardcoded for now (FIXME) */ unsigned mCurrencyId; - Character *mChar; /**< Character involved. */ + Being *mChar; /**< Character involved. */ TradedItems mItems; /**< Traded items. */ bool mSell; /**< Are items sold? */ }; diff --git a/src/game-server/character.cpp b/src/game-server/character.cpp index e52747fd..63621491 100644 --- a/src/game-server/character.cpp +++ b/src/game-server/character.cpp @@ -49,30 +49,29 @@ #include <limits.h> // Experience curve related values -const float Character::EXPCURVE_EXPONENT = 3.0f; -const float Character::EXPCURVE_FACTOR = 10.0f; -const float Character::LEVEL_SKILL_PRECEDENCE_FACTOR = 0.75f; -const float Character::EXP_LEVEL_FLEXIBILITY = 1.0f; +const float CharacterComponent::EXPCURVE_EXPONENT = 3.0f; +const float CharacterComponent::EXPCURVE_FACTOR = 10.0f; +const float CharacterComponent::LEVEL_SKILL_PRECEDENCE_FACTOR = 0.75f; +const float CharacterComponent::EXP_LEVEL_FLEXIBILITY = 1.0f; -Script::Ref Character::mDeathCallback; -Script::Ref Character::mDeathAcceptedCallback; -Script::Ref Character::mLoginCallback; +Script::Ref CharacterComponent::mDeathCallback; +Script::Ref CharacterComponent::mDeathAcceptedCallback; +Script::Ref CharacterComponent::mLoginCallback; -static bool executeCallback(Script::Ref function, Character *character) +static bool executeCallback(Script::Ref function, Entity &entity) { if (!function.isValid()) return false; Script *script = ScriptManager::currentState(); script->prepare(function); - script->push(character); - script->execute(character->getMap()); + script->push(&entity); + script->execute(entity.getMap()); return true; } -Character::Character(MessageIn &msg): - Being(OBJECT_CHARACTER), +CharacterComponent::CharacterComponent(Entity &entity, MessageIn &msg): mClient(NULL), mConnected(true), mTransactionHandler(NULL), @@ -88,29 +87,35 @@ Character::Character(MessageIn &msg): mTransaction(TRANS_NONE), mTalkNpcId(0), mNpcThread(0), - mKnuckleAttackInfo(0) + mKnuckleAttackInfo(0), + mBaseEntity(&entity) { - const AttributeManager::AttributeScope &attr = + // Temporary until all dependencies are in a component + Being &being = static_cast<Being &>(entity); + + mCharacterData = new CharacterData(&being, this); + + const AttributeManager::AttributeScope &attributes = attributeManager->getAttributeScope(CharacterScope); LOG_DEBUG("Character creation: initialisation of " - << attr.size() << " attributes."); - for (AttributeManager::AttributeScope::const_iterator it1 = attr.begin(), - it1_end = attr.end(); it1 != it1_end; ++it1) - mAttributes.insert(std::make_pair(it1->first, Attribute(*it1->second))); + << attributes.size() << " attributes."); + for (auto attributeScope : attributes) + being.createAttribute(attributeScope.first, *attributeScope.second); + - setWalkMask(Map::BLOCKMASK_WALL); - setBlockType(BLOCKTYPE_CHARACTER); + being.setWalkMask(Map::BLOCKMASK_WALL); + being.setBlockType(BLOCKTYPE_CHARACTER); - CombatComponent *combatcomponent = new CombatComponent(*this); - addComponent(combatcomponent); + CombatComponent *combatcomponent = new CombatComponent(being); + entity.addComponent(combatcomponent); combatcomponent->getAttacks().attack_added.connect( - sigc::mem_fun(this, &Character::attackAdded)); + sigc::mem_fun(this, &CharacterComponent::attackAdded)); combatcomponent->getAttacks().attack_removed.connect( - sigc::mem_fun(this, &Character::attackRemoved)); + sigc::mem_fun(this, &CharacterComponent::attackRemoved)); // Default knuckle attack - int damageBase = this->getModifiedAttribute(ATTR_STR); + int damageBase = being.getModifiedAttribute(ATTR_STR); int damageDelta = damageBase / 2; Damage knuckleDamage; knuckleDamage.skill = skillManager->getDefaultSkillId(); @@ -126,34 +131,38 @@ Character::Character(MessageIn &msg): // Get character data. mDatabaseID = msg.readInt32(); - setName(msg.readString()); - deserializeCharacterData(*this, msg); - mOld = getPosition(); - Inventory(this).initialize(); - modifiedAllAttribute(); - setSize(16); + being.setName(msg.readString()); + + deserializeCharacterData(*mCharacterData, msg); + + Inventory(&being, mPossessions).initialize(); + modifiedAllAttributes(entity); + being.setSize(16); + + being.signal_attribute_changed.connect(sigc::mem_fun( + this, &CharacterComponent::attributeChanged)); } -Character::~Character() +CharacterComponent::~CharacterComponent() { delete mNpcThread; delete mKnuckleAttackInfo; } -void Character::update() +void CharacterComponent::update(Entity &entity) { - // First, deal with being generic updates - Being::update(); + // Temporary until all dependencies are available as component + Being &being = static_cast<Being &>(entity); // Update character level if needed. if (mRecalculateLevel) { mRecalculateLevel = false; - recalculateLevel(); + recalculateLevel(entity); } // Dead character: don't regenerate anything else - if (getAction() == DEAD) + if (being.getAction() == DEAD) return; // Update special recharge @@ -169,9 +178,9 @@ void Character::update() { Script *script = ScriptManager::currentState(); script->prepare(s.specialInfo->rechargedCallback); - script->push(this); + script->push(&entity); script->push(s.specialInfo->id); - script->execute(getMap()); + script->execute(entity.getMap()); } } } @@ -181,53 +190,46 @@ void Character::update() sendSpecialUpdate(); mSpecialUpdateNeeded = false; } - - mStatusEffects.clear(); - StatusEffects::iterator it = mStatus.begin(); - while (it != mStatus.end()) - { - mStatusEffects[it->first] = it->second.time; - it++; - } } -void Character::died() +void CharacterComponent::characterDied(Being *being) { - Being::died(); - executeCallback(mDeathCallback, this); + executeCallback(mDeathCallback, *being); } -void Character::respawn() +void CharacterComponent::respawn(Entity &entity) { - if (mAction != DEAD) + // Temporary until all dependencies are available as component + Being &being = static_cast<Being &>(entity); + + if (being.getAction() != DEAD) { - LOG_WARN("Character \"" << getName() + LOG_WARN("Character \"" << being.getName() << "\" tried to respawn without being dead"); return; } // Make it alive again - setAction(STAND); + being.setAction(STAND); // Reset target - getComponent<CombatComponent>()->clearTarget(); + entity.getComponent<CombatComponent>()->clearTarget(); // Execute respawn callback when set - if (executeCallback(mDeathAcceptedCallback, this)) + if (executeCallback(mDeathAcceptedCallback, entity)) return; // No script respawn callback set - fall back to hardcoded logic - mAttributes[ATTR_HP].setBase(mAttributes[ATTR_MAX_HP].getModifiedAttribute()); - updateDerivedAttributes(ATTR_HP); + being.setAttribute(ATTR_HP, being.getModifiedAttribute(ATTR_MAX_HP)); // Warp back to spawn point. int spawnMap = Configuration::getValue("char_respawnMap", 1); int spawnX = Configuration::getValue("char_respawnX", 1024); int spawnY = Configuration::getValue("char_respawnY", 1024); - GameState::enqueueWarp(this, MapManager::getMap(spawnMap), + GameState::enqueueWarp(&being, MapManager::getMap(spawnMap), Point(spawnX, spawnY)); } -bool Character::specialUseCheck(SpecialMap::iterator it) +bool CharacterComponent::specialUseCheck(SpecialMap::iterator it) { if (it == mSpecials.end()) { @@ -257,7 +259,7 @@ bool Character::specialUseCheck(SpecialMap::iterator it) return true; } -void Character::useSpecialOnBeing(int id, Being *b) +void CharacterComponent::useSpecialOnBeing(Entity &user, int id, Being *b) { SpecialMap::iterator it = mSpecials.find(id); if (!specialUseCheck(it)) @@ -270,13 +272,13 @@ void Character::useSpecialOnBeing(int id, Being *b) //tell script engine to cast the spell Script *script = ScriptManager::currentState(); script->prepare(special.specialInfo->useCallback); - script->push(this); + script->push(&user); script->push(b); script->push(special.specialInfo->id); - script->execute(getMap()); + script->execute(user.getMap()); } -void Character::useSpecialOnPoint(int id, int x, int y) +void CharacterComponent::useSpecialOnPoint(Entity &user, int id, int x, int y) { SpecialMap::iterator it = mSpecials.find(id); if (!specialUseCheck(it)) @@ -289,14 +291,14 @@ void Character::useSpecialOnPoint(int id, int x, int y) //tell script engine to cast the spell Script *script = ScriptManager::currentState(); script->prepare(special.specialInfo->useCallback); - script->push(this); + script->push(&user); script->push(x); script->push(y); script->push(special.specialInfo->id); - script->execute(getMap()); + script->execute(user.getMap()); } -bool Character::giveSpecial(int id, int currentMana) +bool CharacterComponent::giveSpecial(int id, int currentMana) { if (mSpecials.find(id) == mSpecials.end()) { @@ -315,7 +317,7 @@ bool Character::giveSpecial(int id, int currentMana) return false; } -bool Character::setSpecialMana(int id, int mana) +bool CharacterComponent::setSpecialMana(int id, int mana) { SpecialMap::iterator it = mSpecials.find(id); if (it != mSpecials.end()) @@ -327,7 +329,7 @@ bool Character::setSpecialMana(int id, int mana) return false; } -bool Character::setSpecialRechargeSpeed(int id, int speed) +bool CharacterComponent::setSpecialRechargeSpeed(int id, int speed) { SpecialMap::iterator it = mSpecials.find(id); if (it != mSpecials.end()) @@ -339,7 +341,7 @@ bool Character::setSpecialRechargeSpeed(int id, int speed) return false; } -void Character::sendSpecialUpdate() +void CharacterComponent::sendSpecialUpdate() { //GPMSG_SPECIAL_STATUS = 0x0293, // { B specialID, L current, L max, L recharge } @@ -353,20 +355,10 @@ void Character::sendSpecialUpdate() msg.writeInt32(it->second.specialInfo->neededMana); msg.writeInt32(it->second.rechargeSpeed); } - gameHandler->sendTo(this, msg); + gameHandler->sendTo(mClient, msg); } -int Character::getMapId() const -{ - return getMap()->getID(); -} - -void Character::setMapId(int id) -{ - setMap(MapManager::getMap(id)); -} - -void Character::cancelTransaction() +void CharacterComponent::cancelTransaction() { TransactionType t = mTransaction; mTransaction = TRANS_NONE; @@ -383,19 +375,19 @@ void Character::cancelTransaction() } } -Trade *Character::getTrading() const +Trade *CharacterComponent::getTrading() const { return mTransaction == TRANS_TRADE ? static_cast< Trade * >(mTransactionHandler) : NULL; } -BuySell *Character::getBuySell() const +BuySell *CharacterComponent::getBuySell() const { return mTransaction == TRANS_BUYSELL ? static_cast< BuySell * >(mTransactionHandler) : NULL; } -void Character::setTrading(Trade *t) +void CharacterComponent::setTrading(Trade *t) { if (t) { @@ -410,7 +402,7 @@ void Character::setTrading(Trade *t) } } -void Character::setBuySell(BuySell *t) +void CharacterComponent::setBuySell(BuySell *t) { if (t) { @@ -425,18 +417,21 @@ void Character::setBuySell(BuySell *t) } } -void Character::sendStatus() +void CharacterComponent::sendStatus(Entity &entity) { + // Temporary until all dependencies are available as components + Being &being = static_cast<Being &>(entity); + MessageOut attribMsg(GPMSG_PLAYER_ATTRIBUTE_CHANGE); for (std::set<size_t>::const_iterator i = mModifiedAttributes.begin(), i_end = mModifiedAttributes.end(); i != i_end; ++i) { int attr = *i; attribMsg.writeInt16(attr); - attribMsg.writeInt32(getAttributeBase(attr) * 256); - attribMsg.writeInt32(getModifiedAttribute(attr) * 256); + attribMsg.writeInt32(being.getAttributeBase(attr) * 256); + attribMsg.writeInt32(being.getModifiedAttribute(attr) * 256); } - if (attribMsg.getLength() > 2) gameHandler->sendTo(this, attribMsg); + if (attribMsg.getLength() > 2) gameHandler->sendTo(mClient, attribMsg); mModifiedAttributes.clear(); MessageOut expMsg(GPMSG_PLAYER_EXP_CHANGE); @@ -449,7 +444,7 @@ void Character::sendStatus() expMsg.writeInt32(getExpNeeded(skill)); expMsg.writeInt16(levelForExp(getExperience(skill))); } - if (expMsg.getLength() > 2) gameHandler->sendTo(this, expMsg); + if (expMsg.getLength() > 2) gameHandler->sendTo(mClient, expMsg); mModifiedExperience.clear(); if (mUpdateLevelProgress) @@ -457,73 +452,52 @@ void Character::sendStatus() mUpdateLevelProgress = false; MessageOut progressMessage(GPMSG_LEVEL_PROGRESS); progressMessage.writeInt8(mLevelProgress); - gameHandler->sendTo(this, progressMessage); + gameHandler->sendTo(mClient, progressMessage); } } -void Character::modifiedAllAttribute() +void CharacterComponent::modifiedAllAttributes(Entity &entity) { + // Temporary until all dependencies are available as components + Being &being = static_cast<Being &>(entity); + LOG_DEBUG("Marking all attributes as changed, requiring recalculation."); - for (AttributeMap::iterator it = mAttributes.begin(), - it_end = mAttributes.end(); - it != it_end; ++it) + for (auto attribute : being.getAttributes()) { - recalculateBaseAttribute(it->first); - updateDerivedAttributes(it->first); + being.recalculateBaseAttribute(attribute.first); + mModifiedAttributes.insert(attribute.first); } } -void Character::recalculateBaseAttribute(unsigned attr) +void CharacterComponent::attributeChanged(Being *being, unsigned attr) { - // `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; + // Inform the client of this attribute modification. + accountHandler->updateAttributes(getDatabaseID(), attr, + being->getAttributeBase(attr), + being->getModifiedAttribute(attr)); + mModifiedAttributes.insert(attr); + // Update the knuckle Attack if required if (attr == ATTR_STR && mKnuckleAttackInfo) { // TODO: dehardcode this Damage &knuckleDamage = mKnuckleAttackInfo->getDamage(); - knuckleDamage.base = getModifiedAttribute(ATTR_STR); + knuckleDamage.base = being->getModifiedAttribute(ATTR_STR); knuckleDamage.delta = knuckleDamage.base / 2; } - Being::recalculateBaseAttribute(attr); - -} - - -void Character::updateDerivedAttributes(unsigned attr) -{ - /* - * `attr' has changed, perform updates accordingly. - */ - flagAttribute(attr); - - - Being::updateDerivedAttributes(attr); } -void Character::flagAttribute(int attr) -{ - // Inform the client of this attribute modification. - accountHandler->updateAttributes(getDatabaseID(), attr, - getAttributeBase(attr), - getModifiedAttribute(attr)); - mModifiedAttributes.insert(attr); -} - -int Character::expForLevel(int level) +int CharacterComponent::expForLevel(int level) { return int(pow(level, EXPCURVE_EXPONENT) * EXPCURVE_FACTOR); } -int Character::levelForExp(int exp) +int CharacterComponent::levelForExp(int exp) { return int(pow(float(exp) / EXPCURVE_FACTOR, 1.0f / EXPCURVE_EXPONENT)); } -void Character::receiveExperience(int skill, int experience, int optimalLevel) +void CharacterComponent::receiveExperience(int skill, int experience, int optimalLevel) { // reduce experience when skill is over optimal level int levelOverOptimum = levelForExp(getExperience(skill)) - optimalLevel; @@ -562,7 +536,7 @@ void Character::receiveExperience(int skill, int experience, int optimalLevel) mRecalculateLevel = true; } -void Character::incrementKillCount(int monsterType) +void CharacterComponent::incrementKillCount(int monsterType) { std::map<int, int>::iterator i = mKillCount.find(monsterType); if (i == mKillCount.end()) @@ -577,7 +551,7 @@ void Character::incrementKillCount(int monsterType) } } -int Character::getKillCount(int monsterType) const +int CharacterComponent::getKillCount(int monsterType) const { std::map<int, int>::const_iterator i = mKillCount.find(monsterType); if (i != mKillCount.end()) @@ -586,7 +560,7 @@ int Character::getKillCount(int monsterType) const } -void Character::recalculateLevel() +void CharacterComponent::recalculateLevel(Entity &entity) { std::list<float> levels; std::map<int, int>::const_iterator a; @@ -618,7 +592,7 @@ void Character::recalculateLevel() while (mLevel < level) { - levelup(); + levelup(entity); } int levelProgress = int((level - floor(level)) * 100); @@ -629,20 +603,23 @@ void Character::recalculateLevel() } } -int Character::getExpNeeded(size_t skill) const +int CharacterComponent::getExpNeeded(size_t skill) const { int level = levelForExp(getExperience(skill)); - return Character::expForLevel(level + 1) - expForLevel(level); + return CharacterComponent::expForLevel(level + 1) - expForLevel(level); } -int Character::getExpGot(size_t skill) const +int CharacterComponent::getExpGot(size_t skill) const { int level = levelForExp(getExperience(skill)); - return mExperience.at(skill) - Character::expForLevel(level); + return mExperience.at(skill) - CharacterComponent::expForLevel(level); } -void Character::levelup() +void CharacterComponent::levelup(Entity &entity) { + // Temporary until all dependencies are available as Component + Being &being = static_cast<Being &>(entity); + mLevel++; mCharacterPoints += CHARPOINTS_PER_LEVELUP; @@ -654,40 +631,47 @@ void Character::levelup() levelupMsg.writeInt16(mLevel); levelupMsg.writeInt16(mCharacterPoints); levelupMsg.writeInt16(mCorrectionPoints); - gameHandler->sendTo(this, levelupMsg); - LOG_INFO(getName()<<" reached level "<<mLevel); + gameHandler->sendTo(mClient, levelupMsg); + LOG_INFO(being.getName() << " reached level " << mLevel); } -AttribmodResponseCode Character::useCharacterPoint(size_t attribute) +AttribmodResponseCode CharacterComponent::useCharacterPoint(Entity &entity, + size_t attribute) { + // Temporary until all dependencies are available as Component + Being &being = static_cast<Being &>(entity); + if (!attributeManager->isAttributeDirectlyModifiable(attribute)) return ATTRIBMOD_INVALID_ATTRIBUTE; if (!mCharacterPoints) return ATTRIBMOD_NO_POINTS_LEFT; --mCharacterPoints; - setAttribute(attribute, getAttributeBase(attribute) + 1); - updateDerivedAttributes(attribute); + being.setAttribute(attribute, being.getAttributeBase(attribute) + 1); + being.updateDerivedAttributes(attribute); return ATTRIBMOD_OK; } -AttribmodResponseCode Character::useCorrectionPoint(size_t attribute) +AttribmodResponseCode CharacterComponent::useCorrectionPoint(Entity &entity, + size_t attribute) { + // Temporary until all dependencies are available as Component + Being &being = static_cast<Being &>(entity); + if (!attributeManager->isAttributeDirectlyModifiable(attribute)) return ATTRIBMOD_INVALID_ATTRIBUTE; if (!mCorrectionPoints) return ATTRIBMOD_NO_POINTS_LEFT; - if (getAttributeBase(attribute) <= 1) + if (being.getAttributeBase(attribute) <= 1) return ATTRIBMOD_DENIED; --mCorrectionPoints; ++mCharacterPoints; - setAttribute(attribute, getAttributeBase(attribute) - 1); - updateDerivedAttributes(attribute); + being.setAttribute(attribute, being.getAttributeBase(attribute) - 1); return ATTRIBMOD_OK; } -void Character::startNpcThread(Script::Thread *thread, int npcId) +void CharacterComponent::startNpcThread(Script::Thread *thread, int npcId) { if (mNpcThread) delete mNpcThread; @@ -698,7 +682,7 @@ void Character::startNpcThread(Script::Thread *thread, int npcId) resumeNpcThread(); } -void Character::resumeNpcThread() +void CharacterComponent::resumeNpcThread() { Script *script = ScriptManager::currentState(); @@ -708,43 +692,47 @@ void Character::resumeNpcThread() { MessageOut msg(GPMSG_NPC_CLOSE); msg.writeInt16(mTalkNpcId); - gameHandler->sendTo(this, msg); + gameHandler->sendTo(mClient, msg); mTalkNpcId = 0; mNpcThread = 0; } } -void Character::attackAdded(Attack &attack) +void CharacterComponent::attackAdded(CombatComponent *combatComponent, + Attack &attack) { // Remove knuckle attack if (attack.getAttackInfo() != mKnuckleAttackInfo) - getComponent<CombatComponent>()->removeAttack(mKnuckleAttackInfo); + combatComponent->removeAttack(mKnuckleAttackInfo); } -void Character::attackRemoved(Attack &attack) +void CharacterComponent::attackRemoved(CombatComponent *combatComponent, + Attack &attack) { // Add knuckle attack - CombatComponent *combatComponent = getComponent<CombatComponent>(); // 1 since the attack is not really removed yet. if (combatComponent->getAttacks().getNumber() == 1) combatComponent->addAttack(mKnuckleAttackInfo); } -void Character::disconnected() +void CharacterComponent::disconnected(Entity &entity) { + // Temporary until all dependencies are available as a Component + Being &being = static_cast<Being &>(entity); + mConnected = false; // Make the dead characters respawn, even in case of disconnection. - if (getAction() == DEAD) - respawn(); + if (being.getAction() == DEAD) + respawn(entity); else - GameState::remove(this); + GameState::remove(&entity); - signal_disconnected.emit(this); + signal_disconnected.emit(entity); } -bool Character::takeSpecial(int id) +bool CharacterComponent::takeSpecial(int id) { SpecialMap::iterator i = mSpecials.find(id); if (i != mSpecials.end()) @@ -756,12 +744,12 @@ bool Character::takeSpecial(int id) return false; } -void Character::clearSpecials() +void CharacterComponent::clearSpecials() { mSpecials.clear(); } -void Character::triggerLoginCallback() +void CharacterComponent::triggerLoginCallback(Entity &entity) { - executeCallback(mLoginCallback, this); + executeCallback(mLoginCallback, entity); } diff --git a/src/game-server/character.h b/src/game-server/character.h index 8b015f98..4b5089d6 100644 --- a/src/game-server/character.h +++ b/src/game-server/character.h @@ -26,6 +26,8 @@ #include "common/manaserv_protocol.h" #include "game-server/being.h" +#include "game-server/mapcomposite.h" +#include "game-server/mapmanager.h" #include "game-server/specialmanager.h" #include "scripting/script.h" @@ -63,48 +65,113 @@ struct SpecialValue */ typedef std::map<unsigned, SpecialValue> SpecialMap; + +class CharacterData +{ +public: + CharacterData(Being *being, CharacterComponent *characterComponent); + + void setGender(BeingGender); + BeingGender getGender() const; + + void setMapId(int id); + int getMapId() const; + void setPosition(Point &point); + const Point &getPosition() const; + + void setAttribute(int id, int base); + void setModAttribute(int id, int mod); + const AttributeMap &getAttributes() const; + void setCharacterPoints(int characterPoints); + int getCharacterPoints() const; + void setCorrectionPoints(int correctionPoints); + int getCorrectionPoints() const; + + void setExperience(int skill, int level); + void setLevel(int level) const; + int getLevel() const; + + int getAccountLevel() const; + + void setHairStyle(int style); + int getHairStyle() const; + void setHairColor(int color); + int getHairColor() const; + + void setAccountLevel(int level); + + int getSkillSize() const; + const std::map<int, int>::const_iterator getSkillBegin() const; + const std::map<int, int>::const_iterator getSkillEnd() const; + + void applyStatusEffect(int status, int time); + int getStatusEffectSize() const; + const std::map<int, Status>::const_iterator getStatusEffectBegin() const; + const std::map<int, Status>::const_iterator getStatusEffectEnd() const; + + int getKillCountSize() const; + const std::map<int, int>::const_iterator getKillCountBegin() const; + const std::map<int, int>::const_iterator getKillCountEnd() const; + void setKillCount(int monsterId, int kills); + + void clearSpecials(); + void giveSpecial(int id, int mana); + int getSpecialSize() const; + SpecialMap::const_iterator getSpecialBegin() const; + SpecialMap::const_iterator getSpecialEnd() const; + + Possessions &getPossessions() const; + +private: + Being *mBeing; + CharacterComponent *mCharacterComponent; +}; + + /** * The representation of a player's character in the game world. */ -class Character : public Being +class CharacterComponent : public Component { public: + static const ComponentType type = CT_Character; + /** * Utility constructor for creating a Character from a received * characterdata message. */ - Character(MessageIn &msg); + CharacterComponent(Entity &entity, MessageIn &msg); - ~Character(); + ~CharacterComponent(); /** * recalculates the level when necessary and calls Being::update */ - void update(); + void update(Entity &entity); void processAttacks(); /** - * Executes the global die script and calls the base class function + * Executes the global die script */ - virtual void died(); + virtual void characterDied(Being *); /** * makes the character respawn */ - void respawn(); + void respawn(Entity &entity); /** * makes the character perform a special action on a being * when it is allowed to do so */ - void useSpecialOnBeing(int id, Being *b); + void useSpecialOnBeing(Entity &user, int id, Being *b); /** * makes the character perform a special action on a map point * when it is allowed to do so */ - void useSpecialOnPoint(int id, int x, int y); + void useSpecialOnPoint(Entity &user, int id, int x, int y); /** * Allows a character to perform a special action @@ -232,43 +299,25 @@ class Character : public Being * Sends a message that informs the client about attribute * modified since last call. */ - void sendStatus(); - - /** - * Gets the ID of the map that the character is on. - * For serialization purpose only. - */ - int getMapId() const; - - /** - * Sets the ID of the map that the character is on. - * For serialization purpose only. - */ - void setMapId(int); + void sendStatus(Entity &entity); /** * Marks all attributes as being modified. */ - void modifiedAllAttribute(); + void modifiedAllAttributes(Entity &entity); /** - * 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) + * Signal handler for attribute changed event + * Flags the attribute as modified. + * @param being th being of which the attribute was changed + * @param attributeId the changed id */ - void updateDerivedAttributes(unsigned); + void attributeChanged(Being *being, unsigned attributeId); /** * Calls all the "disconnected" listener. */ - void disconnected(); + void disconnected(Entity &entity); /** * Associative array containing all the quest variables known by the @@ -292,18 +341,6 @@ class Character : public Being { return mExperience.end(); } /** - * Used to serialize status effects. - */ - int getStatusEffectSize() const - { return mStatusEffects.size(); } - - const std::map<int, int>::const_iterator getStatusEffectBegin() const - { return mStatusEffects.begin(); } - - const std::map<int, int>::const_iterator getStatusEffectEnd() const - { return mStatusEffects.end(); } - - /** * Used to serialize kill count. */ int getKillCountSize() const @@ -366,13 +403,15 @@ class Character : public Being * Tries to use a character point to increase a * basic attribute */ - AttribmodResponseCode useCharacterPoint(size_t attribute); + AttribmodResponseCode useCharacterPoint(Entity &entity, + size_t attribute); /** * Tries to use a correction point to reduce a * basic attribute and regain a character point */ - AttribmodResponseCode useCorrectionPoint(size_t attribute); + AttribmodResponseCode useCorrectionPoint(Entity &entity, + size_t attribute); void setCharacterPoints(int points) { mCharacterPoints = points; } int getCharacterPoints() const { return mCharacterPoints; } @@ -423,13 +462,15 @@ class Character : public Being static void setLoginCallback(Script *script) { script->assignCallback(mLoginCallback); } - void triggerLoginCallback(); + void triggerLoginCallback(Entity &entity); - void attackAdded(Attack &attackInfo); + void attackAdded(CombatComponent *combatComponent, Attack &attackInfo); + void attackRemoved(CombatComponent *combatComponent, Attack &attackInfo); - void attackRemoved(Attack &attackInfo); + CharacterData *getCharacterData() + { return mCharacterData; } - sigc::signal<void, Character *> signal_disconnected; + sigc::signal<void, Entity &> signal_disconnected; private: bool specialUseCheck(SpecialMap::iterator it); @@ -439,8 +480,8 @@ class Character : public Being double getAttrMod(AttributeMap::const_iterator it) const { return it->second.getModifiedAttribute(); } - Character(const Character &); - Character &operator=(const Character &); + CharacterComponent(const CharacterComponent &); + CharacterComponent &operator=(const CharacterComponent &); static const float EXPCURVE_EXPONENT; static const float EXPCURVE_FACTOR; @@ -453,12 +494,7 @@ class Character : public Being /** * Advances the character by one level; */ - void levelup(); - - /** - * Marks attribute as recently modified. - */ - void flagAttribute(int); + void levelup(Entity &entity); /** * Returns the exp needed for next skill levelup @@ -473,7 +509,7 @@ class Character : public Being /** * Recalculates the character level */ - void recalculateLevel(); + void recalculateLevel(Entity &entity); /** * Informs the client about his characters special charge status @@ -503,9 +539,6 @@ class Character : public Being std::map<int, int> mExperience; /**< experience collected for each skill.*/ SpecialMap mSpecials; - std::map<int, int> mStatusEffects; /**< only used by select functions - to make it easier to make the accountserver - do not modify or use anywhere else*/ bool mSpecialUpdateNeeded; int mDatabaseID; /**< Character's database ID. */ @@ -529,13 +562,221 @@ class Character : public Being AttackInfo *mKnuckleAttackInfo; + Entity *mBaseEntity; /**< The entity this component is part of + this is ONLY required to allow using + the serialization routine without many + changes (we cannot pass the entity as + argument there). DO NOT USE THIS IF IT + IS AVOIDABLE in order to allow + refactoring this easier later! */ + + CharacterData *mCharacterData; + static Script::Ref mDeathCallback; static Script::Ref mDeathAcceptedCallback; static Script::Ref mLoginCallback; - - // Set as a friend, but still a lot of redundant accessors. FIXME. - template< class T > - friend void serializeCharacterData(const T &data, MessageOut &msg); }; + +inline CharacterData::CharacterData(Being *being, + CharacterComponent *characterComponent): + mBeing(being), + mCharacterComponent(characterComponent) +{} + +inline void CharacterData::setGender(BeingGender gender) +{ + mBeing->setGender(gender); +} + +inline BeingGender CharacterData::getGender() const +{ + return mBeing->getGender(); +} + +inline void CharacterData::setMapId(int id) +{ + mBeing->setMap(MapManager::getMap(id)); +} + +inline int CharacterData::getMapId() const +{ + return mBeing->getMap()->getID(); +} + +inline void CharacterData::setPosition(Point &point) +{ + mBeing->setPosition(point); +} + +inline const Point &CharacterData::getPosition() const +{ + return mBeing->getPosition(); +} + +inline void CharacterData::setAttribute(int id, int base) +{ + mBeing->setAttribute(id, base); +} + +inline void CharacterData::setModAttribute(int id, int mod) +{ + mBeing->setModAttribute(id, mod); +} + +inline const AttributeMap &CharacterData::getAttributes() const +{ + return mBeing->getAttributes(); +} + +inline void CharacterData::setCharacterPoints(int characterPoints) +{ + mCharacterComponent->setCharacterPoints(characterPoints); +} + +inline int CharacterData::getCharacterPoints() const +{ + return mCharacterComponent->getCharacterPoints(); +} + +inline void CharacterData::setCorrectionPoints(int correctionPoints) +{ + mCharacterComponent->setCorrectionPoints(correctionPoints); +} + +inline int CharacterData::getCorrectionPoints() const +{ + return mCharacterComponent->getCorrectionPoints(); +} + +inline void CharacterData::setExperience(int skill, int level) +{ + mCharacterComponent->setExperience(skill, level); +} + +inline void CharacterData::setLevel(int level) const +{ + mCharacterComponent->setLevel(level); +} + +inline int CharacterData::getLevel() const +{ + return mCharacterComponent->getLevel(); +} + +inline int CharacterData::getAccountLevel() const +{ + return mCharacterComponent->getAccountLevel(); +} + +inline void CharacterData::setHairStyle(int style) +{ + mCharacterComponent->setHairStyle(style); +} + +inline int CharacterData::getHairStyle() const +{ + return mCharacterComponent->getHairStyle(); +} + +inline void CharacterData::setHairColor(int color) +{ + mCharacterComponent->setHairColor(color); +} + +inline int CharacterData::getHairColor() const +{ + return mCharacterComponent->getHairColor(); +} + +inline void CharacterData::setAccountLevel(int level) +{ + mCharacterComponent->setAccountLevel(level); +} + +inline int CharacterData::getSkillSize() const +{ + return mCharacterComponent->getSkillSize(); +} + +inline const std::map<int, int>::const_iterator CharacterData::getSkillBegin() const +{ + return mCharacterComponent->getSkillBegin(); +} + +inline const std::map<int, int>::const_iterator CharacterData::getSkillEnd() const +{ + return mCharacterComponent->getSkillEnd(); +} + +inline void CharacterData::applyStatusEffect(int status, int time) +{ + mBeing->applyStatusEffect(status, time); +} + +inline int CharacterData::getStatusEffectSize() const +{ + return mBeing->getStatusEffects().size(); +} + +inline const std::map<int, Status>::const_iterator CharacterData::getStatusEffectBegin() const +{ + return mBeing->getStatusEffects().begin(); +} + +inline const std::map<int, Status>::const_iterator CharacterData::getStatusEffectEnd() const +{ + return mBeing->getStatusEffects().end(); +} + +inline int CharacterData::getKillCountSize() const +{ + return mCharacterComponent->getKillCountSize(); +} + +inline const std::map<int, int>::const_iterator CharacterData::getKillCountBegin() const +{ + return mCharacterComponent->getKillCountBegin(); +} + +inline const std::map<int, int>::const_iterator CharacterData::getKillCountEnd() const +{ + return mCharacterComponent->getKillCountEnd(); +} + +inline void CharacterData::setKillCount(int monsterId, int kills) +{ + mCharacterComponent->setKillCount(monsterId, kills); +} + +inline void CharacterData::clearSpecials() +{ + mCharacterComponent->clearSpecials(); +} + +inline void CharacterData::giveSpecial(int id, int mana) +{ + mCharacterComponent->giveSpecial(id, mana); +} + +inline int CharacterData::getSpecialSize() const +{ + return mCharacterComponent->getSpecialSize(); +} + +inline SpecialMap::const_iterator CharacterData::getSpecialBegin() const +{ + return mCharacterComponent->getSpecialBegin(); +} + +inline SpecialMap::const_iterator CharacterData::getSpecialEnd() const +{ + return mCharacterComponent->getSpecialEnd(); +} + +inline Possessions &CharacterData::getPossessions() const +{ + return mCharacterComponent->getPossessions(); +} + #endif // CHARACTER_H diff --git a/src/game-server/combatcomponent.cpp b/src/game-server/combatcomponent.cpp index 469569b6..d71f86a3 100644 --- a/src/game-server/combatcomponent.cpp +++ b/src/game-server/combatcomponent.cpp @@ -180,7 +180,7 @@ void CombatComponent::processAttack(Being &source, Attack &attack) */ void CombatComponent::addAttack(AttackInfo *attackInfo) { - mAttacks.add(attackInfo); + mAttacks.add(this, attackInfo); } /** @@ -188,7 +188,7 @@ void CombatComponent::addAttack(AttackInfo *attackInfo) */ void CombatComponent::removeAttack(AttackInfo *attackInfo) { - mAttacks.remove(attackInfo); + mAttacks.remove(this, attackInfo); } /** diff --git a/src/game-server/commandhandler.cpp b/src/game-server/commandhandler.cpp index d38828fe..63b960d3 100644 --- a/src/game-server/commandhandler.cpp +++ b/src/game-server/commandhandler.cpp @@ -48,44 +48,44 @@ struct CmdRef const char *cmd; const char *usage; const char *help; - void (*func)(Character*, std::string&) ; + void (*func)(Being*, std::string&) ; }; -static void handleHelp(Character*, std::string&); -static void handleReport(Character*, std::string&); -static void handleWhere(Character*, std::string&); -static void handleRights(Character*, std::string&); -static void handleWarp(Character*, std::string&); -static void handleCharWarp(Character*, std::string&); -static void handleGoto(Character*, std::string&); -static void handleRecall(Character*, std::string&); -static void handleBan(Character*, std::string&); -static void handleItem(Character*, std::string&); -static void handleDrop(Character*, std::string&); -static void handleMoney(Character*, std::string&); -static void handleSpawn(Character*, std::string&); -static void handleAttribute(Character*, std::string&); -static void handleReload(Character*, std::string&); -static void handlePermissions(Character*, std::string&); -static void handleGivePermission(Character*, std::string&); -static void handleTakePermission(Character*, std::string&); -static void handleAnnounce(Character*, std::string&); -static void handleHistory(Character*, std::string&); -static void handleMute(Character*, std::string&); -static void handleDie(Character*, std::string&); -static void handleKill(Character*, std::string&); -static void handleKick(Character*, std::string&); -static void handleLog(Character*, std::string&); -static void handleLogsay(Character*, std::string&); -static void handleKillMonsters(Character*, std::string&); -static void handleCraft(Character*, std::string&); -static void handleGetPos(Character*, std::string&); -static void handleSkills(Character*, std::string&); -static void handleEffect(Character*, std::string&); -static void handleGiveSpecial(Character*, std::string&); -static void handleTakeSpecial(Character*, std::string&); -static void handleRechargeSpecial(Character*, std::string&); -static void handleListSpecials(Character*, std::string&); +static void handleHelp(Being*, std::string&); +static void handleReport(Being*, std::string&); +static void handleWhere(Being*, std::string&); +static void handleRights(Being*, std::string&); +static void handleWarp(Being*, std::string&); +static void handleCharWarp(Being*, std::string&); +static void handleGoto(Being*, std::string&); +static void handleRecall(Being*, std::string&); +static void handleBan(Being*, std::string&); +static void handleItem(Being*, std::string&); +static void handleDrop(Being*, std::string&); +static void handleMoney(Being*, std::string&); +static void handleSpawn(Being*, std::string&); +static void handleAttribute(Being*, std::string&); +static void handleReload(Being*, std::string&); +static void handlePermissions(Being*, std::string&); +static void handleGivePermission(Being*, std::string&); +static void handleTakePermission(Being*, std::string&); +static void handleAnnounce(Being*, std::string&); +static void handleHistory(Being*, std::string&); +static void handleMute(Being*, std::string&); +static void handleDie(Being*, std::string&); +static void handleKill(Being*, std::string&); +static void handleKick(Being*, std::string&); +static void handleLog(Being*, std::string&); +static void handleLogsay(Being*, std::string&); +static void handleKillMonsters(Being*, std::string&); +static void handleCraft(Being*, std::string&); +static void handleGetPos(Being*, std::string&); +static void handleSkills(Being*, std::string&); +static void handleEffect(Being*, std::string&); +static void handleGiveSpecial(Being*, std::string&); +static void handleTakeSpecial(Being*, std::string&); +static void handleRechargeSpecial(Being*, std::string&); +static void handleListSpecials(Being*, std::string&); static CmdRef const cmdRef[] = { @@ -171,7 +171,7 @@ static CmdRef const cmdRef[] = }; -static void say(const std::string &message, Character *player) +static void say(const std::string &message, Being *player) { GameState::sayTo(player, NULL, message); } @@ -193,10 +193,10 @@ static bool checkPermission(Character *player, unsigned permissions) * Returns the next argument, and remove it from the given string. */ -static std::string playerRights(Character *ch) +static std::string playerRights(Being *ch) { std::stringstream str; - str << (unsigned)ch->getAccountLevel(); + str << (unsigned)ch->getComponent<CharacterComponent>()->getAccountLevel(); str << " ( "; std::list<std::string> classes = PermissionManager::getClassList(ch); @@ -263,7 +263,7 @@ static std::string getArgument(std::string &args) return argument; } -static void handleHelp(Character *player, std::string &args) +static void handleHelp(Being *player, std::string &args) { if (args.empty()) { @@ -302,7 +302,7 @@ static void handleHelp(Character *player, std::string &args) } } -static void handleWarp(Character *player, std::string &args) +static void handleWarp(Being *player, std::string &args) { int x, y; MapComposite *map; @@ -382,15 +382,17 @@ static void handleWarp(Character *player, std::string &args) // log transaction std::stringstream ss; ss << "User warped to " << map->getName() << " (" << x << ", " << y << ")"; - accountHandler->sendTransaction(player->getDatabaseID(), TRANS_CMD_WARP, + int databaseId = + player->getComponent<CharacterComponent>()->getDatabaseID(); + accountHandler->sendTransaction(databaseId, TRANS_CMD_WARP, ss.str()); } -static void handleCharWarp(Character *player, std::string &args) +static void handleCharWarp(Being *player, std::string &args) { int x, y; MapComposite *map; - Character *other; + Being *other; // get the arguments std::string character = getArgument(args); @@ -485,13 +487,14 @@ static void handleCharWarp(Character *player, std::string &args) std::stringstream ss; ss << "User warped " << other->getName() << " to " << map->getName() << " (" << x << ", " << y << ")"; - accountHandler->sendTransaction(player->getDatabaseID(), TRANS_CMD_WARP, - ss.str()); + int databaseId = + player->getComponent<CharacterComponent>()->getDatabaseID(); + accountHandler->sendTransaction(databaseId, TRANS_CMD_WARP, ss.str()); } -static void handleItem(Character *player, std::string &args) +static void handleItem(Being *player, std::string &args) { - Character *other; + Being *other; ItemClass *ic; int value = 0; @@ -562,10 +565,12 @@ static void handleItem(Character *player, std::string &args) // log transaction std::stringstream str; str << "User created item " << ic->getDatabaseID(); - accountHandler->sendTransaction(player->getDatabaseID(), TRANS_CMD_ITEM, str.str()); + int databaseId = + player->getComponent<CharacterComponent>()->getDatabaseID(); + accountHandler->sendTransaction(databaseId, TRANS_CMD_ITEM, str.str()); } -static void handleDrop(Character *player, std::string &args) +static void handleDrop(Being *player, std::string &args) { ItemClass *ic; int amount = 0; @@ -623,12 +628,14 @@ static void handleDrop(Character *player, std::string &args) // log transaction std::stringstream str; str << "User created item " << ic->getDatabaseID(); - accountHandler->sendTransaction(player->getDatabaseID(), TRANS_CMD_DROP, str.str()); + int databaseId = + player->getComponent<CharacterComponent>()->getDatabaseID(); + accountHandler->sendTransaction(databaseId, TRANS_CMD_DROP, str.str()); } -static void handleMoney(Character *player, std::string &args) +static void handleMoney(Being *player, std::string &args) { - Character *other; + Being *other; int value; // get arguments @@ -674,10 +681,12 @@ static void handleMoney(Character *player, std::string &args) // log transaction std::string msg = "User created " + valuestr + " money"; - accountHandler->sendTransaction(player->getDatabaseID(), TRANS_CMD_MONEY, msg); + int databaseId = + player->getComponent<CharacterComponent>()->getDatabaseID(); + accountHandler->sendTransaction(databaseId, TRANS_CMD_MONEY, msg); } -static void handleSpawn(Character *player, std::string &args) +static void handleSpawn(Being *player, std::string &args) { MonsterClass *mc; MapComposite *map = player->getMap(); @@ -745,13 +754,15 @@ static void handleSpawn(Character *player, std::string &args) // log transaction std::string msg = "User created monster " + monster->getName(); - accountHandler->sendTransaction(player->getDatabaseID(), TRANS_CMD_SPAWN, msg); + int databaseId = + player->getComponent<CharacterComponent>()->getDatabaseID(); + accountHandler->sendTransaction(databaseId, TRANS_CMD_SPAWN, msg); } } -static void handleGoto(Character *player, std::string &args) +static void handleGoto(Being *player, std::string &args) { - Character *other; + Being *other; // get the arguments std::string character = getArgument(args); @@ -780,12 +791,14 @@ static void handleGoto(Character *player, std::string &args) // log transaction std::stringstream msg; msg << "User warped own character to " << other->getName(); - accountHandler->sendTransaction(player->getDatabaseID(), TRANS_CMD_GOTO, msg.str()); + int databaseId = + player->getComponent<CharacterComponent>()->getDatabaseID(); + accountHandler->sendTransaction(databaseId, TRANS_CMD_GOTO, msg.str()); } -static void handleRecall(Character *player, std::string &args) +static void handleRecall(Being *player, std::string &args) { - Character *other; + Being *other; // get the arguments std::string character = getArgument(args); @@ -812,16 +825,16 @@ static void handleRecall(Character *player, std::string &args) GameState::warp(other, map, pos); } -static void handleReload(Character *, std::string &) +static void handleReload(Being *, std::string &) { // reload the items and monsters itemManager->reload(); monsterManager->reload(); } -static void handleBan(Character *player, std::string &args) +static void handleBan(Being *player, std::string &args) { - Character *other; + Being *other; int length; int lengthMutiplier = 0; @@ -877,22 +890,25 @@ static void handleBan(Character *player, std::string &args) return; } + auto *characterComponent = player->getComponent<CharacterComponent>(); + // ban the player accountHandler->banCharacter(other, length); // disconnect the player MessageOut kickmsg(GPMSG_CONNECT_RESPONSE); kickmsg.writeInt8(ERRMSG_ADMINISTRATIVE_LOGOFF); - other->getClient()->disconnect(kickmsg); + characterComponent->getClient()->disconnect(kickmsg); // feedback for command user std::string msg = "You've banned " + other->getName() + " for " + utils::toString(length) + " minutes"; say(msg.c_str(), player); // log transaction msg = "User banned " + other->getName() + " for " + utils::toString(length) + " minutes"; - accountHandler->sendTransaction(player->getDatabaseID(), TRANS_CMD_BAN, msg); + accountHandler->sendTransaction(characterComponent->getDatabaseID(), + TRANS_CMD_BAN, msg); } -static void handlePermissions(Character *player, std::string &args) +static void handlePermissions(Being *player, std::string &args) { std::string character = getArgument(args); if (character.empty()) @@ -902,7 +918,7 @@ static void handlePermissions(Character *player, std::string &args) return; } - Character *other = gameHandler->getCharacterByNameSlow(character); + Being *other = gameHandler->getCharacterByNameSlow(character); if (!other) { say("Invalid character", player); @@ -913,9 +929,9 @@ static void handlePermissions(Character *player, std::string &args) playerRights(other), player); } -static void handleGivePermission(Character *player, std::string &args) +static void handleGivePermission(Being *player, std::string &args) { - Character *other; + Being *other; // get the arguments std::string character = getArgument(args); @@ -953,20 +969,24 @@ static void handleGivePermission(Character *player, std::string &args) return; } - if (permission & other->getAccountLevel()) + auto *characterComponent = + player->getComponent<CharacterComponent>(); + + if (permission & characterComponent->getAccountLevel()) { say(player->getName()+" already has the permission "+strPermission, player); } else { - permission += other->getAccountLevel(); + permission += characterComponent->getAccountLevel(); // change the player's account level - other->setAccountLevel(permission); + characterComponent->setAccountLevel(permission); accountHandler->changeAccountLevel(other, permission); // log transaction std::string msg = "User gave right " + strPermission + " to " + other->getName(); - accountHandler->sendTransaction(player->getDatabaseID(), TRANS_CMD_SETGROUP, msg); + accountHandler->sendTransaction(characterComponent->getDatabaseID(), + TRANS_CMD_SETGROUP, msg); say("You gave " + other->getName() + " the rights of a " + strPermission, player); say("Congratulations, " + player->getName() + @@ -974,9 +994,9 @@ static void handleGivePermission(Character *player, std::string &args) } } -static void handleTakePermission(Character *player, std::string &args) +static void handleTakePermission(Being *player, std::string &args) { - Character *other; + Being *other; // get the arguments std::string character = getArgument(args); @@ -1014,27 +1034,30 @@ static void handleTakePermission(Character *player, std::string &args) return; } + auto *characterComponent = + player->getComponent<CharacterComponent>(); - if (!(permission & other->getAccountLevel())) + if (!(permission & characterComponent->getAccountLevel())) { say(player->getName()+" hasn't got the permission "+strPermission, player); } else { - permission = other->getAccountLevel() - permission; + permission = characterComponent->getAccountLevel() - permission; // change the player's account level - other->setAccountLevel(permission); + characterComponent->setAccountLevel(permission); accountHandler->changeAccountLevel(other, permission); // log transaction std::string msg = "User took right " + strPermission + " from " + other->getName(); - accountHandler->sendTransaction(player->getDatabaseID(), TRANS_CMD_SETGROUP, msg); + accountHandler->sendTransaction(characterComponent->getDatabaseID(), + TRANS_CMD_SETGROUP, msg); say("Sorry, "+player->getName()+" revoked your rights of a "+strPermission, other); } } -static void handleAttribute(Character *player, std::string &args) +static void handleAttribute(Being *player, std::string &args) { - Character *other; + Being *other; int attr, value; // get arguments @@ -1098,10 +1121,12 @@ static void handleAttribute(Character *player, std::string &args) std::stringstream msg; msg << "User changed attribute " << attr << " of player " << other->getName() << " to " << value; - accountHandler->sendTransaction(player->getDatabaseID(), TRANS_CMD_ATTRIBUTE, msg.str()); + int databaseId = + player->getComponent<CharacterComponent>()->getDatabaseID(); + accountHandler->sendTransaction(databaseId, TRANS_CMD_ATTRIBUTE, msg.str()); } -static void handleReport(Character *player, std::string &args) +static void handleReport(Being *player, std::string &args) { std::string bugReport = getArgument(args); @@ -1115,7 +1140,7 @@ static void handleReport(Character *player, std::string &args) // TODO: Send the report to a developer or something } -static void handleAnnounce(Character *player, std::string &args) +static void handleAnnounce(Being *player, std::string &args) { if (args.empty()) { @@ -1126,16 +1151,17 @@ static void handleAnnounce(Character *player, std::string &args) MessageOut msg(GAMSG_ANNOUNCE); msg.writeString(args); - msg.writeInt16(player->getDatabaseID()); + msg.writeInt16(player->getComponent<CharacterComponent>() + ->getDatabaseID()); msg.writeString(player->getName()); accountHandler->send(msg); } -static void handleWhere(Character *player, std::string &) +static void handleWhere(Being *player, std::string &) { std::stringstream str; str << "Your current location is map " - << player->getMapId() + << player->getMap()->getID() << " [" << player->getPosition().x << ":" @@ -1144,19 +1170,19 @@ static void handleWhere(Character *player, std::string &) say (str.str(), player); } -static void handleRights(Character *player, std::string &) +static void handleRights(Being *player, std::string &) { say("Your rights level is: " + playerRights(player), player); } -static void handleHistory(Character *, std::string &) +static void handleHistory(Being *, std::string &) { // TODO: Get args number of transactions and show them to the player } -static void handleMute(Character *player, std::string &args) +static void handleMute(Being *player, std::string &args) { - Character *other; + Being *other; int length; // Get arguments. @@ -1185,7 +1211,7 @@ static void handleMute(Character *player, std::string &args) } // Mute the player. - other->mute(length); + other->getComponent<CharacterComponent>()->mute(length); // Feedback. std::stringstream targetMsg; @@ -1214,18 +1240,20 @@ static void handleMute(Character *player, std::string &args) } else { msg << "User unmuted " << other->getName(); } - accountHandler->sendTransaction(player->getDatabaseID(), TRANS_CMD_MUTE, msg.str()); + int databaseId = + player->getComponent<CharacterComponent>()->getDatabaseID(); + accountHandler->sendTransaction(databaseId, TRANS_CMD_MUTE, msg.str()); } -static void handleDie(Character *player, std::string &) +static void handleDie(Being *player, std::string &) { player->setAttribute(ATTR_HP, 0); say("You've killed yourself.", player); } -static void handleKill(Character *player, std::string &args) +static void handleKill(Being *player, std::string &args) { - Character *other; + Being *other; // get arguments std::string character = getArgument(args); @@ -1252,12 +1280,14 @@ static void handleKill(Character *player, std::string &args) // log transaction std::stringstream logMsg; logMsg << "User killed " << other->getName(); - accountHandler->sendTransaction(player->getDatabaseID(), TRANS_CMD_KILL, logMsg.str()); + int databaseId = + player->getComponent<CharacterComponent>()->getDatabaseID(); + accountHandler->sendTransaction(databaseId, TRANS_CMD_KILL, logMsg.str()); } -static void handleKick(Character *player, std::string &args) +static void handleKick(Being *player, std::string &args) { - Character *other; + Being *other; // get arguments std::string character = getArgument(args); @@ -1275,19 +1305,25 @@ static void handleKick(Character *player, std::string &args) userMsg << "You kicked " << other->getName() << "."; say(userMsg.str(), player); + + auto *characterComponent = + player->getComponent<CharacterComponent>(); + // disconnect the client MessageOut msg(GPMSG_CONNECT_RESPONSE); msg.writeInt8(ERRMSG_ADMINISTRATIVE_LOGOFF); - other->getClient()->disconnect(msg); + characterComponent->getClient()->disconnect(msg); // log transaction std::stringstream logMsg; logMsg << "User kicked " << other->getName(); - accountHandler->sendTransaction(player->getDatabaseID(), TRANS_CMD_KICK, logMsg.str()); + int databaseId = + player->getComponent<CharacterComponent>()->getDatabaseID(); + accountHandler->sendTransaction(databaseId, TRANS_CMD_KICK, logMsg.str()); } -static void handleLog(Character *player, std::string &msg) +static void handleLog(Being *player, std::string &msg) { if (msg.empty()) { @@ -1298,13 +1334,15 @@ static void handleLog(Character *player, std::string &msg) // log transaction std::string logmsg = "[silent] " + msg; - accountHandler->sendTransaction(player->getDatabaseID(), TRANS_CMD_LOG, logmsg); + int databaseId = + player->getComponent<CharacterComponent>()->getDatabaseID(); + accountHandler->sendTransaction(databaseId, TRANS_CMD_LOG, logmsg); // send feedback say("Message logged", player); } -static void handleLogsay(Character *player, std::string &msg) +static void handleLogsay(Being *player, std::string &msg) { if (msg.empty()) { @@ -1317,13 +1355,15 @@ static void handleLogsay(Character *player, std::string &msg) // log transaction std::string logmsg = "[public] " + msg; - accountHandler->sendTransaction(player->getDatabaseID(), TRANS_CMD_LOG, logmsg); + int databaseId = + player->getComponent<CharacterComponent>()->getDatabaseID(); + accountHandler->sendTransaction(databaseId, TRANS_CMD_LOG, logmsg); // send feedback say("Message logged", player); } -static void handleKillMonsters(Character *player, std::string &) +static void handleKillMonsters(Being *player, std::string &) { const MapComposite *map = player->getMap(); int count = 0; @@ -1343,11 +1383,12 @@ static void handleKillMonsters(Character *player, std::string &) // log transaction std::string msg = "User killed all monsters on map " + map->getName(); - accountHandler->sendTransaction(player->getDatabaseID(), - TRANS_CMD_KILLMONSTERS, msg); + int databaseId = + player->getComponent<CharacterComponent>()->getDatabaseID(); + accountHandler->sendTransaction(databaseId, TRANS_CMD_KILLMONSTERS, msg); } -static void handleCraft(Character *player, std::string &args) +static void handleCraft(Being *player, std::string &args) { std::stringstream errMsg; std::list<InventoryItem> recipe; @@ -1420,7 +1461,7 @@ static void handleCraft(Character *player, std::string &args) } } -static void handleGetPos(Character *player, std::string &args) +static void handleGetPos(Being *player, std::string &args) { std::string character = getArgument(args); if (character.empty()) @@ -1429,7 +1470,7 @@ static void handleGetPos(Character *player, std::string &args) say("Usage: @getpos <character>", player); return; } - Character *other; + Being *other; other = gameHandler->getCharacterByNameSlow(character); if (!other) { @@ -1441,7 +1482,7 @@ static void handleGetPos(Character *player, std::string &args) str << "The current location of " << character << " is map " - << other->getMapId() + << other->getMap()->getID() << " [" << pos.x << ":" @@ -1450,7 +1491,7 @@ static void handleGetPos(Character *player, std::string &args) say(str.str(), player); } -static void handleSkills(Character *player, std::string &args) +static void handleSkills(Being *player, std::string &args) { std::string character = getArgument(args); if (character.empty()) @@ -1459,7 +1500,7 @@ static void handleSkills(Character *player, std::string &args) say("Usage: @skills <character>", player); return; } - Character *other; + Being *other; if (character == "#") other = player; else @@ -1470,9 +1511,15 @@ static void handleSkills(Character *player, std::string &args) return; } + + auto *characterComponent = + player->getComponent<CharacterComponent>(); + say("List of skills of player '" + other->getName() + "':", player); - std::map<int, int>::const_iterator it = other->getSkillBegin(); - std::map<int, int>::const_iterator it_end = other->getSkillEnd(); + std::map<int, int>::const_iterator it = + characterComponent->getSkillBegin(); + std::map<int, int>::const_iterator it_end = + characterComponent->getSkillEnd(); if (it == it_end) { @@ -1489,7 +1536,7 @@ static void handleSkills(Character *player, std::string &args) } } -static void handleEffect(Character *player, std::string &args) +static void handleEffect(Being *player, std::string &args) { std::vector<std::string> arguments; for (std::string arg = getArgument(args); !arg.empty(); @@ -1506,7 +1553,7 @@ static void handleEffect(Character *player, std::string &args) else if (arguments.size() == 2) { int id = utils::stringToInt(arguments[0]); - Character *p = gameHandler->getCharacterByNameSlow(arguments[1]); + Being *p = gameHandler->getCharacterByNameSlow(arguments[1]); if (!p) { say("Invalid target player.", player); @@ -1529,7 +1576,7 @@ static void handleEffect(Character *player, std::string &args) } } -static void handleGiveSpecial(Character *player, std::string &args) +static void handleGiveSpecial(Being *player, std::string &args) { std::string character = getArgument(args); std::string special = getArgument(args); @@ -1540,7 +1587,7 @@ static void handleGiveSpecial(Character *player, std::string &args) return; } - Character *other; + Being *other; if (character == "#") other = player; else @@ -1558,14 +1605,15 @@ static void handleGiveSpecial(Character *player, std::string &args) else specialId = specialManager->getId(special); - if (specialId <= 0 || !other->giveSpecial(specialId)) + if (specialId <= 0 || + !other->getComponent<CharacterComponent>()->giveSpecial(specialId)) { say("Invalid special.", player); return; } } -static void handleTakeSpecial(Character *player, std::string &args) +static void handleTakeSpecial(Being *player, std::string &args) { std::string character = getArgument(args); std::string special = getArgument(args); @@ -1576,7 +1624,7 @@ static void handleTakeSpecial(Character *player, std::string &args) return; } - Character *other; + Being *other; if (character == "#") other = player; else @@ -1599,14 +1647,14 @@ static void handleTakeSpecial(Character *player, std::string &args) say("Invalid special.", player); return; } - if (!other->takeSpecial(specialId)) + if (!other->getComponent<CharacterComponent>()->takeSpecial(specialId)) { say("Character does not have special.", player); return; } } -static void handleRechargeSpecial(Character *player, std::string &args) +static void handleRechargeSpecial(Being *player, std::string &args) { std::string character = getArgument(args); std::string special = getArgument(args); @@ -1618,7 +1666,7 @@ static void handleRechargeSpecial(Character *player, std::string &args) return; } - Character *other; + Being *other; if (character == "#") other = player; else @@ -1658,14 +1706,15 @@ static void handleRechargeSpecial(Character *player, std::string &args) } mana = utils::stringToInt(newMana); } - if (!other->setSpecialMana(specialId, mana)) + if (!other->getComponent<CharacterComponent>() + ->setSpecialMana(specialId, mana)) { say("Character does not have special.", player); return; } } -static void handleListSpecials(Character *player, std::string &args) +static void handleListSpecials(Being *player, std::string &args) { std::string character = getArgument(args); if (character.empty()) @@ -1675,7 +1724,7 @@ static void handleListSpecials(Character *player, std::string &args) return; } - Character *other; + Being *other; if (character == "#") other = player; else @@ -1687,9 +1736,12 @@ static void handleListSpecials(Character *player, std::string &args) return; } + auto *characterComponent = + other->getComponent<CharacterComponent>(); + say("Specials of character " + other->getName() + ":", player); - for (SpecialMap::const_iterator it = other->getSpecialBegin(), - it_end = other->getSpecialEnd(); it != it_end; ++it) + for (SpecialMap::const_iterator it = characterComponent->getSpecialBegin(), + it_end = characterComponent->getSpecialEnd(); it != it_end; ++it) { const SpecialValue &info = it->second; std::stringstream str; @@ -1699,7 +1751,7 @@ static void handleListSpecials(Character *player, std::string &args) } } -void CommandHandler::handleCommand(Character *player, +void CommandHandler::handleCommand(Being *player, const std::string &command) { // get command type, and arguments diff --git a/src/game-server/commandhandler.h b/src/game-server/commandhandler.h index 5327dda7..b5a268f5 100644 --- a/src/game-server/commandhandler.h +++ b/src/game-server/commandhandler.h @@ -23,14 +23,14 @@ #include <string> -class Character; +class Being; namespace CommandHandler { /** * Parse and handle the given command. */ - void handleCommand(Character *player, const std::string &command); + void handleCommand(Being *player, const std::string &command); } #endif //SERVER_COMMANDHANDLER_H diff --git a/src/game-server/component.h b/src/game-server/component.h index 974cad0c..45fe742e 100644 --- a/src/game-server/component.h +++ b/src/game-server/component.h @@ -25,6 +25,7 @@ class Entity; enum ComponentType { + CT_Character, CT_Effect, CT_Fighting, CT_Item, diff --git a/src/game-server/gamehandler.cpp b/src/game-server/gamehandler.cpp index 9cec7728..55588b61 100644 --- a/src/game-server/gamehandler.cpp +++ b/src/game-server/gamehandler.cpp @@ -71,27 +71,28 @@ void GameHandler::computerDisconnected(NetComputer *comp) { mTokenCollector.deletePendingClient(&computer); } - else if (Character *ch = computer.character) + else if (Entity *ch = computer.character) { accountHandler->sendCharacterData(ch); - ch->disconnected(); + ch->getComponent<CharacterComponent>()->disconnected(*ch); delete ch; } delete &computer; } -void GameHandler::kill(Character *ch) +void GameHandler::kill(Entity *ch) { - GameClient *client = ch->getClient(); + auto *component = ch->getComponent<CharacterComponent>(); + GameClient *client = component->getClient(); assert(client); - client->character = NULL; + client->character = nullptr; client->status = CLIENT_LOGIN; - ch->setClient(0); + component->setClient(0); } -void GameHandler::prepareServerChange(Character *ch) +void GameHandler::prepareServerChange(Entity *ch) { - GameClient *client = ch->getClient(); + GameClient *client = ch->getComponent<CharacterComponent>()->getClient(); assert(client); client->status = CLIENT_CHANGE_SERVER; } @@ -104,14 +105,16 @@ void GameHandler::completeServerChange(int id, const std::string &token, { GameClient *c = static_cast< GameClient * >(*i); if (c->status == CLIENT_CHANGE_SERVER && - c->character->getDatabaseID() == id) + c->character->getComponent<CharacterComponent>() + ->getDatabaseID() == id) { MessageOut msg(GPMSG_PLAYER_SERVER_CHANGE); msg.writeString(token, MAGIC_TOKEN_LENGTH); msg.writeString(address); msg.writeInt16(port); c->send(msg); - c->character->disconnected(); + c->character->getComponent<CharacterComponent>()->disconnected( + *c->character); delete c->character; c->character = NULL; c->status = CLIENT_LOGIN; @@ -126,10 +129,11 @@ void GameHandler::updateCharacter(int charid, int partyid) i_end = clients.end(); i != i_end; ++i) { GameClient *c = static_cast< GameClient * >(*i); - if (c->character->getDatabaseID() == charid) - { - c->character->setParty(partyid); - } + auto *characterComponent = + c->character->getComponent<CharacterComponent>(); + + if (characterComponent->getDatabaseID() == charid) + characterComponent->setParty(partyid); } } @@ -165,7 +169,7 @@ static Being *findBeingNear(Actor *p, int id) return 0; } -static Character *findCharacterNear(Actor *p, int id) +static Being *findCharacterNear(Actor *p, int id) { MapComposite *map = p->getMap(); const Point &ppos = p->getPosition(); @@ -174,10 +178,14 @@ static Character *findCharacterNear(Actor *p, int id) for (CharacterIterator i(map->getAroundPointIterator(ppos, pixelDist)); i; ++i) { - Character *c = *i; + Being *c = *i; if (c->getPublicID() != id) continue; - return ppos.inRangeOf(c->getPosition(), pixelDist) ? c : 0; + + if (ppos.inRangeOf(c->getPosition(), pixelDist)) + return c; + + return 0; } return 0; } @@ -293,7 +301,8 @@ void GameHandler::processMessage(NetComputer *computer, MessageIn &message) case PGMSG_RESPAWN: // plausibility check is done by character class - client.character->respawn(); + client.character->getComponent<CharacterComponent>()->respawn( + *client.character); break; case PGMSG_NPC_POST_SEND: @@ -315,26 +324,34 @@ void GameHandler::processMessage(NetComputer *computer, MessageIn &message) } } -void GameHandler::sendTo(Character *beingPtr, MessageOut &msg) +void GameHandler::sendTo(Entity *beingPtr, MessageOut &msg) +{ + GameClient *client = beingPtr->getComponent<CharacterComponent>() + ->getClient(); + sendTo(client, msg); +} + +void GameHandler::sendTo(GameClient *client, MessageOut &msg) { - GameClient *client = beingPtr->getClient(); assert(client && client->status == CLIENT_CONNECTED); client->send(msg); } -void GameHandler::addPendingCharacter(const std::string &token, Character *ch) +void GameHandler::addPendingCharacter(const std::string &token, Being *ch) { /* First, check if the character is already on the map. This may happen if a client just lost its connection, and logged to the account server again, yet the game server has not yet detected the lost connection. */ - int id = ch->getDatabaseID(); + int id = ch->getComponent<CharacterComponent>()->getDatabaseID(); for (NetComputers::const_iterator i = clients.begin(), i_end = clients.end(); i != i_end; ++i) { GameClient *c = static_cast< GameClient * >(*i); - Character *old_ch = c->character; - if (old_ch && old_ch->getDatabaseID() == id) + Being *old_ch = c->character; + const int oldId = old_ch->getComponent<CharacterComponent>() + ->getDatabaseID(); + if (old_ch && oldId == id) { if (c->status != CLIENT_CONNECTED) { @@ -350,7 +367,7 @@ void GameHandler::addPendingCharacter(const std::string &token, Character *ch) it available for a new connection. */ delete ch; GameState::remove(old_ch); - kill(old_ch); + kill(ch); ch = old_ch; break; } @@ -360,12 +377,15 @@ void GameHandler::addPendingCharacter(const std::string &token, Character *ch) mTokenCollector.addPendingConnect(token, ch); } -void GameHandler::tokenMatched(GameClient *computer, Character *character) +void GameHandler::tokenMatched(GameClient *computer, Being *character) { computer->character = character; computer->status = CLIENT_CONNECTED; - character->setClient(computer); + auto *characterComponent = + character->getComponent<CharacterComponent>(); + + characterComponent->setClient(computer); MessageOut result(GPMSG_CONNECT_RESPONSE); @@ -378,14 +398,14 @@ void GameHandler::tokenMatched(GameClient *computer, Character *character) return; } // Trigger login script bind - character->triggerLoginCallback(); + characterComponent->triggerLoginCallback(*character); result.writeInt8(ERRMSG_OK); computer->send(result); // Force sending the whole character to the client. Inventory(character).sendFull(); - character->modifiedAllAttribute(); + characterComponent->modifiedAllAttributes(*character); } void GameHandler::deletePendingClient(GameClient *computer) @@ -401,18 +421,18 @@ void GameHandler::deletePendingClient(GameClient *computer) computer->disconnect(msg); } -void GameHandler::deletePendingConnect(Character *character) +void GameHandler::deletePendingConnect(Being *character) { delete character; } -Character *GameHandler::getCharacterByNameSlow(const std::string &name) const +Being *GameHandler::getCharacterByNameSlow(const std::string &name) const { for (NetComputers::const_iterator i = clients.begin(), i_end = clients.end(); i != i_end; ++i) { GameClient *c = static_cast< GameClient * >(*i); - Character *ch = c->character; + Being *ch = c->character; if (ch && ch->getName() == name && c->status == CLIENT_CONNECTED) { @@ -433,7 +453,7 @@ void GameHandler::handleSay(GameClient &client, MessageIn &message) CommandHandler::handleCommand(client.character, say); return; } - if (!client.character->isMuted()) + if (!client.character->getComponent<CharacterComponent>()->isMuted()) { GameState::sayAround(client.character, say); } @@ -518,9 +538,11 @@ void GameHandler::handlePickup(GameClient &client, MessageIn &message) std::stringstream str; str << "User picked up item " << ic->getDatabaseID() << " at " << opos.x << "x" << opos.y; + auto *characterComponent = client.character + ->getComponent<CharacterComponent>(); accountHandler->sendTransaction( - client.character->getDatabaseID(), - TRANS_ITEM_PICKUP, str.str() + characterComponent->getDatabaseID(), + TRANS_ITEM_PICKUP, str.str() ); } break; @@ -545,7 +567,9 @@ void GameHandler::handleUseItem(GameClient &client, MessageIn &message) std::stringstream str; str << "User activated item " << ic->getDatabaseID() << " from slot " << slot; - accountHandler->sendTransaction(client.character->getDatabaseID(), + auto *characterComponent = client.character + ->getComponent<CharacterComponent>(); + accountHandler->sendTransaction(characterComponent->getDatabaseID(), TRANS_ITEM_USED, str.str()); if (ic->useTrigger(client.character, ITT_ACTIVATE)) inv.removeFromSlot(slot, 1); @@ -588,7 +612,9 @@ void GameHandler::handleDrop(GameClient &client, MessageIn &message) std::stringstream str; str << "User dropped item " << ic->getDatabaseID() << " at " << pos.x << "x" << pos.y; - accountHandler->sendTransaction(client.character->getDatabaseID(), + auto *characterComponent = client.character + ->getComponent<CharacterComponent>(); + accountHandler->sendTransaction(characterComponent->getDatabaseID(), TRANS_ITEM_DROP, str.str()); } } @@ -637,7 +663,9 @@ void GameHandler::handleMoveItem(GameClient &client, MessageIn &message) std::stringstream str; str << "User moved item " << " from slot " << slot1 << " to slot " << slot2; - accountHandler->sendTransaction(client.character->getDatabaseID(), + auto *characterComponent = + client.character->getComponent<CharacterComponent>(); + accountHandler->sendTransaction(characterComponent->getDatabaseID(), TRANS_ITEM_MOVE, str.str()); } @@ -667,7 +695,9 @@ void GameHandler::handleUseSpecialOnBeing(GameClient &client, MessageIn &message being = findBeingNear(client.character, targetID); LOG_DEBUG("Character " << client.character->getPublicID() << " tries to use his special attack " << specialID); - client.character->useSpecialOnBeing(specialID, being); + auto *characterComponent = client.character + ->getComponent<CharacterComponent>(); + characterComponent->useSpecialOnBeing(*client.character, specialID, being); } void GameHandler::handleUseSpecialOnPoint(GameClient &client, MessageIn &message) @@ -681,7 +711,9 @@ void GameHandler::handleUseSpecialOnPoint(GameClient &client, MessageIn &message LOG_DEBUG("Character " << client.character->getPublicID() << " tries to use his special attack " << specialID); - client.character->useSpecialOnPoint(specialID, x, y); + auto *characterComponent = client.character + ->getComponent<CharacterComponent>(); + characterComponent->useSpecialOnPoint(*client.character, specialID, x, y); } void GameHandler::handleActionChange(GameClient &client, MessageIn &message) @@ -716,7 +748,11 @@ void GameHandler::handleActionChange(GameClient &client, MessageIn &message) // log transaction std::stringstream str; str << "User changed action from " << current << " to " << action; - accountHandler->sendTransaction(client.character->getDatabaseID(), + + auto *characterComponent = + client.character->getComponent<CharacterComponent>(); + + accountHandler->sendTransaction(characterComponent->getDatabaseID(), TRANS_ACTION_CHANGE, str.str()); } @@ -735,19 +771,21 @@ void GameHandler::handleDisconnect(GameClient &client, MessageIn &message) MessageOut result(GPMSG_DISCONNECT_RESPONSE); result.writeInt8(ERRMSG_OK); // It is, when control reaches here + auto *characterComponent = + client.character->getComponent<CharacterComponent>(); + if (reconnectAccount) { std::string magic_token(utils::getMagicToken()); result.writeString(magic_token, MAGIC_TOKEN_LENGTH); // No accountserver data, the client should remember that accountHandler->playerReconnectAccount( - client.character->getDatabaseID(), + characterComponent->getDatabaseID(), magic_token); } accountHandler->sendCharacterData(client.character); - // Done with the character, also handle possible respawn case - client.character->disconnected(); + characterComponent->disconnected(*client.character); delete client.character; client.character = 0; client.status = CLIENT_LOGIN; @@ -759,12 +797,15 @@ void GameHandler::handleTradeRequest(GameClient &client, MessageIn &message) { const int id = message.readInt16(); - if (Trade *t = client.character->getTrading()) + auto *characterComponent = + client.character->getComponent<CharacterComponent>(); + + if (Trade *t = characterComponent->getTrading()) if (t->request(client.character, id)) return; - Character *q = findCharacterNear(client.character, id); - if (!q || q->isBusy()) + Being *q = findCharacterNear(client.character, id); + if (!q || characterComponent->isBusy()) { client.send(MessageOut(GPMSG_TRADE_CANCEL)); return; @@ -775,14 +816,19 @@ void GameHandler::handleTradeRequest(GameClient &client, MessageIn &message) // log transaction std::string str; str = "User requested trade with " + q->getName(); - accountHandler->sendTransaction(client.character->getDatabaseID(), + accountHandler->sendTransaction(characterComponent->getDatabaseID(), TRANS_TRADE_REQUEST, str); } void GameHandler::handleTrade(GameClient &client, MessageIn &message) { + auto *characterComponent = + client.character->getComponent<CharacterComponent>(); + + int databaseId = characterComponent->getDatabaseID(); + std::stringstream str; - Trade *t = client.character->getTrading(); + Trade *t = characterComponent->getTrading(); if (!t) return; @@ -797,7 +843,7 @@ void GameHandler::handleTrade(GameClient &client, MessageIn &message) case PGMSG_TRADE_AGREED: t->agree(client.character); // log transaction - accountHandler->sendTransaction(client.character->getDatabaseID(), + accountHandler->sendTransaction(databaseId, TRANS_TRADE_END, "User finished trading"); break; @@ -807,7 +853,7 @@ void GameHandler::handleTrade(GameClient &client, MessageIn &message) t->setMoney(client.character, money); // log transaction str << "User added " << money << " money to trade."; - accountHandler->sendTransaction(client.character->getDatabaseID(), + accountHandler->sendTransaction(databaseId, TRANS_TRADE_MONEY, str.str()); } break; case PGMSG_TRADE_ADD_ITEM: @@ -816,7 +862,7 @@ void GameHandler::handleTrade(GameClient &client, MessageIn &message) t->addItem(client.character, slot, message.readInt8()); // log transaction str << "User add item from slot " << slot; - accountHandler->sendTransaction(client.character->getDatabaseID(), + accountHandler->sendTransaction(databaseId, TRANS_TRADE_ITEM, str.str()); } break; } @@ -824,7 +870,8 @@ void GameHandler::handleTrade(GameClient &client, MessageIn &message) void GameHandler::handleNpcBuySell(GameClient &client, MessageIn &message) { - BuySell *t = client.character->getBuySell(); + BuySell *t = client.character->getComponent<CharacterComponent>() + ->getBuySell(); if (!t) return; const int id = message.readInt16(); @@ -834,9 +881,13 @@ void GameHandler::handleNpcBuySell(GameClient &client, MessageIn &message) void GameHandler::handleRaiseAttribute(GameClient &client, MessageIn &message) { + auto *characterComponent = + client.character->getComponent<CharacterComponent>(); + const int attribute = message.readInt16(); AttribmodResponseCode retCode; - retCode = client.character->useCharacterPoint(attribute); + retCode = characterComponent->useCharacterPoint(*client.character, + attribute); MessageOut result(GPMSG_RAISE_ATTRIBUTE_RESPONSE); result.writeInt8(retCode); @@ -846,23 +897,27 @@ void GameHandler::handleRaiseAttribute(GameClient &client, MessageIn &message) if (retCode == ATTRIBMOD_OK) { accountHandler->updateCharacterPoints( - client.character->getDatabaseID(), - client.character->getCharacterPoints(), - client.character->getCorrectionPoints()); + characterComponent->getDatabaseID(), + characterComponent->getCharacterPoints(), + characterComponent->getCorrectionPoints()); // log transaction std::stringstream str; str << "User increased attribute " << attribute; - accountHandler->sendTransaction(client.character->getDatabaseID(), + accountHandler->sendTransaction(characterComponent->getDatabaseID(), TRANS_ATTR_INCREASE, str.str()); } } void GameHandler::handleLowerAttribute(GameClient &client, MessageIn &message) { + auto *characterComponent = + client.character->getComponent<CharacterComponent>(); + const int attribute = message.readInt32(); AttribmodResponseCode retCode; - retCode = client.character->useCorrectionPoint(attribute); + retCode = characterComponent->useCorrectionPoint(*client.character, + attribute); MessageOut result(GPMSG_LOWER_ATTRIBUTE_RESPONSE); result.writeInt8(retCode); @@ -872,14 +927,14 @@ void GameHandler::handleLowerAttribute(GameClient &client, MessageIn &message) if (retCode == ATTRIBMOD_OK) { accountHandler->updateCharacterPoints( - client.character->getDatabaseID(), - client.character->getCharacterPoints(), - client.character->getCorrectionPoints()); + characterComponent->getDatabaseID(), + characterComponent->getCharacterPoints(), + characterComponent->getCorrectionPoints()); // log transaction std::stringstream str; str << "User decreased attribute " << attribute; - accountHandler->sendTransaction(client.character->getDatabaseID(), + accountHandler->sendTransaction(characterComponent->getDatabaseID(), TRANS_ATTR_DECREASE, str.str()); } } diff --git a/src/game-server/gamehandler.h b/src/game-server/gamehandler.h index c05e0087..70facb4c 100644 --- a/src/game-server/gamehandler.h +++ b/src/game-server/gamehandler.h @@ -38,7 +38,7 @@ struct GameClient: NetComputer { GameClient(ENetPeer *peer) : NetComputer(peer), character(NULL), status(CLIENT_LOGIN) {} - Character *character; + Being *character; int status; }; @@ -58,17 +58,18 @@ class GameHandler: public ConnectionHandler /** * Sends message to the given character. */ - void sendTo(Character *, MessageOut &msg); + void sendTo(Entity *, MessageOut &msg); + void sendTo(GameClient *, MessageOut &msg); /** * Kills connection with given character. */ - void kill(Character *); + void kill(Entity *); /** * Prepares a server change for given character. */ - void prepareServerChange(Character *); + void prepareServerChange(Entity *); /** * Completes a server change for given character ID. @@ -85,13 +86,13 @@ class GameHandler: public ConnectionHandler * Registers a character that should soon be claimed by a client. * @param token token used by the client when connecting. */ - void addPendingCharacter(const std::string &token, Character *); + void addPendingCharacter(const std::string &token, Being *); /** * Combines a client with its character. * (Needed for TokenCollector) */ - void tokenMatched(GameClient *computer, Character *character); + void tokenMatched(GameClient *computer, Being *character); /** * Deletes a pending client's data. @@ -103,13 +104,13 @@ class GameHandler: public ConnectionHandler * Deletes a pending connection's data. * (Needed for TokenCollector) */ - void deletePendingConnect(Character *character); + void deletePendingConnect(Being *character); /** * Gets the character associated to a character name. This method is * slow, so it should never be called for regular operations. */ - Character *getCharacterByNameSlow(const std::string &) const; + Being *getCharacterByNameSlow(const std::string &) const; protected: NetComputer *computerConnected(ENetPeer *); @@ -160,7 +161,7 @@ class GameHandler: public ConnectionHandler /** * Container for pending clients and pending connections. */ - TokenCollector<GameHandler, GameClient *, Character *> mTokenCollector; + TokenCollector<GameHandler, GameClient *, Being *> mTokenCollector; }; extern GameHandler *gameHandler; diff --git a/src/game-server/inventory.cpp b/src/game-server/inventory.cpp index e14a36af..2219ada1 100644 --- a/src/game-server/inventory.cpp +++ b/src/game-server/inventory.cpp @@ -29,8 +29,15 @@ #include "net/messageout.h" #include "utils/logger.h" -Inventory::Inventory(Character *p): - mPoss(&p->getPossessions()), mCharacter(p) +Inventory::Inventory(Being *p): + mPoss(&p->getComponent<CharacterComponent>()->getPossessions()), + mCharacter(p) +{ +} + +Inventory::Inventory(Being *p, Possessions &possessions): + mPoss(&possessions), + mCharacter(p) { } diff --git a/src/game-server/inventory.h b/src/game-server/inventory.h index 42856bff..75336ace 100644 --- a/src/game-server/inventory.h +++ b/src/game-server/inventory.h @@ -36,7 +36,8 @@ class Inventory /** * Creates a view on the possessions of a character. */ - Inventory(Character *); + explicit Inventory(Being *); + Inventory(Being *, Possessions &possessions); /** * Commits delayed changes if applicable. @@ -189,7 +190,7 @@ class Inventory Possessions *mPoss; /**< Pointer to the modified possessions. */ - Character *mCharacter; /**< Character to notify. */ + Being *mCharacter; /**< Character to notify. */ }; #endif diff --git a/src/game-server/mapcomposite.cpp b/src/game-server/mapcomposite.cpp index bb7093b2..e35c68fb 100644 --- a/src/game-server/mapcomposite.cpp +++ b/src/game-server/mapcomposite.cpp @@ -182,7 +182,7 @@ CharacterIterator::CharacterIterator(const ZoneIterator &it) while (iterator && (*iterator)->nbCharacters == 0) ++iterator; if (iterator) { - current = static_cast< Character * >((*iterator)->objects[pos]); + current = static_cast< Being * >((*iterator)->objects[pos]); } } @@ -195,7 +195,7 @@ void CharacterIterator::operator++() } if (iterator) { - current = static_cast< Character * >((*iterator)->objects[pos]); + current = static_cast< Being * >((*iterator)->objects[pos]); } } diff --git a/src/game-server/mapcomposite.h b/src/game-server/mapcomposite.h index ba76ddc8..c8eb2e88 100644 --- a/src/game-server/mapcomposite.h +++ b/src/game-server/mapcomposite.h @@ -31,7 +31,7 @@ class Actor; class Being; -class Character; +class CharacterComponent; class Map; class MapComposite; class Point; @@ -76,11 +76,11 @@ struct CharacterIterator { ZoneIterator iterator; unsigned short pos; - Character *current; + Being *current; CharacterIterator(const ZoneIterator &); void operator++(); - Character *operator*() const { return current; } + Being *operator*() const { return current; } operator bool() const { return iterator; } }; diff --git a/src/game-server/monster.cpp b/src/game-server/monster.cpp index 9e45bb1d..39b62593 100644 --- a/src/game-server/monster.cpp +++ b/src/game-server/monster.cpp @@ -307,7 +307,7 @@ void MonsterComponent::forgetTarget(Entity *entity) if (b->getType() == OBJECT_CHARACTER) { - Character *c = static_cast< Character * >(b); + Being *c = static_cast< Being * >(b); mExpReceivers.erase(c); mLegalExpReceivers.erase(c); } @@ -376,7 +376,7 @@ void MonsterComponent::monsterDied(Being *monster) } // Distribute exp reward. - std::map<Character *, std::set <size_t> > ::iterator iChar; + std::map<Being *, std::set <size_t> > ::iterator iChar; std::set<size_t>::iterator iSkill; @@ -385,21 +385,24 @@ void MonsterComponent::monsterDied(Being *monster) for (iChar = mExpReceivers.begin(); iChar != mExpReceivers.end(); iChar++) { - Character *character = (*iChar).first; + auto *character = (*iChar).first; const std::set<size_t> &skillSet = (*iChar).second; if (mLegalExpReceivers.find(character) == mLegalExpReceivers.end() || skillSet.empty()) continue; + auto characterComponent = + character->getComponent<CharacterComponent>(); + int expPerSkill = int(expPerChar / skillSet.size()); for (iSkill = skillSet.begin(); iSkill != skillSet.end(); iSkill++) { - character->receiveExperience(*iSkill, expPerSkill, - mSpecy->getOptimalLevel()); + characterComponent->receiveExperience(*iSkill, expPerSkill, + mSpecy->getOptimalLevel()); } - character->incrementKillCount(mSpecy->getId()); + characterComponent->incrementKillCount(mSpecy->getId()); } } } @@ -412,14 +415,13 @@ void MonsterComponent::receivedDamage(Being *source, const Damage &damage, int h if (hpLoss && source && source->getType() == OBJECT_CHARACTER) { - Character *s = static_cast< Character * >(source); - - mExpReceivers[s].insert(damage.skill); - if (mKillStealProtectedTimeout.expired() || mOwner == s - || mOwner->getParty() == s->getParty()) + mExpReceivers[source].insert(damage.skill); + if (mKillStealProtectedTimeout.expired() || mOwner == source + || mOwner->getComponent<CharacterComponent>()->getParty() == + source->getComponent<CharacterComponent>()->getParty()) { - mOwner = s; - mLegalExpReceivers.insert(s); + mOwner = source; + mLegalExpReceivers.insert(source); mKillStealProtectedTimeout.set(KILLSTEAL_PROTECTION_TIME); } } diff --git a/src/game-server/monster.h b/src/game-server/monster.h index d1c8e900..e4d986b3 100644 --- a/src/game-server/monster.h +++ b/src/game-server/monster.h @@ -33,7 +33,7 @@ #include <sigc++/connection.h> -class Character; +class CharacterComponent; class ItemClass; class Script; @@ -275,7 +275,7 @@ struct AttackPosition class MonsterComponent : public Component { public: - static const ComponentType type = CT_Monster; + static const ComponentType type = CT_Monster; /** Time in game ticks until ownership of a monster can change. */ static const int KILLSTEAL_PROTECTION_TIME = 100; @@ -339,16 +339,16 @@ class MonsterComponent : public Component /** * Character who currently owns this monster (killsteal protection). */ - Character *mOwner; + Being *mOwner; /** List of characters and their skills that attacked this monster. */ - std::map<Character *, std::set <size_t> > mExpReceivers; + std::map<Being *, std::set <size_t> > mExpReceivers; /** * List of characters who are entitled to receive exp (killsteal * protection). */ - std::set<Character *> mLegalExpReceivers; + std::set<Being *> mLegalExpReceivers; /** * Set positions relative to target from which the monster can attack. diff --git a/src/game-server/npc.cpp b/src/game-server/npc.cpp index 788f0c95..e7a2988b 100644 --- a/src/game-server/npc.cpp +++ b/src/game-server/npc.cpp @@ -73,9 +73,10 @@ void NpcComponent::setUpdateCallback(Script::Ref function) -static Script *prepareResume(Character *ch, Script::ThreadState expectedState) +static Script *prepareResume(Being *ch, Script::ThreadState expectedState) { - Script::Thread *thread = ch->getNpcThread(); + Script::Thread *thread = + ch->getComponent<CharacterComponent>()->getNpcThread(); if (!thread || thread->mState != expectedState) return 0; @@ -84,7 +85,7 @@ static Script *prepareResume(Character *ch, Script::ThreadState expectedState) return script; } -void Npc::start(Being *npc, Character *ch) +void Npc::start(Being *npc, Being *ch) { NpcComponent *npcComponent = npc->getComponent<NpcComponent>(); @@ -98,30 +99,31 @@ void Npc::start(Being *npc, Character *ch) script->prepare(talkCallback); script->push(npc); script->push(ch); - ch->startNpcThread(thread, npc->getPublicID()); + ch->getComponent<CharacterComponent>() + ->startNpcThread(thread, npc->getPublicID()); } } -void Npc::resume(Character *ch) +void Npc::resume(Being *ch) { if (prepareResume(ch, Script::ThreadPaused)) - ch->resumeNpcThread(); + ch->getComponent<CharacterComponent>()->resumeNpcThread(); } -void Npc::integerReceived(Character *ch, int value) +void Npc::integerReceived(Being *ch, int value) { if (Script *script = prepareResume(ch, Script::ThreadExpectingNumber)) { script->push(value); - ch->resumeNpcThread(); + ch->getComponent<CharacterComponent>()->resumeNpcThread(); } } -void Npc::stringReceived(Character *ch, const std::string &value) +void Npc::stringReceived(Being *ch, const std::string &value) { if (Script *script = prepareResume(ch, Script::ThreadExpectingString)) { script->push(value); - ch->resumeNpcThread(); + ch->getComponent<CharacterComponent>()->resumeNpcThread(); } } diff --git a/src/game-server/npc.h b/src/game-server/npc.h index 1a0b4e8e..63d4ee8b 100644 --- a/src/game-server/npc.h +++ b/src/game-server/npc.h @@ -25,7 +25,7 @@ #include "game-server/component.h" #include "scripting/script.h" -class Character; +class CharacterComponent; /** * Component describing a non-player character. @@ -88,22 +88,22 @@ namespace Npc { /** * Starts a conversation with the NPC. */ -void start(Being *npc, Character *ch); +void start(Being *npc, Being *ch); /** * Resumes an NPC conversation. */ -void resume(Character *ch); +void resume(Being *ch); /** * The player has made a choice or entered an integer. */ -void integerReceived(Character *ch, int value); +void integerReceived(Being *ch, int value); /** * The player has entered an string. */ -void stringReceived(Character *ch, const std::string &value); +void stringReceived(Being *ch, const std::string &value); } // namespace Npc diff --git a/src/game-server/postman.h b/src/game-server/postman.h index b9cf7bb2..8862ccf6 100644 --- a/src/game-server/postman.h +++ b/src/game-server/postman.h @@ -24,12 +24,12 @@ #include <map> #include <string> -class Character; +class Being; class Script; struct PostCallback { - void (*handler)(Character *, + void (*handler)(Being *, const std::string &sender, const std::string &letter, Script *); @@ -40,32 +40,35 @@ struct PostCallback class PostMan { public: - Character *getCharacter(int id) const + Being *getCharacter(int id) const { - std::map<int, Character*>::const_iterator itr = mCharacters.find(id); + std::map<int, Being*>::const_iterator itr = mCharacters.find(id); if (itr != mCharacters.end()) return itr->second; return 0; } - void addCharacter(Character *player) + void addCharacter(Entity *player) { - std::map<int, Character*>::iterator itr = mCharacters.find(player->getDatabaseID()); + int dataBaseId = player->getComponent<CharacterComponent>() + ->getDatabaseID(); + std::map<int, Being*>::iterator itr = mCharacters.find(dataBaseId); if (itr == mCharacters.end()) { - mCharacters.insert(std::pair<int, Character*>(player->getDatabaseID(), player)); + Being *being = static_cast<Being *>(player); + mCharacters.insert(std::pair<int, Being*>(dataBaseId, being)); } } - void getPost(Character *player, PostCallback &f) + void getPost(Being *player, PostCallback &f) { - mCallbacks.insert(std::pair<Character*, PostCallback>(player, f)); + mCallbacks.insert(std::pair<Being*, PostCallback>(player, f)); accountHandler->getPost(player); } - void gotPost(Character *player, std::string sender, std::string letter) + void gotPost(Being *player, std::string sender, std::string letter) { - std::map<Character*, PostCallback>::iterator itr = mCallbacks.find(player); + std::map<Being*, PostCallback>::iterator itr = mCallbacks.find(player); if (itr != mCallbacks.end()) { itr->second.handler(player, sender, letter, itr->second.script); @@ -73,8 +76,8 @@ public: } private: - std::map<int, Character*> mCharacters; - std::map<Character*, PostCallback> mCallbacks; + std::map<int, Being*> mCharacters; + std::map<Being*, PostCallback> mCallbacks; }; extern PostMan *postMan; diff --git a/src/game-server/quest.cpp b/src/game-server/quest.cpp index d6d7d92d..803ec60b 100644 --- a/src/game-server/quest.cpp +++ b/src/game-server/quest.cpp @@ -36,7 +36,7 @@ typedef std::map< std::string, QuestCallbacks > PendingVariables; struct PendingQuest { - Character *character; + Being *character; sigc::connection removedConnection; sigc::connection disconnectedConnection; PendingVariables variables; @@ -46,23 +46,27 @@ typedef std::map< int, PendingQuest > PendingQuests; static PendingQuests pendingQuests; -bool getQuestVar(Character *ch, const std::string &name, std::string &value) +bool getQuestVar(Being *ch, const std::string &name, std::string &value) { std::map< std::string, std::string >::iterator - i = ch->questCache.find(name); - if (i == ch->questCache.end()) return false; + i = ch->getComponent<CharacterComponent>()->questCache.find(name); + if (i == ch->getComponent<CharacterComponent>()->questCache.end()) + return false; value = i->second; return true; } -void setQuestVar(Character *ch, const std::string &name, +void setQuestVar(Being *ch, const std::string &name, const std::string &value) { + auto *characterComponent = + ch->getComponent<CharacterComponent>(); + std::map< std::string, std::string >::iterator - i = ch->questCache.lower_bound(name); - if (i == ch->questCache.end() || i->first != name) + i = characterComponent->questCache.lower_bound(name); + if (i == characterComponent->questCache.end() || i->first != name) { - ch->questCache.insert(i, std::make_pair(name, value)); + characterComponent->questCache.insert(i, std::make_pair(name, value)); } else if (i->second == value) { @@ -75,7 +79,7 @@ void setQuestVar(Character *ch, const std::string &name, accountHandler->updateCharacterVar(ch, name, value); } -void QuestRefCallback::triggerCallback(Character *ch, +void QuestRefCallback::triggerCallback(Being *ch, const std::string &value) const { if (!mRef.isValid()) @@ -91,7 +95,7 @@ void QuestRefCallback::triggerCallback(Character *ch, static void partialRemove(Entity *t) { - int id = static_cast< Character * >(t)->getDatabaseID(); + int id = t->getComponent<CharacterComponent>()->getDatabaseID(); PendingVariables &variables = pendingQuests[id].variables; // Remove all the callbacks, but do not remove the variable names. for (PendingVariables::iterator i = variables.begin(), @@ -102,9 +106,9 @@ static void partialRemove(Entity *t) // The listener is kept in case a fullRemove is needed later. } -static void fullRemove(Character *ch) +static void fullRemove(Entity &ch) { - int id = ch->getDatabaseID(); + int id = ch.getComponent<CharacterComponent>()->getDatabaseID(); { PendingQuest &pendingQuest = pendingQuests[id]; @@ -116,11 +120,15 @@ static void fullRemove(Character *ch) pendingQuests.erase(id); } -void recoverQuestVar(Character *ch, const std::string &name, +void recoverQuestVar(Being *ch, const std::string &name, QuestCallback *f) { - assert(ch->questCache.find(name) == ch->questCache.end()); - int id = ch->getDatabaseID(); + auto *characterComponent = + ch->getComponent<CharacterComponent>(); + + assert(characterComponent->questCache.find(name) == + characterComponent->questCache.end()); + int id = ch->getComponent<CharacterComponent>()->getDatabaseID(); PendingQuests::iterator i = pendingQuests.lower_bound(id); if (i == pendingQuests.end() || i->first != id) { @@ -134,7 +142,8 @@ void recoverQuestVar(Character *ch, const std::string &name, pendingQuest.removedConnection = ch->signal_removed.connect(sigc::ptr_fun(partialRemove)); pendingQuest.disconnectedConnection = - ch->signal_disconnected.connect(sigc::ptr_fun(fullRemove)); + characterComponent->signal_disconnected.connect( + sigc::ptr_fun(fullRemove)); i = pendingQuests.insert(i, std::make_pair(id, pendingQuest)); } @@ -162,8 +171,9 @@ void recoveredQuestVar(int id, return; } - Character *ch = pendingQuest.character; - ch->questCache[name] = value; + Being *ch = pendingQuest.character; + auto *characterComponent = ch->getComponent<CharacterComponent>(); + characterComponent->questCache[name] = value; // Call the registered callbacks. for (QuestCallbacks::const_iterator k = j->second.begin(), diff --git a/src/game-server/quest.h b/src/game-server/quest.h index 0d130789..13f91cc2 100644 --- a/src/game-server/quest.h +++ b/src/game-server/quest.h @@ -25,7 +25,7 @@ #include "scripting/scriptmanager.h" -class Character; +class Being; class Script; @@ -35,14 +35,14 @@ class QuestCallback virtual ~QuestCallback() { } - virtual void triggerCallback(Character *ch, + virtual void triggerCallback(Being *ch, const std::string &value) const = 0; }; class QuestThreadCallback : public QuestCallback { public: - typedef void (*Handler)(Character *, + typedef void (*Handler)(Being *, const std::string &value, Script *mScript); @@ -52,7 +52,7 @@ class QuestThreadCallback : public QuestCallback mScript(script) { } - void triggerCallback(Character *ch, const std::string &value) const + void triggerCallback(Being *ch, const std::string &value) const { mHandler(ch, value, mScript); } private: @@ -67,7 +67,7 @@ class QuestRefCallback : public QuestCallback mQuestName(questName) { script->assignCallback(mRef); } - void triggerCallback(Character *ch, const std::string &value) const; + void triggerCallback(Being *ch, const std::string &value) const; private: Script::Ref mRef; @@ -78,19 +78,18 @@ class QuestRefCallback : public QuestCallback * Gets the value associated to a quest variable. * @return false if no value was in cache. */ -bool getQuestVar(Character *, const std::string &name, std::string &value); +bool getQuestVar(Being *, const std::string &name, std::string &value); /** * Sets the value associated to a quest variable. */ -void setQuestVar(Character *, const std::string &name, - const std::string &value); +void setQuestVar(Being *, const std::string &name, const std::string &value); /** * Starts the recovery of a variable and returns immediatly. The callback will * be called once the value has been recovered. */ -void recoverQuestVar(Character *, const std::string &name, QuestCallback *); +void recoverQuestVar(Being *, const std::string &name, QuestCallback *); /** * Called by the handler of the account server when a value is received. diff --git a/src/game-server/state.cpp b/src/game-server/state.cpp index 74bd87e4..f1ed99a0 100644 --- a/src/game-server/state.cpp +++ b/src/game-server/state.cpp @@ -79,9 +79,10 @@ static std::map< std::string, std::string > mScriptVariables; /** * Sets message fields describing character look. */ -static void serializeLooks(Character *ch, MessageOut &msg) +static void serializeLooks(Being *ch, MessageOut &msg) { - const EquipData &equipData = ch->getPossessions().getEquipment(); + const EquipData &equipData = ch->getComponent<CharacterComponent>() + ->getPossessions().getEquipment(); // We'll use a set to check whether we already sent the update for the given // item instance. @@ -127,7 +128,7 @@ static void serializeLooks(Character *ch, MessageOut &msg) /** * Informs a player of what happened around the character. */ -static void informPlayer(MapComposite *map, Character *p) +static void informPlayer(MapComposite *map, Being *p) { MessageOut moveMsg(GPMSG_BEINGS_MOVE); MessageOut damageMsg(GPMSG_BEINGS_DAMAGE); @@ -186,11 +187,12 @@ static void informPlayer(MapComposite *map, Character *p) { MessageOut LooksMsg(GPMSG_BEING_LOOKS_CHANGE); LooksMsg.writeInt16(oid); - Character * c = static_cast<Character * >(o); - serializeLooks(c, LooksMsg); - LooksMsg.writeInt16(c->getHairStyle()); - LooksMsg.writeInt16(c->getHairColor()); - LooksMsg.writeInt16(c->getGender()); + serializeLooks(o, LooksMsg); + auto *characterComponent = + o->getComponent<CharacterComponent>(); + LooksMsg.writeInt16(characterComponent->getHairStyle()); + LooksMsg.writeInt16(characterComponent->getHairColor()); + LooksMsg.writeInt16(o->getGender()); gameHandler->sendTo(p, LooksMsg); } @@ -261,11 +263,12 @@ static void informPlayer(MapComposite *map, Character *p) { case OBJECT_CHARACTER: { - Character *q = static_cast< Character * >(o); - enterMsg.writeString(q->getName()); - enterMsg.writeInt8(q->getHairStyle()); - enterMsg.writeInt8(q->getHairColor()); - serializeLooks(q, enterMsg); + auto *characterComponent = + o->getComponent<CharacterComponent>(); + enterMsg.writeString(o->getName()); + enterMsg.writeInt8(characterComponent->getHairStyle()); + enterMsg.writeInt8(characterComponent->getHairColor()); + serializeLooks(o, enterMsg); } break; case OBJECT_MONSTER: @@ -328,19 +331,20 @@ static void informPlayer(MapComposite *map, Character *p) gameHandler->sendTo(p, damageMsg); // Inform client about status change. - p->sendStatus(); + p->getComponent<CharacterComponent>()->sendStatus(*p); // Inform client about health change of party members for (CharacterIterator i(map->getWholeMapIterator()); i; ++i) { - Character *c = *i; + Being *c = *i; // Make sure its not the same character if (c == p) continue; // make sure they are in the same party - if (c->getParty() == p->getParty()) + if (c->getComponent<CharacterComponent>()->getParty() == + p->getComponent<CharacterComponent>()->getParty()) { int cflags = c->getUpdateFlags(); if (cflags & UPDATEFLAG_HEALTHCHANGE) @@ -487,9 +491,8 @@ void GameState::update(int tick) remove(o); if (o->getType() == OBJECT_CHARACTER) { - Character *ch = static_cast< Character * >(o); - ch->disconnected(); - gameHandler->kill(ch); + o->getComponent<CharacterComponent>()->disconnected(*o); + gameHandler->kill(o); } delete o; break; @@ -500,7 +503,7 @@ void GameState::update(int tick) case EVENT_WARP: assert(o->getType() == OBJECT_CHARACTER); - warp(static_cast< Character * >(o), e.map, e.point); + warp(static_cast<Being *>(o), e.map, e.point); break; } } @@ -593,11 +596,11 @@ bool GameState::insert(Entity *ptr) mapChangeMessage.writeString(map->getName()); mapChangeMessage.writeInt16(pos.x); mapChangeMessage.writeInt16(pos.y); - gameHandler->sendTo(static_cast< Character * >(obj), mapChangeMessage); + gameHandler->sendTo(ptr, mapChangeMessage); // update the online state of the character - accountHandler->updateOnlineStatus( - static_cast< Character * >(obj)->getDatabaseID(), true); + accountHandler->updateOnlineStatus(ptr->getComponent<CharacterComponent>() + ->getDatabaseID(), true); return true; } @@ -663,11 +666,13 @@ void GameState::remove(Entity *ptr) { if (ptr->getType() == OBJECT_CHARACTER) { - static_cast< Character * >(ptr)->cancelTransaction(); + auto *characterComponent = + ptr->getComponent<CharacterComponent>(); + characterComponent->cancelTransaction(); // remove characters online status accountHandler->updateOnlineStatus( - static_cast< Character * >(ptr)->getDatabaseID(), false); + characterComponent->getDatabaseID(), false); } Actor *obj = static_cast< Actor * >(ptr); @@ -706,7 +711,7 @@ void GameState::remove(Entity *ptr) map->remove(ptr); } -void GameState::warp(Character *ptr, MapComposite *map, const Point &point) +void GameState::warp(Being *ptr, MapComposite *map, const Point &point) { remove(ptr); ptr->setMap(map); @@ -717,16 +722,19 @@ void GameState::warp(Character *ptr, MapComposite *map, const Point &point) a disconnection. */ accountHandler->sendCharacterData(ptr); + auto *characterComponent = + ptr->getComponent<CharacterComponent>(); + // If the player has just left, The character pointer is also about // to be deleted. So we don't have to do anything else. - if (!ptr->isConnected()) + if (!characterComponent->isConnected()) return; if (map->isActive()) { if (!insert(ptr)) { - ptr->disconnected(); + characterComponent->disconnected(*ptr); gameHandler->kill(ptr); delete ptr; } @@ -734,7 +742,7 @@ void GameState::warp(Character *ptr, MapComposite *map, const Point &point) else { MessageOut msg(GAMSG_REDIRECT); - msg.writeInt32(ptr->getDatabaseID()); + msg.writeInt32(characterComponent->getDatabaseID()); accountHandler->send(msg); gameHandler->prepareServerChange(ptr); } @@ -770,13 +778,13 @@ void GameState::enqueueRemove(Actor *ptr) enqueueEvent(ptr, event); } -void GameState::enqueueWarp(Character *ptr, +void GameState::enqueueWarp(Being *ptr, MapComposite *map, const Point &point) { // When the player has just disconnected, better not wait for the pointer // to become invalid. - if (!ptr->isConnected()) + if (!ptr->getComponent<CharacterComponent>()->isConnected()) { warp(ptr, map, point); return; @@ -823,7 +831,7 @@ void GameState::sayTo(Actor *destination, Actor *source, const std::string &text } msg.writeString(text); - gameHandler->sendTo(static_cast< Character * >(destination), msg); + gameHandler->sendTo(destination, msg); } void GameState::sayToAll(const std::string &text) diff --git a/src/game-server/state.h b/src/game-server/state.h index e8ed30a8..512e9afd 100644 --- a/src/game-server/state.h +++ b/src/game-server/state.h @@ -26,7 +26,7 @@ #include <string> class Actor; -class Character; +class Being; class Entity; class ItemClass; class MapComposite; @@ -71,7 +71,7 @@ namespace GameState * @note No update may be in progress. * @note The character is destroyed, if needed. */ - void warp(Character *, MapComposite *, const Point &point); + void warp(Being *, MapComposite *, const Point &point); /** * Enqueues an insert event. @@ -90,7 +90,7 @@ namespace GameState * Enqueues a warp event. * @note The event will be executed at end of update. */ - void enqueueWarp(Character *, MapComposite *, const Point &point); + void enqueueWarp(Being *, MapComposite *, const Point &point); /** * Says something to an actor. diff --git a/src/game-server/trade.cpp b/src/game-server/trade.cpp index 042719b2..9e9e05fb 100644 --- a/src/game-server/trade.cpp +++ b/src/game-server/trade.cpp @@ -37,31 +37,31 @@ * TRADE_AGREE_WAIT : One player has agreed, waiting for the other one */ -Trade::Trade(Character *c1, Character *c2): +Trade::Trade(Being *c1, Being *c2): mChar1(c1), mChar2(c2), mMoney1(0), mMoney2(0), mState(TRADE_INIT), mCurrencyId(ATTR_GP) { MessageOut msg(GPMSG_TRADE_REQUEST); msg.writeInt16(c1->getPublicID()); - c2->getClient()->send(msg); - c1->setTrading(this); - c2->setTrading(this); + c2->getComponent<CharacterComponent>()->getClient()->send(msg); + c1->getComponent<CharacterComponent>()->setTrading(this); + c2->getComponent<CharacterComponent>()->setTrading(this); } Trade::~Trade() { - mChar1->setTrading(NULL); - mChar2->setTrading(NULL); + mChar1->getComponent<CharacterComponent>()->setTrading(nullptr); + mChar2->getComponent<CharacterComponent>()->setTrading(nullptr); } void Trade::cancel() { MessageOut msg(GPMSG_TRADE_CANCEL); - mChar1->getClient()->send(msg); - mChar2->getClient()->send(msg); + mChar1->getComponent<CharacterComponent>()->getClient()->send(msg); + mChar2->getComponent<CharacterComponent>()->getClient()->send(msg); delete this; } -bool Trade::request(Character *c, int id) +bool Trade::request(Being *c, int id) { //The trade isn't confirmed, the player which is request is the same. if (mState != TRADE_INIT || c != mChar2 || mChar1->getPublicID() != id) @@ -79,8 +79,8 @@ bool Trade::request(Character *c, int id) //Telling both player that the trade has started MessageOut msg(GPMSG_TRADE_START); - mChar1->getClient()->send(msg); - mChar2->getClient()->send(msg); + mChar1->getComponent<CharacterComponent>()->getClient()->send(msg); + mChar2->getComponent<CharacterComponent>()->getClient()->send(msg); return true; } @@ -99,7 +99,7 @@ bool Trade::perform(TradedItems items, Inventory &inv1, Inventory &inv2) return true; } -void Trade::agree(Character *c) +void Trade::agree(Being *c) { // No player agreed if (mState == TRADE_CONFIRMED) @@ -116,7 +116,7 @@ void Trade::agree(Character *c) // Send the other player that the first player has confirmed MessageOut msg(GPMSG_TRADE_AGREED); - mChar2->getClient()->send(msg); + mChar2->getComponent<CharacterComponent>()->getClient()->send(msg); return; } @@ -148,12 +148,12 @@ void Trade::agree(Character *c) } MessageOut msg(GPMSG_TRADE_COMPLETE); - mChar1->getClient()->send(msg); - mChar2->getClient()->send(msg); + mChar1->getComponent<CharacterComponent>()->getClient()->send(msg); + mChar2->getComponent<CharacterComponent>()->getClient()->send(msg); delete this; } -void Trade::confirm(Character *c) +void Trade::confirm(Being *c) { if (mState == TRADE_CONFIRMED || mState == TRADE_AGREE_WAIT) return; @@ -173,7 +173,7 @@ void Trade::confirm(Character *c) //Send the other player that the first player has confirmed MessageOut msg(GPMSG_TRADE_CONFIRM); - mChar2->getClient()->send(msg); + mChar2->getComponent<CharacterComponent>()->getClient()->send(msg); return; } @@ -185,11 +185,11 @@ void Trade::confirm(Character *c) mState = TRADE_CONFIRMED; MessageOut msg(GPMSG_TRADE_BOTH_CONFIRM); - mChar1->getClient()->send(msg); - mChar2->getClient()->send(msg); + mChar1->getComponent<CharacterComponent>()->getClient()->send(msg); + mChar2->getComponent<CharacterComponent>()->getClient()->send(msg); } -void Trade::setMoney(Character *c, int amount) +void Trade::setMoney(Being *c, int amount) { //If the player has already confirmed, exit. if ((mState != TRADE_RUN && (mState != TRADE_CONFIRM_WAIT || c != mChar1)) @@ -205,26 +205,26 @@ void Trade::setMoney(Character *c, int amount) if (c == mChar1) { mMoney1 = amount; - mChar2->getClient()->send(msg); + mChar2->getComponent<CharacterComponent>()->getClient()->send(msg); } else { assert(c == mChar2); mMoney2 = amount; - mChar1->getClient()->send(msg); + mChar1->getComponent<CharacterComponent>()->getClient()->send(msg); } // Go back to normal run. mState = TRADE_RUN; } -void Trade::addItem(Character *c, int slot, int amount) +void Trade::addItem(Being *c, int slot, int amount) { //If the player has already confirmed, exit. if ((mState != TRADE_RUN && (mState != TRADE_CONFIRM_WAIT || c != mChar1)) || amount < 0) return; - Character *other; + Being *other; TradedItems *items; if (c == mChar1) { @@ -258,5 +258,5 @@ void Trade::addItem(Character *c, int slot, int amount) MessageOut msg(GPMSG_TRADE_ADD_ITEM); msg.writeInt16(id); msg.writeInt8(amount); - other->getClient()->send(msg); + other->getComponent<CharacterComponent>()->getClient()->send(msg); } diff --git a/src/game-server/trade.h b/src/game-server/trade.h index 3e5fb3a3..be527e86 100644 --- a/src/game-server/trade.h +++ b/src/game-server/trade.h @@ -23,7 +23,7 @@ #include <vector> -class Character; +class Being; class Inventory; class Trade @@ -34,7 +34,7 @@ class Trade * Sets up a trade between two characters. * Asks for an acknowledgment from the second one. */ - Trade(Character *, Character *); + Trade(Being *, Being *); /** * Cancels a trade by a given character (optional). @@ -49,27 +49,27 @@ class Trade * otherwise. * @return true if the current trade keeps going. */ - bool request(Character *, int); + bool request(Being *, int); /** * Confirm the trade. */ - void confirm(Character *); + void confirm(Being *); /* * Agree to complete the trade */ - void agree(Character *c); + void agree(Being *c); /** * Adds some items to the trade. */ - void addItem(Character *, int slot, int amount); + void addItem(Being *, int slot, int amount); /** * Adds some money to the trade. */ - void setMoney(Character *, int amount); + void setMoney(Being *, int amount); private: @@ -98,7 +98,7 @@ class Trade static bool perform(TradedItems items, Inventory &inv1, Inventory &inv2); - Character *mChar1, *mChar2; /**< Characters involved. */ + Being *mChar1, *mChar2; /**< Characters involved. */ TradedItems mItems1, mItems2; /**< Traded items. */ int mMoney1, mMoney2; /**< Traded money. */ TradeState mState; /**< State of transaction. */ diff --git a/src/game-server/triggerareacomponent.cpp b/src/game-server/triggerareacomponent.cpp index 7c32f097..d4736e4e 100644 --- a/src/game-server/triggerareacomponent.cpp +++ b/src/game-server/triggerareacomponent.cpp @@ -34,7 +34,7 @@ void WarpAction::process(Actor *obj) { if (obj->getType() == OBJECT_CHARACTER) { - GameState::enqueueWarp(static_cast< Character * >(obj), mMap, mTargetPoint); + GameState::enqueueWarp(static_cast<Being *>(obj), mMap, mTargetPoint); } } diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp index 993508a2..622d1867 100644 --- a/src/scripting/lua.cpp +++ b/src/scripting/lua.cpp @@ -120,7 +120,7 @@ static int on_recalculate_base_attribute(lua_State *s) static int on_character_death(lua_State *s) { luaL_checktype(s, 1, LUA_TFUNCTION); - Character::setDeathCallback(getScript(s)); + CharacterComponent::setDeathCallback(getScript(s)); return 0; } @@ -134,7 +134,7 @@ static int on_character_death(lua_State *s) static int on_character_death_accept(lua_State *s) { luaL_checktype(s, 1, LUA_TFUNCTION); - Character::setDeathAcceptedCallback(getScript(s)); + CharacterComponent::setDeathAcceptedCallback(getScript(s)); return 0; } @@ -147,7 +147,7 @@ static int on_character_death_accept(lua_State *s) static int on_character_login(lua_State *s) { luaL_checktype(s, 1, LUA_TFUNCTION); - Character::setLoginCallback(getScript(s)); + CharacterComponent::setLoginCallback(getScript(s)); return 0; } @@ -502,7 +502,7 @@ static int item_drop(lua_State *s) static int npc_message(lua_State *s) { Being *npc = checkNpc(s, 1); - Character *q = checkCharacter(s, 2); + Being *q = checkCharacter(s, 2); const char *m = luaL_checkstring(s, 3); Script::Thread *thread = checkCurrentThread(s); @@ -535,7 +535,7 @@ static int npc_message(lua_State *s) static int npc_choice(lua_State *s) { Being *npc = checkNpc(s, 1); - Character *q = checkCharacter(s, 2); + Being *q = checkCharacter(s, 2); Script::Thread *thread = checkCurrentThread(s); @@ -591,7 +591,7 @@ static int npc_choice(lua_State *s) static int npc_ask_integer(lua_State *s) { Being *npc = checkNpc(s, 1); - Character *q = checkCharacter(s, 2); + Being *q = checkCharacter(s, 2); int min = luaL_checkint(s, 3); int max = luaL_checkint(s, 4); int defaultValue = luaL_optint(s, 5, min); @@ -621,7 +621,7 @@ static int npc_ask_integer(lua_State *s) static int npc_ask_string(lua_State *s) { Being *npc = checkNpc(s, 1); - Character *q = checkCharacter(s, 2); + Being *q = checkCharacter(s, 2); Script::Thread *thread = checkCurrentThread(s); @@ -641,7 +641,7 @@ static int npc_ask_string(lua_State *s) static int npc_post(lua_State *s) { Being *npc = checkNpc(s, 1); - Character *q = checkCharacter(s, 2); + Being *q = checkCharacter(s, 2); MessageOut msg(GPMSG_NPC_POST); msg.writeInt16(npc->getPublicID()); @@ -768,7 +768,7 @@ static int announce(lua_State *s) static int npc_trade(lua_State *s) { Being *npc = checkNpc(s, 1); - Character *q = checkCharacter(s, 2); + Being *q = checkCharacter(s, 2); if (!lua_isboolean(s, 3)) { luaL_error(s, "npc_trade called with incorrect parameters."); @@ -892,7 +892,7 @@ static int npc_trade(lua_State *s) */ static int chr_inv_count(lua_State *s) { - Character *q = checkCharacter(s, 1); + Being *q = checkCharacter(s, 1); if (!lua_isboolean(s, 2) || !lua_isboolean(s, 3)) { luaL_error(s, "chr_inv_count called with incorrect parameters."); @@ -933,7 +933,7 @@ static int chr_inv_count(lua_State *s) */ static int chr_inv_change(lua_State *s) { - Character *q = checkCharacter(s, 1); + Being *q = checkCharacter(s, 1); int nb_items = (lua_gettop(s) - 1) / 2; Inventory inv(q); for (int i = 0; i < nb_items; ++i) @@ -997,10 +997,11 @@ static int chr_inv_change(lua_State *s) */ static int chr_get_inventory(lua_State *s) { - Character *q = checkCharacter(s, 1); + Being *q = checkCharacter(s, 1); // Create a lua table with the inventory ids. - const InventoryData invData = q->getPossessions().getInventory(); + const InventoryData invData = q->getComponent<CharacterComponent>() + ->getPossessions().getInventory(); lua_newtable(s); int firstTableStackPosition = lua_gettop(s); @@ -1061,10 +1062,11 @@ static int chr_get_inventory(lua_State *s) */ static int chr_get_equipment(lua_State *s) { - Character *q = checkCharacter(s, 1); + Being *q = checkCharacter(s, 1); // Create a lua table with the inventory ids. - const EquipData equipData = q->getPossessions().getEquipment(); + const EquipData equipData = q->getComponent<CharacterComponent>() + ->getPossessions().getEquipment(); lua_newtable(s); int firstTableStackPosition = lua_gettop(s); @@ -1113,7 +1115,7 @@ static int chr_get_equipment(lua_State *s) */ static int chr_equip_slot(lua_State *s) { - Character *ch = checkCharacter(s, 1); + Being *ch = checkCharacter(s, 1); int inventorySlot = luaL_checkint(s, 2); Inventory inv(ch); @@ -1132,7 +1134,7 @@ static int chr_equip_slot(lua_State *s) */ static int chr_equip_item(lua_State *s) { - Character *ch = checkCharacter(s, 1); + Being *ch = checkCharacter(s, 1); ItemClass *it = checkItemClass(s, 2); Inventory inv(ch); @@ -1156,7 +1158,7 @@ static int chr_equip_item(lua_State *s) */ static int chr_unequip_slot(lua_State *s) { - Character *ch = checkCharacter(s, 1); + Being *ch = checkCharacter(s, 1); int equipmentSlot = luaL_checkint(s, 2); Inventory inv(ch); @@ -1176,7 +1178,7 @@ static int chr_unequip_slot(lua_State *s) */ static int chr_unequip_item(lua_State *s) { - Character *ch = checkCharacter(s, 1); + Being *ch = checkCharacter(s, 1); ItemClass *it = checkItemClass(s, 2); Inventory inv(ch); @@ -1197,7 +1199,7 @@ static int chr_unequip_item(lua_State *s) */ static int chr_get_quest(lua_State *s) { - Character *q = checkCharacter(s, 1); + Being *q = checkCharacter(s, 1); const char *name = luaL_checkstring(s, 2); luaL_argcheck(s, name[0] != 0, 2, "empty variable name"); @@ -1226,7 +1228,7 @@ static int chr_get_quest(lua_State *s) */ static int chr_set_quest(lua_State *s) { - Character *q = checkCharacter(s, 1); + Being *q = checkCharacter(s, 1); const char *name = luaL_checkstring(s, 2); const char *value = luaL_checkstring(s, 3); luaL_argcheck(s, name[0] != 0, 2, "empty variable name"); @@ -1246,11 +1248,12 @@ static int chr_set_quest(lua_State *s) */ static int chr_set_special_recharge_speed(lua_State *s) { - Character *c = checkCharacter(s, 1); + Being *c = checkCharacter(s, 1); const int special = checkSpecial(s, 2); const int speed = luaL_checkint(s, 3); - if (!c->setSpecialRechargeSpeed(special, speed)) + if (!c->getComponent<CharacterComponent>() + ->setSpecialRechargeSpeed(special, speed)) { luaL_error(s, "chr_set_special_recharge_speed called with special " @@ -1271,12 +1274,14 @@ static int chr_set_special_recharge_speed(lua_State *s) */ static int chr_get_special_recharge_speed(lua_State *s) { - Character *c = checkCharacter(s, 1); + Being *c = checkCharacter(s, 1); const int special = checkSpecial(s, 2); - SpecialMap::iterator it = c->findSpecial(special); + auto *characterComponent = c->getComponent<CharacterComponent>(); - luaL_argcheck(s, it != c->getSpecialEnd(), 2, + SpecialMap::iterator it = characterComponent->findSpecial(special); + + luaL_argcheck(s, it != characterComponent->getSpecialEnd(), 2, "character does not have special"); lua_pushinteger(s, it->second.rechargeSpeed); @@ -1295,10 +1300,10 @@ static int chr_get_special_recharge_speed(lua_State *s) */ static int chr_set_special_mana(lua_State *s) { - Character *c = checkCharacter(s, 1); + Being *c = checkCharacter(s, 1); const int special = checkSpecial(s, 2); const int mana = luaL_checkint(s, 3); - if (!c->setSpecialMana(special, mana)) + if (!c->getComponent<CharacterComponent>()->setSpecialMana(special, mana)) { luaL_error(s, "chr_set_special_mana called with special " @@ -1319,10 +1324,11 @@ static int chr_set_special_mana(lua_State *s) */ static int chr_get_special_mana(lua_State *s) { - Character *c = checkCharacter(s, 1); + Being *c = checkCharacter(s, 1); + auto *characterComponent = c->getComponent<CharacterComponent>(); const int special = checkSpecial(s, 2); - SpecialMap::iterator it = c->findSpecial(special); - luaL_argcheck(s, it != c->getSpecialEnd(), 2, + SpecialMap::iterator it = characterComponent->findSpecial(special); + luaL_argcheck(s, it != characterComponent->getSpecialEnd(), 2, "character does not have special"); lua_pushinteger(s, it->second.currentMana); return 1; @@ -1610,7 +1616,7 @@ static int being_get_walkmask(lua_State *s) */ static int chr_warp(lua_State *s) { - Character *q = checkCharacter(s, 1); + Being *q = checkCharacter(s, 1); int x = luaL_checkint(s, 3); int y = luaL_checkint(s, 4); @@ -1838,15 +1844,17 @@ static int being_set_gender(lua_State *s) */ static int chr_get_level(lua_State *s) { - Character *ch = checkCharacter(s, 1); + Being *ch = checkCharacter(s, 1); + auto *characterComponent = ch->getComponent<CharacterComponent>(); if (lua_gettop(s) > 1) { int skillId = checkSkill(s, 2); - lua_pushinteger(s, ch->levelForExp(ch->getExperience(skillId))); + lua_pushinteger(s, characterComponent->levelForExp( + characterComponent->getExperience(skillId))); } else { - lua_pushinteger(s, ch->getLevel()); + lua_pushinteger(s, characterComponent->getLevel()); } return 1; } @@ -1862,9 +1870,9 @@ static int chr_get_level(lua_State *s) */ static int chr_get_exp(lua_State *s) { - Character *c = checkCharacter(s, 1); + Being *c = checkCharacter(s, 1); int skill = checkSkill(s, 2); - const int exp = c->getExperience(skill); + const int exp = c->getComponent<CharacterComponent>()->getExperience(skill); lua_pushinteger(s, exp); return 1; @@ -1882,12 +1890,13 @@ static int chr_get_exp(lua_State *s) */ static int chr_give_exp(lua_State *s) { - Character *c = checkCharacter(s, 1); + Being *c = checkCharacter(s, 1); int skill = checkSkill(s, 2); const int exp = luaL_checkint(s, 3); const int optimalLevel = luaL_optint(s, 4, 0); - c->receiveExperience(skill, exp, optimalLevel); + c->getComponent<CharacterComponent>()->receiveExperience(skill, exp, + optimalLevel); return 0; } @@ -1900,7 +1909,7 @@ static int chr_give_exp(lua_State *s) static int exp_for_level(lua_State *s) { const int level = luaL_checkint(s, 1); - lua_pushinteger(s, Character::expForLevel(level)); + lua_pushinteger(s, CharacterComponent::expForLevel(level)); return 1; } @@ -1911,9 +1920,9 @@ static int exp_for_level(lua_State *s) */ static int chr_get_hair_color(lua_State *s) { - Character *c = checkCharacter(s, 1); + Being *c = checkCharacter(s, 1); - lua_pushinteger(s, c->getHairColor()); + lua_pushinteger(s, c->getComponent<CharacterComponent>()->getHairColor()); return 1; } @@ -1924,11 +1933,11 @@ static int chr_get_hair_color(lua_State *s) */ static int chr_set_hair_color(lua_State *s) { - Character *c = checkCharacter(s, 1); + Being *c = checkCharacter(s, 1); const int color = luaL_checkint(s, 2); luaL_argcheck(s, color >= 0, 2, "invalid color id"); - c->setHairColor(color); + c->getComponent<CharacterComponent>()->setHairColor(color); c->raiseUpdateFlags(UPDATEFLAG_LOOKSCHANGE); return 0; @@ -1941,9 +1950,9 @@ static int chr_set_hair_color(lua_State *s) */ static int chr_get_hair_style(lua_State *s) { - Character *c = checkCharacter(s, 1); + Being *c = checkCharacter(s, 1); - lua_pushinteger(s, c->getHairStyle()); + lua_pushinteger(s, c->getComponent<CharacterComponent>()->getHairStyle()); return 1; } @@ -1954,11 +1963,11 @@ static int chr_get_hair_style(lua_State *s) */ static int chr_set_hair_style(lua_State *s) { - Character *c = checkCharacter(s, 1); + Being *c = checkCharacter(s, 1); const int style = luaL_checkint(s, 2); luaL_argcheck(s, style >= 0, 2, "invalid style id"); - c->setHairStyle(style); + c->getComponent<CharacterComponent>()->setHairStyle(style); c->raiseUpdateFlags(UPDATEFLAG_LOOKSCHANGE); return 0; } @@ -1974,10 +1983,10 @@ static int chr_set_hair_style(lua_State *s) */ static int chr_get_kill_count(lua_State *s) { - Character *c = checkCharacter(s, 1); + Being *c = checkCharacter(s, 1); MonsterClass *monster = checkMonsterClass(s, 2); - lua_pushinteger(s, c->getKillCount(monster->getId())); + lua_pushinteger(s, c->getComponent<CharacterComponent>()->getKillCount(monster->getId())); return 1; } @@ -1988,8 +1997,9 @@ static int chr_get_kill_count(lua_State *s) */ static int chr_get_rights(lua_State *s) { - Character *c = checkCharacter(s, 1); - lua_pushinteger(s, c->getAccountLevel()); + Being *c = checkCharacter(s, 1); + lua_pushinteger(s, + c->getComponent<CharacterComponent>()->getAccountLevel()); return 1; } @@ -2000,10 +2010,10 @@ static int chr_get_rights(lua_State *s) */ static int chr_kick(lua_State *s) { - Character *ch = checkCharacter(s, 1); + Being *ch = checkCharacter(s, 1); MessageOut kickmsg(GPMSG_CONNECT_RESPONSE); kickmsg.writeInt8(ERRMSG_ADMINISTRATIVE_LOGOFF); - ch->getClient()->disconnect(kickmsg); + ch->getComponent<CharacterComponent>()->getClient()->disconnect(kickmsg); return 0; } @@ -2033,7 +2043,7 @@ static int being_get_mapid(lua_State *s) */ static int chr_request_quest(lua_State *s) { - Character *ch = checkCharacter(s, 1); + Being *ch = checkCharacter(s, 1); const char *name = luaL_checkstring(s, 2); luaL_argcheck(s, name[0] != 0, 2, "empty variable name"); luaL_checktype(s, 3, LUA_TFUNCTION); @@ -2072,7 +2082,7 @@ static int chr_request_quest(lua_State *s) */ static int chr_try_get_quest(lua_State *s) { - Character *q = checkCharacter(s, 1); + Being *q = checkCharacter(s, 1); const char *name = luaL_checkstring(s, 2); luaL_argcheck(s, name[0] != 0, 2, "empty variable name"); @@ -2096,7 +2106,7 @@ static int get_character_by_name(lua_State *s) { const char *name = luaL_checkstring(s, 1); - Character *ch = gameHandler->getCharacterByNameSlow(name); + Being *ch = gameHandler->getCharacterByNameSlow(name); if (!ch) lua_pushnil(s); else @@ -2112,7 +2122,7 @@ static int get_character_by_name(lua_State *s) */ static int chr_get_post(lua_State *s) { - Character *c = checkCharacter(s, 1); + Being *c = checkCharacter(s, 1); Script *script = getScript(s); Script::Thread *thread = checkCurrentThread(s, script); @@ -2151,7 +2161,7 @@ static int being_register(lua_State *s) */ static int chr_shake_screen(lua_State *s) { - Character *c = checkCharacter(s, 1); + Being *c = checkCharacter(s, 1); const int x = luaL_checkint(s, 2); const int y = luaL_checkint(s, 3); @@ -2164,7 +2174,7 @@ static int chr_shake_screen(lua_State *s) if (lua_isnumber(s, 5)) msg.writeInt16(lua_tointeger(s, 5)); - c->getClient()->send(msg); + c->getComponent<CharacterComponent>()->getClient()->send(msg); return 0; } @@ -2177,12 +2187,12 @@ static int chr_shake_screen(lua_State *s) */ static int chr_create_text_particle(lua_State *s) { - Character *c = checkCharacter(s, 1); + Being *c = checkCharacter(s, 1); const char *text = luaL_checkstring(s, 2); MessageOut msg(GPMSG_CREATE_TEXT_PARTICLE); msg.writeString(text); - c->getClient()->send(msg); + c->getComponent<CharacterComponent>()->getClient()->send(msg); return 0; } @@ -2195,11 +2205,11 @@ static int chr_create_text_particle(lua_State *s) static int chr_give_special(lua_State *s) { // cost_type is ignored until we have more than one cost type - Character *c = checkCharacter(s, 1); + Being *c = checkCharacter(s, 1); const int special = checkSpecial(s, 2); const int currentMana = luaL_optint(s, 3, 0); - c->giveSpecial(special, currentMana); + c->getComponent<CharacterComponent>()->giveSpecial(special, currentMana); return 0; } @@ -2210,10 +2220,11 @@ static int chr_give_special(lua_State *s) */ static int chr_has_special(lua_State *s) { - Character *c = checkCharacter(s, 1); + Being *c = checkCharacter(s, 1); const int special = luaL_checkint(s, 2); - lua_pushboolean(s, c->hasSpecial(special)); + lua_pushboolean(s, c->getComponent<CharacterComponent>()->hasSpecial( + special)); return 1; } @@ -2227,11 +2238,12 @@ static int chr_has_special(lua_State *s) */ static int chr_take_special(lua_State *s) { - Character *c = checkCharacter(s, 1); + Being *c = checkCharacter(s, 1); const int special = luaL_checkint(s, 2); - lua_pushboolean(s, c->hasSpecial(special)); - c->takeSpecial(special); + lua_pushboolean(s, c->getComponent<CharacterComponent>()->hasSpecial( + special)); + c->getComponent<CharacterComponent>()->takeSpecial(special); return 1; } diff --git a/src/scripting/luascript.cpp b/src/scripting/luascript.cpp index e9f4492d..328ae8ce 100644 --- a/src/scripting/luascript.cpp +++ b/src/scripting/luascript.cpp @@ -275,35 +275,37 @@ void LuaScript::processRemoveEvent(Entity *entity) /** * Called when the server has recovered the value of a quest variable. */ -void LuaScript::getQuestCallback(Character *q, +void LuaScript::getQuestCallback(Being *q, const std::string &value, Script *script) { - Script::Thread *thread = q->getNpcThread(); + auto *characterComponent = q->getComponent<CharacterComponent>(); + Script::Thread *thread = characterComponent->getNpcThread(); if (!thread || thread->mState != Script::ThreadExpectingString) return; script->prepareResume(thread); script->push(value); - q->resumeNpcThread(); + characterComponent->resumeNpcThread(); } /** * Called when the server has recovered the post for a user. */ -void LuaScript::getPostCallback(Character *q, +void LuaScript::getPostCallback(Being *q, const std::string &sender, const std::string &letter, Script *script) { - Script::Thread *thread = q->getNpcThread(); + auto *characterComponent = q->getComponent<CharacterComponent>(); + Script::Thread *thread = characterComponent->getNpcThread(); if (!thread || thread->mState != Script::ThreadExpectingTwoStrings) return; script->prepareResume(thread); script->push(sender); script->push(letter); - q->resumeNpcThread(); + characterComponent->resumeNpcThread(); } diff --git a/src/scripting/luascript.h b/src/scripting/luascript.h index 3bedbc28..b7bdde1e 100644 --- a/src/scripting/luascript.h +++ b/src/scripting/luascript.h @@ -28,7 +28,7 @@ extern "C" { #include "scripting/script.h" -class Character; +class CharacterComponent; /** * Implementation of the Script class for Lua. @@ -69,11 +69,11 @@ class LuaScript : public Script void unref(Ref &ref); - static void getQuestCallback(Character *, + static void getQuestCallback(Being *, const std::string &value, Script *); - static void getPostCallback(Character *, + static void getPostCallback(Being *, const std::string &sender, const std::string &letter, Script *); diff --git a/src/scripting/luautil.cpp b/src/scripting/luautil.cpp index d082cbe7..f835be81 100644 --- a/src/scripting/luautil.cpp +++ b/src/scripting/luautil.cpp @@ -128,14 +128,14 @@ Being *getBeing(lua_State *s, int p) return static_cast<Being *>(lua_touserdata(s, p)); } -Character *getCharacter(lua_State *s, int p) +Being *getCharacter(lua_State *s, int p) { if (!lua_islightuserdata(s, p)) return 0; Entity *t = static_cast<Entity *>(lua_touserdata(s, p)); if (t->getType() != OBJECT_CHARACTER) return 0; - return static_cast<Character *>(t); + return static_cast<Being *>(t); } ItemClass *getItemClass(lua_State *s, int p) @@ -206,9 +206,9 @@ Being *checkBeing(lua_State *s, int p) return being; } -Character *checkCharacter(lua_State *s, int p) +Being *checkCharacter(lua_State *s, int p) { - Character *character = getCharacter(s, p); + Being *character = getCharacter(s, p); luaL_argcheck(s, character, p, "character expected"); return character; } diff --git a/src/scripting/luautil.h b/src/scripting/luautil.h index e76a15a1..bf335d20 100644 --- a/src/scripting/luautil.h +++ b/src/scripting/luautil.h @@ -38,7 +38,7 @@ extern "C" { #include "game-server/specialmanager.h" class Being; -class Character; +class CharacterComponent; class Entity; class ItemClass; class MapComposite; @@ -166,14 +166,14 @@ typedef LuaUserData<SpecialManager::SpecialInfo> LuaSpecialInfo; Script * getScript(lua_State *s); Being * getBeing(lua_State *s, int p); -Character * getCharacter(lua_State *s, int p); +Being * getCharacter(lua_State *s, int p); ItemClass * getItemClass(lua_State *s, int p); Being * getMonster(lua_State *s, int p); MonsterClass * getMonsterClass(lua_State *s, int p); Being * getNpc(lua_State *s, int p); Being * checkBeing(lua_State *s, int p); -Character * checkCharacter(lua_State *s, int p); +Being * checkCharacter(lua_State *s, int p); ItemClass * checkItemClass(lua_State *s, int p); Being * checkMonster(lua_State *s, int p); MonsterClass * checkMonsterClass(lua_State *s, int p); diff --git a/src/serialize/characterdata.h b/src/serialize/characterdata.h index abcc6114..c25fb096 100644 --- a/src/serialize/characterdata.h +++ b/src/serialize/characterdata.h @@ -42,16 +42,14 @@ void serializeCharacterData(const T &data, MessageOut &msg) msg.writeInt16(data.getCharacterPoints()); msg.writeInt16(data.getCorrectionPoints()); - msg.writeInt16(data.mAttributes.size()); - AttributeMap::const_iterator attr_it, attr_it_end; - for (attr_it = data.mAttributes.begin(), - attr_it_end = data.mAttributes.end(); - attr_it != attr_it_end; - ++attr_it) + + const AttributeMap &attributes = data.getAttributes(); + msg.writeInt16(attributes.size()); + for (auto attributeIt : attributes) { - msg.writeInt16(attr_it->first); - msg.writeDouble(data.getAttrBase(attr_it)); - msg.writeDouble(data.getAttrMod(attr_it)); + msg.writeInt16(attributeIt.first); + msg.writeDouble(attributeIt.second.getBase()); + msg.writeDouble(attributeIt.second.getModifiedAttribute()); } // character skills @@ -66,11 +64,11 @@ void serializeCharacterData(const T &data, MessageOut &msg) // status effects currently affecting the character msg.writeInt16(data.getStatusEffectSize()); - std::map<int, int>::const_iterator status_it; + std::map<int, Status>::const_iterator status_it; for (status_it = data.getStatusEffectBegin(); status_it != data.getStatusEffectEnd(); status_it++) { msg.writeInt16(status_it->first); - msg.writeInt16(status_it->second); + msg.writeInt16(status_it->second.time); } // location |