Lucasbaragatti 11 Postado Novembro 24, 2011 Autor Share Postado Novembro 24, 2011 Tenta usar a nova versão do stians repack que pus hoje... pq aqui rodou tudo 100% Link para o comentário https://xtibia.com/forum/topic/173167-beta-duel-system-v11/page/2/#findComment-1138405 Compartilhar em outros sites More sharing options...
lailton 0 Postado Novembro 26, 2011 Share Postado Novembro 26, 2011 (editado) Lucas, Segue abaixo a mensagem de erro ao tentar compilar. ( atualizei pro novo download o msmo erro continua ). Pelo que entendi o problema esta aqui ( player->getId() ) ele nao encontra o getid... comentei essa linha e compilo porem sei q é necessario corrigir isso, de alguma forma é necessario pegar o ID do player, segue abaixo meu script player. Player.h //////////////////////////////////////////////////////////////////////// // OpenTibia - an opensource roleplaying game //////////////////////////////////////////////////////////////////////// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. //////////////////////////////////////////////////////////////////////// #ifndef __PLAYER__ #define __PLAYER__ #include "otsystem.h" #include "enums.h" #include "creature.h" #include "cylinder.h" #include "container.h" #include "depot.h" #include "outfit.h" #include "vocation.h" #include "group.h" #include "protocolgame.h" #include "ioguild.h" #include "party.h" #include "npc.h" class House; class NetworkMessage; class Weapon; class ProtocolGame; class Npc; class Party; class SchedulerTask; class Quest; enum skillsid_t { SKILL_LEVEL = 0, SKILL_TRIES = 1, SKILL_PERCENT = 2 }; enum playerinfo_t { PLAYERINFO_LEVEL, PLAYERINFO_LEVELPERCENT, PLAYERINFO_HEALTH, PLAYERINFO_MAXHEALTH, PLAYERINFO_MANA, PLAYERINFO_MAXMANA, PLAYERINFO_MAGICLEVEL, PLAYERINFO_MAGICLEVELPERCENT, PLAYERINFO_SOUL, }; enum freeslot_t { SLOT_TYPE_NONE, SLOT_TYPE_INVENTORY, SLOT_TYPE_CONTAINER }; enum chaseMode_t { CHASEMODE_STANDSTILL, CHASEMODE_FOLLOW, }; enum fightMode_t { FIGHTMODE_ATTACK, FIGHTMODE_BALANCED, FIGHTMODE_DEFENSE }; enum secureMode_t { SECUREMODE_ON, SECUREMODE_OFF }; enum tradestate_t { TRADE_NONE, TRADE_INITIATED, TRADE_ACCEPT, TRADE_ACKNOWLEDGE, TRADE_TRANSFER }; enum AccountManager_t { MANAGER_NONE, MANAGER_NEW, MANAGER_ACCOUNT, MANAGER_NAMELOCK }; enum GamemasterCondition_t { GAMEMASTER_INVISIBLE = 0, GAMEMASTER_IGNORE = 1, GAMEMASTER_TELEPORT = 2 }; enum Exhaust_t { EXHAUST_COMBAT = 1, EXHAUST_HEALING = 2 }; typedef std::set<uint32_t> VIPListSet; typedef std::vector<std::pair<uint32_t, Container*> > ContainerVector; typedef std::map<uint32_t, std::pair<Depot*, bool> > DepotMap; typedef std::map<uint32_t, uint32_t> MuteCountMap; typedef std::list<std::string> LearnedInstantSpellList; typedef std::list<uint32_t> InvitedToGuildsList; typedef std::list<Party*> PartyList; #define SPEED_MAX 1500 #define SPEED_MIN 10 #define STAMINA_MAX (42 * 60 * 60 * 1000) #define STAMINA_MULTIPLIER (60 * 1000) class Player : public Creature, public Cylinder { public: #ifdef __ENABLE_SERVER_DIAGNOSTIC__ static uint32_t playerCount; #endif Player(const std::string& name, ProtocolGame* p); virtual ~Player(); virtual Player* getPlayer() {return this;} virtual const Player* getPlayer() const {return this;} static MuteCountMap muteCountMap; virtual const std::string& getName() const {return name;} virtual const std::string& getNameDescription() const {return nameDescription;} virtual std::string getDescription(int32_t lookDistance) const; const std::string& getSpecialDescription() const {return specialDescription;} void setSpecialDescription(const std::string& desc) {specialDescription = desc;} void manageAccount(const std::string& text); bool isAccountManager() const {return (accountManager != MANAGER_NONE);} void kickPlayer(bool displayEffect, bool forceLogout); void setGUID(uint32_t _guid) {guid = _guid;} uint32_t getGUID() const {return guid;} static AutoList<Player> autoList; virtual uint32_t rangeId() {return 0x10000000;} void addList(); void removeList(); static uint64_t getExpForLevel(uint32_t lv) { lv--; return ((50ULL * lv * lv * lv) - (150ULL * lv * lv) + (400ULL * lv)) / 3ULL; } uint32_t getPromotionLevel() const {return promotionLevel;} void setPromotionLevel(uint32_t pLevel); bool changeOutfit(Outfit_t outfit, bool checkList); void hasRequestedOutfit(bool v) {requestedOutfit = v;} Vocation* getVocation() const {return vocation;} int32_t getPlayerInfo(playerinfo_t playerinfo) const; void setParty(Party* _party) {party = _party;} Party* getParty() const {return party;} PartyShields_t getPartyShield(const Creature* creature) const; bool isInviting(const Player* player) const; bool isPartner(const Player* player) const; void sendPlayerPartyIcons(Player* player); bool addPartyInvitation(Party* party); bool removePartyInvitation(Party* party); void clearPartyInvitations(); uint32_t getGuildId() const {return guildId;} void setGuildId(uint32_t newId) {guildId = newId;} uint32_t getRankId() const {return rankId;} void setRankId(uint32_t newId) {rankId = newId;} GuildLevel_t getGuildLevel() const {return guildLevel;} bool setGuildLevel(GuildLevel_t newLevel, uint32_t rank = 0); const std::string& getGuildName() const {return guildName;} void setGuildName(const std::string& newName) {guildName = newName;} const std::string& getRankName() const {return rankName;} void setRankName(const std::string& newName) {rankName = newName;} const std::string& getGuildNick() const {return guildNick;} void setGuildNick(const std::string& newNick) {guildNick = newNick;} bool isGuildInvited(uint32_t guildId) const; void leaveGuild(); void setFlags(uint64_t flags) {if(group) group->setFlags(flags);} bool hasFlag(PlayerFlags value) const {return group != NULL && group->hasFlag(value);} void setCustomFlags(uint64_t flags) {if(group) group->setCustomFlags(flags);} bool hasCustomFlag(PlayerCustomFlags value) const {return group != NULL && group->hasCustomFlag(value);} void addBlessing(int16_t blessing) {blessings += blessing;} bool hasBlessing(int16_t value) const {return (blessings & ((int16_t)1 << value));} uint16_t getBlessings() const; OperatingSystem_t getOperatingSystem() const {return operatingSystem;} void setOperatingSystem(OperatingSystem_t clientOs) {operatingSystem = clientOs;} uint32_t getClientVersion() const {return clientVersion;} void setClientVersion(uint32_t version) {clientVersion = version;} bool hasClient() const {return client;} bool isVirtual() const {return (getID() == 0);} void disconnect() {if(client) client->disconnect();} uint32_t getIP() const; bool canOpenCorpse(uint32_t ownerId); Container* getContainer(uint32_t cid); int32_t getContainerID(const Container* container) const; void addContainer(uint32_t cid, Container* container); void closeContainer(uint32_t cid); virtual bool setStorage(const uint32_t key, const std::string& value); virtual void eraseStorage(const uint32_t key); void generateReservedStorage(); bool transferMoneyTo(const std::string& name, uint64_t amount); void increaseCombatValues(int32_t& min, int32_t& max, bool useCharges, bool countWeapon); void setGroupId(int32_t newId); int32_t getGroupId() const {return groupId;} void setGroup(Group* newGroup); Group* getGroup() const {return group;} virtual bool isGhost() const {return hasCondition(CONDITION_GAMEMASTER, GAMEMASTER_INVISIBLE) || hasFlag(PlayerFlag_CannotBeSeen);} void switchSaving() {saving = !saving;} bool isSaving() const {return saving;} uint32_t getIdleTime() const {return idleTime;} void setIdleTime(uint32_t amount) {idleTime = amount;} bool checkLoginDelay(uint32_t playerId) const; bool isTrading() const {return tradePartner;} uint32_t getAccount() const {return accountId;} std::string getAccountName() const {return account;} uint16_t getAccess() const {return group ? group->getAccess() : 0;} uint16_t getGhostAccess() const {return group ? group->getGhostAccess() : 0;} bool isPremium() const; int32_t getPremiumDays() const {return premiumDays;} uint32_t getLevel() const {return level;} uint64_t getExperience() const {return experience;} uint32_t getMagicLevel() const {return getPlayerInfo(PLAYERINFO_MAGICLEVEL);} uint64_t getSpentMana() const {return manaSpent;} uint32_t getVocationId() const {return vocation_id;} void setVocation(uint32_t vocId); uint16_t getSex(bool full) const {return full ? sex : sex % 2;} void setSex(uint16_t); uint64_t getStamina() const {return hasFlag(PlayerFlag_HasInfiniteStamina) ? STAMINA_MAX : stamina;} void setStamina(uint64_t value) {stamina = std::min((uint64_t)STAMINA_MAX, (uint64_t)std::max((uint64_t)0, value));} uint32_t getStaminaMinutes() const {return (uint32_t)(getStamina() / (uint64_t)STAMINA_MULTIPLIER);} void setStaminaMinutes(uint32_t value) {setStamina((uint64_t)(value * STAMINA_MULTIPLIER));} void useStamina(int64_t value) {stamina = std::min((int64_t)STAMINA_MAX, (int64_t)std::max((int64_t)0, ((int64_t)stamina + value)));} uint64_t getSpentStamina() {return (uint64_t)STAMINA_MAX - stamina;} int64_t getLastLoad() const {return lastLoad;} time_t getLastLogin() const {return lastLogin;} time_t getLastLogout() const {return lastLogout;} Position getLoginPosition() const {return loginPosition;} uint32_t getTown() const {return town;} void setTown(uint32_t _town) {town = _town;} virtual bool isPushable() const; virtual int32_t getThrowRange() const {return 1;} bool isMuted(uint16_t channelId, SpeakClasses type, uint32_t& time); void addMessageBuffer(); void removeMessageBuffer(); double getCapacity() const {return capacity;} void setCapacity(double newCapacity) {capacity = newCapacity;} double getFreeCapacity() const { if(hasFlag(PlayerFlag_CannotPickupItem)) return 0.00; else if(hasFlag(PlayerFlag_HasInfiniteCapacity)) return 10000.00; return std::max(0.00, capacity - inventoryWeight); } virtual int32_t getSoul() const {return getPlayerInfo(PLAYERINFO_SOUL);} virtual int32_t getMaxHealth() const {return getPlayerInfo(PLAYERINFO_MAXHEALTH);} virtual int32_t getMaxMana() const {return getPlayerInfo(PLAYERINFO_MAXMANA);} int32_t getSoulMax() const {return soulMax;} Item* getInventoryItem(slots_t slot) const; Item* getEquippedItem(slots_t slot) const; bool isItemAbilityEnabled(slots_t slot) const {return inventoryAbilities[slot];} void setItemAbility(slots_t slot, bool enabled) {inventoryAbilities[slot] = enabled;} int32_t getVarSkill(skills_t skill) const {return varSkills[skill];} void setVarSkill(skills_t skill, int32_t modifier) {varSkills[skill] += modifier;} int32_t getVarStats(stats_t stat) const {return varStats[stat];} void setVarStats(stats_t stat, int32_t modifier); int32_t getDefaultStats(stats_t stat); void setConditionSuppressions(uint32_t conditions, bool remove); uint32_t getLossPercent(lossTypes_t lossType) const {return lossPercent[lossType];} void setLossPercent(lossTypes_t lossType, uint32_t newPercent) {lossPercent[lossType] = newPercent;} Depot* getDepot(uint32_t depotId, bool autoCreateDepot); bool addDepot(Depot* depot, uint32_t depotId); void useDepot(uint32_t depotId, bool value); virtual bool canSee(const Position& pos) const; virtual bool canSeeCreature(const Creature* creature) const; virtual bool canWalkthrough(const Creature* creature) const; virtual bool canSeeInvisibility() const {return hasFlag(PlayerFlag_CanSenseInvisibility);} virtual RaceType_t getRace() const {return RACE_BLOOD;} //safe-trade functions void setTradeState(tradestate_t state) {tradeState = state;} tradestate_t getTradeState() {return tradeState;} Item* getTradeItem() {return tradeItem;} //shop functions void setShopOwner(Npc* owner, int32_t onBuy, int32_t onSell, ShopInfoList offer) { shopOwner = owner; purchaseCallback = onBuy; saleCallback = onSell; shopOffer = offer; } Npc* getShopOwner(int32_t& onBuy, int32_t& onSell) { onBuy = purchaseCallback; onSell = saleCallback; return shopOwner; } const Npc* getShopOwner(int32_t& onBuy, int32_t& onSell) const { onBuy = purchaseCallback; onSell = saleCallback; return shopOwner; } //V.I.P. functions void notifyLogIn(Player* loginPlayer); void notifyLogOut(Player* logoutPlayer); bool removeVIP(uint32_t guid); bool addVIP(uint32_t guid, std::string& name, bool isOnline, bool internal = false); //follow functions virtual bool setFollowCreature(Creature* creature, bool fullPathSearch = false); //follow events virtual void onFollowCreature(const Creature* creature); //walk events virtual void onWalk(Direction& dir); virtual void onWalkAborted(); virtual void onWalkComplete(); void stopWalk(); void openShopWindow(); void closeShopWindow(Npc* npc = NULL, int32_t onBuy = -1, int32_t onSell = -1); bool canShopItem(uint16_t itemId, uint8_t subType, ShopEvent_t event); void setChaseMode(chaseMode_t mode); void setFightMode(fightMode_t mode) {fightMode = mode;} void setSecureMode(secureMode_t mode) {secureMode = mode;} secureMode_t getSecureMode() const {return secureMode;} //combat functions virtual bool setAttackedCreature(Creature* creature); bool isImmune(CombatType_t type) const; bool isImmune(ConditionType_t type) const; bool hasShield() const; virtual bool isAttackable() const; virtual void changeHealth(int32_t healthChange); virtual void changeMana(int32_t manaChange); void changeSoul(int32_t soulChange); bool isPzLocked() const {return pzLocked;} void setPzLocked(bool v) {pzLocked = v;} virtual BlockType_t blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage, bool checkDefense = false, bool checkArmor = false); virtual void doAttacking(uint32_t interval); virtual bool hasExtraSwing() {return lastAttack > 0 && ((OTSYS_TIME() - lastAttack) >= getAttackSpeed());} int32_t getShootRange() const {return shootRange;} int32_t getSkill(skills_t skilltype, skillsid_t skillinfo) const; bool getAddAttackSkill() const {return addAttackSkillPoint;} BlockType_t getLastAttackBlockType() const {return lastAttackBlockType;} Item* getWeapon(bool ignoreAmmo = false); virtual WeaponType_t getWeaponType(); int32_t getWeaponSkill(const Item* item) const; void getShieldAndWeapon(const Item* &shield, const Item* &weapon) const; virtual void drainHealth(Creature* attacker, CombatType_t combatType, int32_t damage); virtual void drainMana(Creature* attacker, CombatType_t combatType, int32_t damage); void addExperience(uint64_t exp); void removeExperience(uint64_t exp, bool updateStats = true); void addManaSpent(uint64_t amount, bool useMultiplier = true); void addSkillAdvance(skills_t skill, uint32_t count, bool useMultiplier = true); bool addUnjustifiedKill(const Player* attacked); virtual int32_t getArmor() const; virtual int32_t getDefense() const; virtual float getAttackFactor() const; virtual float getDefenseFactor() const; void addExhaust(uint32_t ticks, Exhaust_t type); void addInFightTicks(bool pzLock = false); void addDefaultRegeneration(uint32_t addTicks); virtual double getGainedExperience(Creature* attacker) const; //combat event functions virtual void onAddCondition(ConditionType_t type, bool hadCondition); virtual void onAddCombatCondition(ConditionType_t type, bool hadCondition); virtual void onEndCondition(ConditionType_t type); virtual void onCombatRemoveCondition(const Creature* attacker, Condition* condition); virtual void onTickCondition(ConditionType_t type, int32_t interval, bool& _remove); virtual void onAttackedCreature(Creature* target); virtual void onSummonAttackedCreature(Creature* summon, Creature* target); virtual void onAttacked(); virtual void onAttackedCreatureDrain(Creature* target, int32_t points); virtual void onSummonAttackedCreatureDrain(Creature* summon, Creature* target, int32_t points); virtual void onTargetCreatureGainHealth(Creature* target, int32_t points); virtual bool onKilledCreature(Creature* target, uint32_t& flags); virtual void onGainExperience(double& gainExp, bool fromMonster, bool multiplied); virtual void onGainSharedExperience(double& gainExp, bool fromMonster, bool multiplied); virtual void onAttackedCreatureBlockHit(Creature* target, BlockType_t blockType); virtual void onBlockHit(BlockType_t blockType); virtual void onChangeZone(ZoneType_t zone); virtual void onAttackedCreatureChangeZone(ZoneType_t zone); virtual void onIdleStatus(); virtual void onPlacedCreature(); virtual void getCreatureLight(LightInfo& light) const; Skulls_t getSkull() const; Skulls_t getSkullClient(const Creature* creature) const; bool hasAttacked(const Player* attacked) const; void addAttacked(const Player* attacked); void clearAttacked() {attackedSet.clear();} time_t getSkullEnd() const {return skullEnd;} void setSkullEnd(time_t _time, bool login, Skulls_t _skull); bool addOutfit(uint32_t outfitId, uint32_t addons); bool removeOutfit(uint32_t outfitId, uint32_t addons); bool canWearOutfit(uint32_t outfitId, uint32_t addons); bool canLogout(bool checkInfight); //tile //send methods void sendAddTileItem(const Tile* tile, const Position& pos, const Item* item) {if(client) client->sendAddTileItem(tile, pos, tile->getClientIndexOfThing(this, item), item);} void sendUpdateTileItem(const Tile* tile, const Position& pos, const Item* oldItem, const Item* newItem) {if(client) client->sendUpdateTileItem(tile, pos, tile->getClientIndexOfThing(this, oldItem), newItem);} void sendRemoveTileItem(const Tile* tile, const Position& pos, uint32_t stackpos, const Item* item) {if(client) client->sendRemoveTileItem(tile, pos, stackpos);} void sendUpdateTile(const Tile* tile, const Position& pos) {if(client) client->sendUpdateTile(tile, pos);} void sendChannelMessage(std::string author, std::string text, SpeakClasses type, uint8_t channel) {if(client) client->sendChannelMessage(author, text, type, channel);} void sendCreatureAppear(const Creature* creature) {if(client) client->sendAddCreature(creature, creature->getPosition(), creature->getTile()->getClientIndexOfThing( this, creature));} void sendCreatureDisappear(const Creature* creature, uint32_t stackpos) {if(client) client->sendRemoveCreature(creature, creature->getPosition(), stackpos);} void sendCreatureMove(const Creature* creature, const Tile* newTile, const Position& newPos, const Tile* oldTile, const Position& oldPos, uint32_t oldStackpos, bool teleport) {if(client) client->sendMoveCreature(creature, newTile, newPos, newTile->getClientIndexOfThing( this, creature), oldTile, oldPos, oldStackpos, teleport);} void sendCreatureTurn(const Creature* creature) {if(client) client->sendCreatureTurn(creature, creature->getTile()->getClientIndexOfThing(this, creature));} void sendCreatureSay(const Creature* creature, SpeakClasses type, const std::string& text, Position* pos = NULL) {if(client) client->sendCreatureSay(creature, type, text, pos);} void sendCreatureSquare(const Creature* creature, SquareColor_t color) {if(client) client->sendCreatureSquare(creature, color);} void sendCreatureChangeOutfit(const Creature* creature, const Outfit_t& outfit) {if(client) client->sendCreatureOutfit(creature, outfit);} void sendCreatureChangeVisible(const Creature* creature, Visible_t visible); void sendCreatureLight(const Creature* creature) {if(client) client->sendCreatureLight(creature);} void sendCreatureShield(const Creature* creature) {if(client) client->sendCreatureShield(creature);} //container void sendAddContainerItem(const Container* container, const Item* item); void sendUpdateContainerItem(const Container* container, uint8_t slot, const Item* oldItem, const Item* newItem); void sendRemoveContainerItem(const Container* container, uint8_t slot, const Item* item); void sendContainer(uint32_t cid, const Container* container, bool hasParent) {if(client) client->sendContainer(cid, container, hasParent);} //inventory void sendAddInventoryItem(slots_t slot, const Item* item) {if(client) client->sendAddInventoryItem(slot, item);} void sendUpdateInventoryItem(slots_t slot, const Item* oldItem, const Item* newItem) {if(client) client->sendUpdateInventoryItem(slot, newItem);} void sendRemoveInventoryItem(slots_t slot, const Item* item) {if(client) client->sendRemoveInventoryItem(slot);} //event methods virtual void onUpdateTileItem(const Tile* tile, const Position& pos, const Item* oldItem, const ItemType& oldType, const Item* newItem, const ItemType& newType); virtual void onRemoveTileItem(const Tile* tile, const Position& pos, const ItemType& iType, const Item* item); virtual void onCreatureAppear(const Creature* creature); virtual void onCreatureDisappear(const Creature* creature, bool isLogout); virtual void onCreatureMove(const Creature* creature, const Tile* newTile, const Position& newPos, const Tile* oldTile, const Position& oldPos, bool teleport); virtual void onAttackedCreatureDisappear(bool isLogout); virtual void onFollowCreatureDisappear(bool isLogout); //cylinder implementations virtual Cylinder* getParent() {return Creature::getParent();} virtual const Cylinder* getParent() const {return Creature::getParent();} virtual bool isRemoved() const {return Creature::isRemoved();} virtual Position getPosition() const {return Creature::getPosition();} virtual Tile* getTile() {return Creature::getTile();} virtual const Tile* getTile() const {return Creature::getTile();} virtual Item* getItem() {return NULL;} virtual const Item* getItem() const {return NULL;} virtual Creature* getCreature() {return this;} virtual const Creature* getCreature() const {return this;} //container void onAddContainerItem(const Container* container, const Item* item); void onUpdateContainerItem(const Container* container, uint8_t slot, const Item* oldItem, const ItemType& oldType, const Item* newItem, const ItemType& newType); void onRemoveContainerItem(const Container* container, uint8_t slot, const Item* item); void onCloseContainer(const Container* container); void onSendContainer(const Container* container); void autoCloseContainers(const Container* container); //inventory void onAddInventoryItem(slots_t slot, Item* item) {} void onUpdateInventoryItem(slots_t slot, Item* oldItem, const ItemType& oldType, Item* newItem, const ItemType& newType); void onRemoveInventoryItem(slots_t slot, Item* item); void sendAnimatedText(const Position& pos, uint8_t color, std::string text) const {if(client) client->sendAnimatedText(pos,color,text);} void sendCancel(const std::string& msg) const {if(client) client->sendCancel(msg);} void sendCancelMessage(ReturnValue message) const; void sendCancelTarget() const {if(client) client->sendCancelTarget();} void sendCancelWalk() const {if(client) client->sendCancelWalk();} void sendChangeSpeed(const Creature* creature, uint32_t newSpeed) const {if(client) client->sendChangeSpeed(creature, newSpeed);} void sendCreatureHealth(const Creature* creature) const {if(client) client->sendCreatureHealth(creature);} void sendDistanceShoot(const Position& from, const Position& to, uint8_t type) const {if(client) client->sendDistanceShoot(from, to, type);} void sendHouseWindow(House* house, uint32_t listId) const; void sendOutfitWindow() const {if(client) client->sendOutfitWindow();} void sendQuests() const {if(client) client->sendQuests();} void sendQuestInfo(Quest* quest) const {if(client) client->sendQuestInfo(quest);} void sendCreatureSkull(const Creature* creature) const {if(client) client->sendCreatureSkull(creature);} void sendFYIBox(std::string message) {if(client) client->sendFYIBox(message);} void sendCreatePrivateChannel(uint16_t channelId, const std::string& channelName) {if(client) client->sendCreatePrivateChannel(channelId, channelName);} void sendClosePrivate(uint16_t channelId) const {if(client) client->sendClosePrivate(channelId);} void sendIcons() const; void sendMagicEffect(const Position& pos, uint8_t type) const {if(client) client->sendMagicEffect(pos, type);} void sendStats(); void sendSkills() const {if(client) client->sendSkills();} void sendTextMessage(MessageClasses type, const std::string& message) const {if(client) client->sendTextMessage(type, message);} void sendReLoginWindow() const {if(client) client->sendReLoginWindow();} void sendTextWindow(Item* item, uint16_t maxLen, bool canWrite) const {if(client) client->sendTextWindow(windowTextId, item, maxLen, canWrite);} void sendTextWindow(uint32_t itemId, const std::string& text) const {if(client) client->sendTextWindow(windowTextId, itemId, text);} void sendToChannel(Creature* creature, SpeakClasses type, const std::string& text, uint16_t channelId, uint32_t time = 0) const {if(client) client->sendToChannel(creature, type, text, channelId, time);} void sendShop() const {if(client) client->sendShop(shopOffer);} void sendGoods() const {if(client) client->sendGoods(shopOffer);} void sendCloseShop() const {if(client) client->sendCloseShop();} void sendTradeItemRequest(const Player* player, const Item* item, bool ack) const {if(client) client->sendTradeItemRequest(player, item, ack);} void sendTradeClose() const {if(client) client->sendCloseTrade();} void sendWorldLight(LightInfo& lightInfo) {if(client) client->sendWorldLight(lightInfo);} void sendChannelsDialog() {if(client) client->sendChannelsDialog();} void sendOpenPrivateChannel(const std::string& receiver) {if(client) client->sendOpenPrivateChannel(receiver);} void sendOutfitWindow() {if(client) client->sendOutfitWindow();} void sendCloseContainer(uint32_t cid) {if(client) client->sendCloseContainer(cid);} void sendChannel(uint16_t channelId, const std::string& channelName) {if(client) client->sendChannel(channelId, channelName);} void sendRuleViolationsChannel(uint16_t channelId) {if(client) client->sendRuleViolationsChannel(channelId);} void sendRemoveReport(const std::string& name) {if(client) client->sendRemoveReport(name);} void sendLockRuleViolation() {if(client) client->sendLockRuleViolation();} void sendRuleViolationCancel(const std::string& name) {if(client) client->sendRuleViolationCancel(name);} void sendTutorial(uint8_t tutorialId) {if(client) client->sendTutorial(tutorialId);} void sendAddMarker(const Position& pos, MapMarks_t markType, const std::string& desc) {if (client) client->sendAddMarker(pos, markType, desc);} void sendCritical() const; void receivePing() {lastPong = OTSYS_TIME();} virtual void onThink(uint32_t interval); uint32_t getAttackSpeed(); virtual void postAddNotification(Creature* actor, Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t link = LINK_OWNER); virtual void postRemoveNotification(Creature* actor, Thing* thing, const Cylinder* newParent, int32_t index, bool isCompleteRemoval, cylinderlink_t link = LINK_OWNER); void setNextAction(int64_t time) {if(time > nextAction) {nextAction = time;}} bool canDoAction() const {return nextAction <= OTSYS_TIME();} uint32_t getNextActionTime() const; Item* getWriteItem(uint32_t& _windowTextId, uint16_t& _maxWriteLen); void setWriteItem(Item* item, uint16_t _maxWriteLen = 0); House* getEditHouse(uint32_t& _windowTextId, uint32_t& _listId); void setEditHouse(House* house, uint32_t listId = 0); void learnInstantSpell(const std::string& name); void unlearnInstantSpell(const std::string& name); bool hasLearnedInstantSpell(const std::string& name) const; VIPListSet VIPList; ContainerVector containerVec; InvitedToGuildsList invitedToGuildsList; ConditionList storedConditionList; DepotMap depots; uint32_t marriage; uint64_t balance; double rates[sKILL__LAST + 1]; Container transferContainer; protected: void checkTradeState(const Item* item); bool gainExperience(double& gainExp, bool fromMonster); bool rateExperience(double& gainExp, bool fromMonster); void updateBaseSpeed() { if(!hasFlag(PlayerFlag_SetMaxSpeed)) baseSpeed = vocation->getBaseSpeed() + (2 * (level - 1)); else baseSpeed = SPEED_MAX; } void updateInventoryWeight(); void updateInventoryGoods(uint32_t itemId); void updateItemsLight(bool internal = false); void setNextWalkActionTask(SchedulerTask* task); void setNextWalkTask(SchedulerTask* task); void setNextActionTask(SchedulerTask* task); virtual bool onDeath(); virtual Item* createCorpse(DeathList deathList); virtual void dropCorpse(DeathList deathList); virtual void dropLoot(Container* corpse); //cylinder implementations virtual ReturnValue __queryAdd(int32_t index, const Thing* thing, uint32_t count, uint32_t flags) const; virtual ReturnValue __queryMaxCount(int32_t index, const Thing* thing, uint32_t count, uint32_t& maxQueryCount, uint32_t flags) const; virtual ReturnValue __queryRemove(const Thing* thing, uint32_t count, uint32_t flags) const; virtual Cylinder* __queryDestination(int32_t& index, const Thing* thing, Item** destItem, uint32_t& flags); virtual void __addThing(Creature* actor, Thing* thing); virtual void __addThing(Creature* actor, int32_t index, Thing* thing); virtual void __updateThing(Thing* thing, uint16_t itemId, uint32_t count); virtual void __replaceThing(uint32_t index, Thing* thing); virtual void __removeThing(Thing* thing, uint32_t count); virtual Thing* __getThing(uint32_t index) const; virtual int32_t __getIndexOfThing(const Thing* thing) const; virtual int32_t __getFirstIndex() const; virtual int32_t __getLastIndex() const; virtual uint32_t __getItemTypeCount(uint16_t itemId, int32_t subType = -1, bool itemCount = true) const; virtual std::map<uint32_t, uint32_t>& __getAllItemTypeCount(std::map<uint32_t, uint32_t>& countMap, bool itemCount = true) const; virtual void __internalAddThing(Thing* thing); virtual void __internalAddThing(uint32_t index, Thing* thing); uint32_t getVocAttackSpeed() const {return vocation->getAttackSpeed();} virtual int32_t getStepSpeed() const { if(getSpeed() > SPEED_MAX) return SPEED_MAX; if(getSpeed() < SPEED_MIN) return SPEED_MIN; return getSpeed(); } virtual uint32_t getDamageImmunities() const {return damageImmunities;} virtual uint32_t getConditionImmunities() const {return conditionImmunities;} virtual uint32_t getConditionSuppressions() const {return conditionSuppressions;} virtual uint16_t getLookCorpse() const; virtual uint64_t getLostExperience() const; virtual void getPathSearchParams(const Creature* creature, FindPathParams& fpp) const; static uint32_t getPercentLevel(uint64_t count, uint64_t nextLevelCount); bool isPromoted(uint32_t pLevel = 1) const {return promotionLevel >= pLevel;} bool hasCapacity(const Item* item, uint32_t count) const; private: bool talkState[13]; bool inventoryAbilities[11]; bool pzLocked; bool saving; bool isConnecting; bool requestedOutfit; bool outfitAttributes; bool addAttackSkillPoint; OperatingSystem_t operatingSystem; AccountManager_t accountManager; PlayerSex_t managerSex; BlockType_t lastAttackBlockType; chaseMode_t chaseMode; fightMode_t fightMode; secureMode_t secureMode; tradestate_t tradeState; GuildLevel_t guildLevel; int16_t blessings; uint16_t maxWriteLen; uint16_t sex; int32_t premiumDays; int32_t soul; int32_t soulMax; int32_t vocation_id; int32_t groupId; int32_t managerNumber, managerNumber2; int32_t purchaseCallback; int32_t saleCallback; int32_t varSkills[sKILL_LAST + 1]; int32_t varStats[sTAT_LAST + 1]; int32_t messageBuffer; int32_t bloodHitCount; int32_t shieldBlockCount; int32_t shootRange; uint32_t clientVersion; uint32_t messageTicks; uint32_t idleTime; uint32_t accountId; uint32_t lastIP; uint32_t level; uint32_t levelPercent; uint32_t magLevel; uint32_t magLevelPercent; uint32_t damageImmunities; uint32_t conditionImmunities; uint32_t conditionSuppressions; uint32_t condition; //? uint32_t nextStepEvent; uint32_t actionTaskEvent; uint32_t walkTaskEvent; uint32_t lossPercent[LOSS_LAST + 1]; uint32_t skills[sKILL_LAST + 1][3]; uint32_t guid; uint32_t editListId; uint32_t windowTextId; uint32_t guildId; uint32_t rankId; uint32_t promotionLevel; uint32_t town; time_t skullEnd; time_t lastLogin; time_t lastLogout; int64_t lastLoad; int64_t lastPong; int64_t lastPing; int64_t nextAction; uint64_t stamina; uint64_t experience; uint64_t manaSpent; uint64_t lastAttack; double inventoryWeight; double capacity; char managerChar[100]; std::string managerString, managerString2; std::string account, password; std::string name, nameDescription, specialDescription; std::string guildName, rankName, guildNick; Position loginPosition; LightInfo itemsLight; Vocation* vocation; ProtocolGame* client; SchedulerTask* walkTask; Party* party; Group* group; Item* inventory[11]; Player* tradePartner; Item* tradeItem; Item* writeItem; House* editHouse; Npc* shopOwner; typedef std::set<uint32_t> AttackedSet; AttackedSet attackedSet; ShopInfoList shopOffer; PartyList invitePartyList; OutfitMap outfits; LearnedInstantSpellList learnedInstantSpellList; friend class Game; friend class LuaScriptInterface; friend class Npc; friend class Map; friend class Actions; friend class IOLoginData; friend class ProtocolGame; }; #endif Player.cpp ////////////////////////////////////////////////////////////////////////// OpenTibia - an opensource roleplaying game////////////////////////////////////////////////////////////////////////// This program is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program. If not, see <http://www.gnu.org/licenses/>.////////////////////////////////////////////////////////////////////////#include "otpch.h"#include <iostream>#include "player.h"#include "iologindata.h"#include "ioban.h"#include "town.h"#include "house.h"#include "beds.h"#include "combat.h"#if defined(WINDOWS) && !defined(__CONSOLE__)#include "gui.h"#endif#include "movement.h"#include "weapons.h"#include "creatureevent.h"#include "configmanager.h"#include "game.h"#include "chat.h"extern ConfigManager g_config;extern Game g_game;extern Chat g_chat;extern MoveEvents* g_moveEvents;extern Weapons* g_weapons;extern CreatureEvents* g_creatureEvents;AutoList<Player> Player::autoList;#ifdef __ENABLE_SERVER_DIAGNOSTIC__uint32_t Player::playerCount = 0;#endifMuteCountMap Player::muteCountMap;Player::Player(const std::string& _name, ProtocolGame* p):Creature(), transferContainer(ITEM_LOCKER), name(_name), nameDescription(_name), client(p){if(client) client->setPlayer(this);pzLocked = isConnecting = addAttackSkillPoint = requestedOutfit = false;saving = true;lastAttackBlockType = BLOCK_NONE;chaseMode = CHASEMODE_STANDSTILL;fightMode = FIGHTMODE_ATTACK;tradeState = TRADE_NONE;accountManager = MANAGER_NONE;guildLevel = GUILDLEVEL_NONE;promotionLevel = walkTaskEvent = actionTaskEvent = nextStepEvent = bloodHitCount = shieldBlockCount = 0;lastAttack = idleTime = marriage = blessings = balance = premiumDays = mana = manaMax = manaSpent = 0;soul = guildId = levelPercent = magLevelPercent = magLevel = experience = damageImmunities = 0;conditionImmunities = conditionSuppressions = groupId = vocation_id = managerNumber2 = town = skullEnd = 0;lastLogin = lastLogout = lastIP = messageTicks = messageBuffer = nextAction = 0;editListId = maxWriteLen = windowTextId = rankId = 0;purchaseCallback = saleCallback = -1;level = shootRange = 1;rates[sKILL__MAGLEVEL] = rates[sKILL__LEVEL] = 1.0f;soulMax = 100;capacity = 400.00;stamina = STAMINA_MAX;lastLoad = lastPing = lastPong = OTSYS_TIME();writeItem = NULL;group = NULL;editHouse = NULL;shopOwner = NULL;tradeItem = NULL;tradePartner = NULL;walkTask = NULL;setVocation(0);setParty(NULL);transferContainer.setParent(NULL);for(int32_t i = 0; i < 11; i++){ inventory[i] = NULL; inventoryAbilities[i] = false;}for(int32_t i = SKILL_FIRST; i <= SKILL_LAST; ++i){ skills[i][sKILL_LEVEL] = 10; skills[i][sKILL_TRIES] = skills[i][sKILL_PERCENT] = 0; rates[i] = 1.0f;}for(int32_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) varSkills[i] = 0;for(int32_t i = STAT_FIRST; i <= STAT_LAST; ++i) varStats[i] = 0;for(int32_t i = LOSS_FIRST; i <= LOSS_LAST; ++i) lossPercent[i] = 100;for(int8_t i = 0; i <= 13; i++) talkState[i] = false;#ifdef __ENABLE_SERVER_DIAGNOSTIC__playerCount++;#endif}Player::~Player(){#ifdef __ENABLE_SERVER_DIAGNOSTIC__playerCount--;#endifsetWriteItem(NULL);for(int32_t i = 0; i < 11; i++){ if(inventory[i]) { inventory[i]->setParent(NULL); inventory[i]->unRef(); inventory[i] = NULL; inventoryAbilities[i] = false; }}setNextWalkActionTask(NULL);transferContainer.setParent(NULL);for(DepotMap::iterator it = depots.begin(); it != depots.end(); it++) it->second.first->unRef();}void Player::setVocation(uint32_t vocId){vocation_id = vocId;vocation = Vocations::getInstance()->getVocation(vocId);soulMax = vocation->getGain(GAIN_SOUL);if(Condition* condition = getCondition(CONDITION_REGENERATION, CONDITIONID_DEFAULT)){ condition->setParam(CONDITIONPARAM_HEALTHGAIN, vocation->getGainAmount(GAIN_HEALTH)); condition->setParam(CONDITIONPARAM_HEALTHTICKS, (vocation->getGainTicks(GAIN_HEALTH) * 1000)); condition->setParam(CONDITIONPARAM_MANAGAIN, vocation->getGainAmount(GAIN_MANA)); condition->setParam(CONDITIONPARAM_MANATICKS, (vocation->getGainTicks(GAIN_MANA) * 1000));}}bool Player::isPushable() const{return accountManager == MANAGER_NONE && !hasFlag(PlayerFlag_CannotBePushed) && Creature::isPushable();}std::string Player::getDescription(int32_t lookDistance) const{std::stringstream s;if(lookDistance == -1){ s << "yourself."; if(hasFlag(PlayerFlag_ShowGroupNameInsteadOfVocation)) s << " You are " << group->getName(); else if(vocation_id != 0) s << " You are " << vocation->getDescription(); else s << " You have no vocation";}else{ s << nameDescription; if(!hasCustomFlag(PlayerCustomFlag_HideLevel)) s << " (Level " << level << ")"; s << ". " << (sex % 2 ? "He" : "She"); if(hasFlag(PlayerFlag_ShowGroupNameInsteadOfVocation)) s << " is " << group->getName(); else if(vocation_id != 0) s << " is " << vocation->getDescription(); else s << " has no vocation"; s << getSpecialDescription();}std::string tmp;if(marriage && IOLoginData::getInstance()->getNameByGuid(marriage, tmp)){ s << ", "; if(vocation_id == 0) { if(lookDistance == -1) s << "and you are"; else s << "and is"; s << " "; } s << (sex % 2 ? "husband" : "wife") << " of " << tmp;}s << ".";if(guildId){ if(lookDistance == -1) s << " You are "; else s << " " << (sex % 2 ? "He" : "She") << " is "; s << (rankName.empty() ? "a member" : rankName)<< " of the " << guildName; if(!guildNick.empty()) s << " (" << guildNick << ")"; s << ".";}return s.str();}Item* Player::getInventoryItem(slots_t slot) const{if(slot > SLOT_PRE_FIRST && slot < SLOT_LAST) return inventory[slot];if(slot == SLOT_HAND) return inventory[sLOT_LEFT] ? inventory[sLOT_LEFT] : inventory[sLOT_RIGHT];return NULL;}Item* Player::getEquippedItem(slots_t slot) const{Item* item = getInventoryItem(slot);if(!item) return NULL;switch(slot){ case SLOT_LEFT: case SLOT_RIGHT: return item->getWieldPosition() == SLOT_HAND ? item : NULL; default: break;}return item->getWieldPosition() == slot ? item : NULL;}void Player::setConditionSuppressions(uint32_t conditions, bool remove){if(!remove) conditionSuppressions |= conditions;else conditionSuppressions &= ~conditions;}Item* Player::getWeapon(bool ignoreAmmo /*= false*/){Item* item;for(uint32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++){ item = getEquippedItem((slots_t)slot); if(!item) continue; switch(item->getWeaponType()) { case WEAPON_SWORD: case WEAPON_AXE: case WEAPON_CLUB: case WEAPON_WAND: case WEAPON_FIST: { const Weapon* weapon = g_weapons->getWeapon(item); if(weapon) return item; break; } case WEAPON_DIST: { if(!ignoreAmmo && item->getAmmoType() != AMMO_NONE) { Item* ammoItem = getInventoryItem(SLOT_AMMO); if(ammoItem && ammoItem->getAmmoType() == item->getAmmoType()) { const Weapon* weapon = g_weapons->getWeapon(ammoItem); if(weapon) { shootRange = item->getShootRange(); return ammoItem; } } } else { const Weapon* weapon = g_weapons->getWeapon(item); if(weapon) { shootRange = item->getShootRange(); return item; } } break; } default: break; }}return NULL;}WeaponType_t Player::getWeaponType(){if(Item* item = getWeapon()) return item->getWeaponType();return WEAPON_NONE;}int32_t Player::getWeaponSkill(const Item* item) const{if(!item) return getSkill(SKILL_FIST, SKILL_LEVEL);switch(item->getWeaponType()){ case WEAPON_SWORD: return getSkill(SKILL_SWORD, SKILL_LEVEL); case WEAPON_CLUB: return getSkill(SKILL_CLUB, SKILL_LEVEL); case WEAPON_AXE: return getSkill(SKILL_AXE, SKILL_LEVEL); case WEAPON_FIST: return getSkill(SKILL_FIST, SKILL_LEVEL); case WEAPON_DIST: return getSkill(SKILL_DIST, SKILL_LEVEL); default: break;}return 0;}int32_t Player::getArmor() const{int32_t armor = 0;for(int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i){ if(Item* item = getInventoryItem((slots_t)i)) armor += item->getArmor();}if(vocation->getMultiplier(MULTIPLIER_ARMOR) != 1.0) return int32_t(armor * vocation->getMultiplier(MULTIPLIER_ARMOR));return armor;}void Player::getShieldAndWeapon(const Item* &shield, const Item* &weapon) const{shield = weapon = NULL;Item* item = NULL;for(uint32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++){ item = getInventoryItem((slots_t)slot); if(!item) continue; switch(item->getWeaponType()) { case WEAPON_NONE: break; case WEAPON_SHIELD: { if(!shield || (shield && item->getDefense() > shield->getDefense())) shield = item; break; } default: //weapons that are not shields { weapon = item; break; } }}}int32_t Player::getDefense() const{int32_t baseDefense = 5, defenseValue = 0, defenseSkill = 0, extraDefense = 0;float defenseFactor = getDefenseFactor();const Item* weapon = NULL;const Item* shield = NULL;getShieldAndWeapon(shield, weapon);if(weapon){ extraDefense = weapon->getExtraDefense(); defenseValue = baseDefense + weapon->getDefense(); defenseSkill = getWeaponSkill(weapon);}if(shield && shield->getDefense() > defenseValue){ if(shield->getExtraDefense() > extraDefense) extraDefense = shield->getExtraDefense(); defenseValue = baseDefense + shield->getDefense(); defenseSkill = getSkill(SKILL_SHIELD, SKILL_LEVEL);}if(!defenseSkill) return 0;defenseValue += extraDefense;if(vocation->getMultiplier(MULTIPLIER_DEFENSE) != 1.0) defenseValue = int32_t(defenseValue * vocation->getMultiplier(MULTIPLIER_DEFENSE));return ((int32_t)std::ceil(((float)(defenseSkill * (defenseValue * 0.015)) + (defenseValue * 0.1)) * defenseFactor));}float Player::getAttackFactor() const{switch(fightMode){ case FIGHTMODE_BALANCED: return 1.2f; case FIGHTMODE_DEFENSE: return 2.0f; case FIGHTMODE_ATTACK: default: break;}return 1.0f;}float Player::getDefenseFactor() const{switch(fightMode){ case FIGHTMODE_BALANCED: return 1.2f; case FIGHTMODE_DEFENSE: { if((OTSYS_TIME() - lastAttack) < const_cast<Player*>(this)->getAttackSpeed()) //attacking will cause us to get into normal defense return 1.0f; return 2.0f; } case FIGHTMODE_ATTACK: default: break;}return 1.0f;}void Player::sendIcons() const{if(!client) return;uint32_t icons = 0;for(ConditionList::const_iterator it = conditions.begin(); it != conditions.end(); ++it){ if(!isSuppress((*it)->getType())) icons |= (*it)->getIcons();}if(getZone() == ZONE_PROTECTION) icons |= ICON_PROTECTIONZONE;if(pzLocked) icons |= ICON_PZ;client->sendIcons(icons);}void Player::updateInventoryWeight(){inventoryWeight = 0.00;if(hasFlag(PlayerFlag_HasInfiniteCapacity)) return;for(int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i){ if(Item* item = getInventoryItem((slots_t)i)) inventoryWeight += item->getWeight(); mana = inventoryWeight - 392.80;}}void Player::updateInventoryGoods(uint32_t itemId){if(Item::items[itemId].worth){ sendGoods(); return;}for(ShopInfoList::iterator it = shopOffer.begin(); it != shopOffer.end(); ++it){ if(it->itemId != itemId) continue; sendGoods(); break;}}int32_t Player::getPlayerInfo(playerinfo_t playerinfo) const{switch(playerinfo){ case PLAYERINFO_LEVEL: return level; case PLAYERINFO_LEVELPERCENT: return levelPercent; case PLAYERINFO_MAGICLEVEL: return std::max((int32_t)0, ((int32_t)magLevel + varStats[sTAT_MAGICLEVEL])); case PLAYERINFO_MAGICLEVELPERCENT: return magLevelPercent; case PLAYERINFO_HEALTH: return health; case PLAYERINFO_MAXHEALTH: return std::max((int32_t)1, ((int32_t)healthMax + varStats[sTAT_MAXHEALTH])); case PLAYERINFO_MANA: return mana; case PLAYERINFO_MAXMANA: return std::max((int32_t)0, ((int32_t)manaMax + varStats[sTAT_MAXMANA])); case PLAYERINFO_SOUL: return std::max((int32_t)0, ((int32_t)soul + varStats[sTAT_SOUL])); default: break;}return 0;}int32_t Player::getSkill(skills_t skilltype, skillsid_t skillinfo) const{int32_t ret = skills[skilltype][skillinfo];if(skillinfo == SKILL_LEVEL) ret += varSkills[skilltype];return std::max((int32_t)0, ret);}void Player::addSkillAdvance(skills_t skill, uint32_t count, bool useMultiplier/* = true*/){if(!count) return;//player has reached max skilluint32_t currReqTries = vocation->getReqSkillTries(skill, skills[skill][sKILL_LEVEL]), nextReqTries = vocation->getReqSkillTries(skill, skills[skill][sKILL_LEVEL] + 1);if(currReqTries > nextReqTries) return;if(useMultiplier) count = uint32_t((double)count * rates[skill] * g_config.getDouble(ConfigManager::RATE_SKILL));std::stringstream s;while(skills[skill][sKILL_TRIES] + count >= nextReqTries){ count -= nextReqTries - skills[skill][sKILL_TRIES]; skills[skill][sKILL_TRIES] = skills[skill][sKILL_PERCENT] = 0; skills[skill][sKILL_LEVEL]++; s.str(""); s << "You advanced in " << getSkillName(skill); if(g_config.getBool(ConfigManager::ADVANCING_SKILL_LEVEL)) s << " [" << skills[skill][sKILL_LEVEL] << "]"; s << "."; sendTextMessage(MSG_EVENT_ADVANCE, s.str().c_str()); CreatureEventList advanceEvents = getCreatureEvents(CREATURE_EVENT_ADVANCE); for(CreatureEventList::iterator it = advanceEvents.begin(); it != advanceEvents.end(); ++it) (*it)->executeAdvance(this, skill, (skills[skill][sKILL_LEVEL] - 1), skills[skill][sKILL_LEVEL]); currReqTries = nextReqTries; nextReqTries = vocation->getReqSkillTries(skill, skills[skill][sKILL_LEVEL] + 1); if(currReqTries > nextReqTries) { count = 0; break; }}if(count) skills[skill][sKILL_TRIES] += count;//update percentuint32_t newPercent = Player::getPercentLevel(skills[skill][sKILL_TRIES], nextReqTries); if(skills[skill][sKILL_PERCENT] != newPercent){ skills[skill][sKILL_PERCENT] = newPercent; sendSkills(); }else if(!s.str().empty()) sendSkills();}void Player::setVarStats(stats_t stat, int32_t modifier){varStats[stat] += modifier;switch(stat){ case STAT_MAXHEALTH: { if(getHealth() > getMaxHealth()) Creature::changeHealth(getMaxHealth() - getHealth()); else g_game.addCreatureHealth(this); break; } case STAT_MAXMANA: { if(getMana() > getMaxMana()) Creature::changeMana(getMaxMana() - getMana()); break; } default: break;}}int32_t Player::getDefaultStats(stats_t stat){switch(stat){ case STAT_MAGICLEVEL: return getMagicLevel() - getVarStats(STAT_MAGICLEVEL); case STAT_MAXHEALTH: return getMaxHealth() - getVarStats(STAT_MAXHEALTH); case STAT_MAXMANA: return getMaxMana() - getVarStats(STAT_MAXMANA); case STAT_SOUL: return getSoul() - getVarStats(STAT_SOUL); default: break;}return 0;}Container* Player::getContainer(uint32_t cid){for(ContainerVector::iterator it = containerVec.begin(); it != containerVec.end(); ++it){ if(it->first == cid) return it->second;}return NULL;}int32_t Player::getContainerID(const Container* container) const{for(ContainerVector::const_iterator cl = containerVec.begin(); cl != containerVec.end(); ++cl){ if(cl->second == container) return cl->first;}return -1;}void Player::addContainer(uint32_t cid, Container* container){#ifdef __DEBUG__std::cout << getName() << ", addContainer: " << (int32_t)cid << std::endl;#endifif(cid > 0xF) return;for(ContainerVector::iterator cl = containerVec.begin(); cl != containerVec.end(); ++cl){ if(cl->first == cid) { cl->second = container; return; }}containerVec.push_back(std::make_pair(cid, container));}void Player::closeContainer(uint32_t cid){for(ContainerVector::iterator cl = containerVec.begin(); cl != containerVec.end(); ++cl){ if(cl->first == cid) { containerVec.erase(cl); break; }}#ifdef __DEBUG__std::cout << getName() << ", closeContainer: " << (int32_t)cid << std::endl;#endif}bool Player::canOpenCorpse(uint32_t ownerId){return getID() == ownerId || (party && party->canOpenCorpse(ownerId)) || hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges);}uint16_t Player::getLookCorpse() const{if(sex % 2) return ITEM_MALE_CORPSE;return ITEM_FEMALE_CORPSE;}void Player::dropLoot(Container* corpse){if(!corpse || lootDrop != LOOT_DROP_FULL) return;uint32_t start = g_config.getNumber(ConfigManager::BLESS_REDUCTION_BASE), loss = lossPercent[LOSS_CONTAINERS], bless = getBlessings();while(bless > 0 && loss > 0){ loss -= start; start -= g_config.getNumber(ConfigManager::BLESS_REDUCTION_DECREAMENT); bless--;}uint32_t itemLoss = (uint32_t)std::floor((5. + loss) * lossPercent[LOSS_ITEMS] / 1000.);for(int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i){ Item* item = inventory[i]; if(!item) continue; uint32_t rand = random_range(1, 100); if(skull > SKULL_WHITE || (item->getContainer() && rand < loss) || (!item->getContainer() && rand < itemLoss)) { g_game.internalMoveItem(NULL, this, corpse, INDEX_WHEREEVER, item, item->getItemCount(), 0); sendRemoveInventoryItem((slots_t)i, inventory[(slots_t)i]); }}}bool Player::setStorage(const uint32_t key, const std::string& value){if(!IS_IN_KEYRANGE(key, RESERVED_RANGE)) return Creature::setStorage(key, value);if(IS_IN_KEYRANGE(key, OUTFITS_RANGE)){ uint32_t lookType = atoi(value.c_str()) >> 16; uint32_t addons = atoi(value.c_str()) & 0xFF; if(addons < 4) { Outfit outfit; if(Outfits::getInstance()->getOutfit(lookType, outfit)) return addOutfit(outfit.outfitId, addons); } else std::cout << "[Warning - Player::setStorage] Invalid addons value key: " << key << ", value: " << value << " for player: " << getName() << std::endl;}else if(IS_IN_KEYRANGE(key, OUTFITSID_RANGE)){ uint32_t outfitId = atoi(value.c_str()) >> 16; uint32_t addons = atoi(value.c_str()) & 0xFF; if(addons < 4) return addOutfit(outfitId, addons); else std::cout << "[Warning - Player::setStorage] Invalid addons value key: " << key << ", value: " << value << " for player: " << getName() << std::endl;}else std::cout << "[Warning - Player::setStorage] Unknown reserved key: " << key << " for player: " << getName() << std::endl;return false;}void Player::eraseStorage(const uint32_t key){Creature::eraseStorage(key);if(IS_IN_KEYRANGE(key, RESERVED_RANGE)) std::cout << "[Warning - Player::eraseStorage] Unknown reserved key: " << key << " for player: " << name << std::endl;}bool Player::canSee(const Position& pos) const{if(client) return client->canSee(pos);return false;}bool Player::canSeeCreature(const Creature* creature) const{if(creature == this) return true;if(const Player* player = creature->getPlayer()) return !player->isGhost() || getGhostAccess() >= player->getGhostAccess();return !creature->isInvisible() || canSeeInvisibility();}bool Player::canWalkthrough(const Creature* creature) const{if(!creature) return true;if(creature == this) return false;const Player* player = creature->getPlayer();if(!player) return false;if(g_game.getWorldType() == WORLD_TYPE_NO_PVP && player->getTile()->ground && player->getTile()->ground->getID() != ITEM_GLOWING_SWITCH) return true;return player->isGhost() && getGhostAccess() < player->getGhostAccess();}Depot* Player::getDepot(uint32_t depotId, bool autoCreateDepot){DepotMap::iterator it = depots.find(depotId);if(it != depots.end()){ return it->second.first; } //create a new depot?if(autoCreateDepot){ Item* locker = Item::CreateItem(ITEM_LOCKER); if(Container* container = locker->getContainer()) { if(Depot* depot = container->getDepot()){ container->__internalAddThing(Item::CreateItem(ITEM_DEPOT)); addDepot(depot, depotId); return depot; } } g_game.freeThing(locker); std::cout << "Failure: Creating a new depot with id: " << depotId << ", for player: " << getName() << std::endl;}return NULL;}bool Player::addDepot(Depot* depot, uint32_t depotId){if(getDepot(depotId, false)) return false;depots[depotId] = std::make_pair(depot, false);depot->setMaxDepotLimit((group != NULL ? group->getDepotLimit(isPremium()) : 1000));return true;}void Player::useDepot(uint32_t depotId, bool value){DepotMap::iterator it = depots.find(depotId);if(it != depots.end()) depots[depotId] = std::make_pair(it->second.first, value);}void Player::sendCancelMessage(ReturnValue message) const{switch(message){ case RET_DESTINATIONOUTOFREACH: sendCancel("Destination is out of reach."); break; case RET_NOTMOVEABLE: sendCancel("You cannot move this object."); break; case RET_DROPTWOHANDEDITEM: sendCancel("Drop the double-handed object first."); break; case RET_BOTHHANDSNEEDTOBEFREE: sendCancel("Both hands needs to be free."); break; case RET_CANNOTBEDRESSED: sendCancel("You cannot dress this object there."); break; case RET_PUTTHISOBJECTINYOURHAND: sendCancel("Put this object in your hand."); break; case RET_PUTTHISOBJECTINBOTHHANDS: sendCancel("Put this object in both hands."); break; case RET_CANONLYUSEONEWEAPON: sendCancel("You may use only one weapon."); break; case RET_TOOFARAWAY: sendCancel("Too far away."); break; case RET_FIRSTGODOWNSTAIRS: sendCancel("First go downstairs."); break; case RET_FIRSTGOUPSTAIRS: sendCancel("First go upstairs."); break; case RET_NOTENOUGHCAPACITY: sendCancel("You can't carry more than 6 pokemons."); break; case RET_CONTAINERNOTENOUGHROOM: sendCancel("You cannot put more objects in this container."); break; case RET_NEEDEXCHANGE: case RET_NOTENOUGHROOM: sendCancel("There is not enough room."); break; case RET_CANNOTPICKUP: sendCancel("You cannot pickup this object."); break; case RET_CANNOTTHROW: sendCancel("You cannot throw there."); break; case RET_THEREISNOWAY: sendCancel("There is no way."); break; case RET_THISISIMPOSSIBLE: sendCancel("This is impossible."); break; case RET_PLAYERISPZLOCKED: sendCancel("You cannot enter a protection zone after attacking another player."); break; case RET_PLAYERISNOTINVITED: sendCancel("You are not invited."); break; case RET_CREATUREDOESNOTEXIST: sendCancel("Creature does not exist."); break; case RET_DEPOTISFULL: sendCancel("You cannot put more items in this depot."); break; case RET_CANNOTUSETHISOBJECT: sendCancel("You cannot use this object."); break; case RET_PLAYERWITHTHISNAMEISNOTONLINE: sendCancel("A player with this name is not online."); break; case RET_NOTREQUIREDLEVELTOUSERUNE: sendCancel("You do not have the required magic level to use this rune."); break; case RET_YOUAREALREADYTRADING: sendCancel("You are already trading."); break; case RET_THISPLAYERISALREADYTRADING: sendCancel("This player is already trading."); break; case RET_YOUMAYNOTLOGOUTDURINGAFIGHT: sendCancel("You may not logout during or immediately after a fight!"); break; case RET_DIRECTPLAYERSHOOT: sendCancel("You are not allowed to shoot directly on players."); break; case RET_NOTENOUGHLEVEL: sendCancel("You do not have enough level."); break; case RET_NOTENOUGHMAGICLEVEL: sendCancel("You do not have enough magic level."); break; case RET_NOTENOUGHMANA: sendCancel("You do not have enough mana."); break; case RET_NOTENOUGHSOUL: sendCancel("You do not have enough soul."); break; case RET_YOUAREEXHAUSTED: sendCancel("You are exhausted."); break; case RET_CANONLYUSETHISRUNEONCREATURES: sendCancel("You can only use this rune on creatures."); break; case RET_PLAYERISNOTREACHABLE: sendCancel("Player is not reachable."); break; case RET_CREATUREISNOTREACHABLE: sendCancel("Creature is not reachable."); break; case RET_ACTIONNOTPERMITTEDINPROTECTIONZONE: sendCancel("This action is not permitted in a protection zone."); break; case RET_YOUMAYNOTATTACKTHISPLAYER: sendCancel("You may not attack this player."); break; case RET_YOUMAYNOTATTACKTHISCREATURE: sendCancel("You may not attack this creature."); break; case RET_YOUMAYNOTATTACKAPERSONINPROTECTIONZONE: sendCancel("You may not attack a person in a protection zone."); break; case RET_YOUMAYNOTATTACKAPERSONWHILEINPROTECTIONZONE: sendCancel("You may not attack a person while you are in a protection zone."); break; case RET_YOUCANONLYUSEITONCREATURES: sendCancel("You can only use it on creatures."); break; case RET_TURNSECUREMODETOATTACKUNMARKEDPLAYERS: sendCancel("Turn secure mode off if you really want to attack unmarked players."); break; case RET_YOUNEEDPREMIUMACCOUNT: sendCancel("You need a premium account."); break; case RET_YOUNEEDTOLEARNTHISSPELL: sendCancel("You need to learn this spell first."); break; case RET_YOURVOCATIONCANNOTUSETHISSPELL: sendCancel("Your vocation cannot use this spell."); break; case RET_YOUNEEDAWEAPONTOUSETHISSPELL: sendCancel("You need to equip a weapon to use this spell."); break; case RET_PLAYERISPZLOCKEDLEAVEPVPZONE: sendCancel("You cannot leave a pvp zone after attacking another player."); break; case RET_PLAYERISPZLOCKEDENTERPVPZONE: sendCancel("You cannot enter a pvp zone after attacking another player."); break; case RET_ACTIONNOTPERMITTEDINANOPVPZONE: sendCancel("This action is not permitted in a non-pvp zone."); break; case RET_YOUCANNOTLOGOUTHERE: sendCancel("You cannot logout here."); break; case RET_YOUNEEDAMAGICITEMTOCASTSPELL: sendCancel("You need a magic item to cast this spell."); break; case RET_CANNOTCONJUREITEMHERE: sendCancel("You cannot conjure items here."); break; case RET_YOUNEEDTOSPLITYOURSPEARS: sendCancel("You need to split your spears first."); break; case RET_NAMEISTOOAMBIGUOUS: sendCancel("Name is too ambiguous."); break; case RET_CANONLYUSEONESHIELD: sendCancel("You may use only one shield."); break; case RET_YOUARENOTTHEOWNER: sendCancel("You are not the owner."); break; case RET_YOUMAYNOTCASTAREAONBLACKSKULL: sendCancel("You may not cast area spells while you have a black skull."); break; case RET_TILEISFULL: sendCancel("You cannot add more items on this tile."); break; case RET_DONTSHOWMESSAGE: break; case RET_NOTPOSSIBLE: default: sendCancel("Sorry, not possible."); break;}}void Player::sendStats(){if(client) client->sendStats();}Item* Player::getWriteItem(uint32_t& _windowTextId, uint16_t& _maxWriteLen){_windowTextId = windowTextId;_maxWriteLen = maxWriteLen;return writeItem;}void Player::setWriteItem(Item* item, uint16_t _maxWriteLen/* = 0*/){windowTextId++;if(writeItem) writeItem->unRef();if(item){ writeItem = item; maxWriteLen = _maxWriteLen; writeItem->addRef();}else{ writeItem = NULL; maxWriteLen = 0;}}House* Player::getEditHouse(uint32_t& _windowTextId, uint32_t& _listId){_windowTextId = windowTextId;_listId = editListId;return editHouse;}void Player::setEditHouse(House* house, uint32_t listId/* = 0*/){windowTextId++;editHouse = house;editListId = listId;}void Player::sendHouseWindow(House* house, uint32_t listId) const{if(!client) return;std::string text;if(house->getAccessList(listId, text)) client->sendHouseWindow(windowTextId, house, listId, text);}void Player::sendCreatureChangeVisible(const Creature* creature, Visible_t visible){if(!client) return;const Player* player = creature->getPlayer();if(player == this || (player && (visible < VISIBLE_GHOST_APPEAR || getGhostAccess() >= player->getGhostAccess())) || (!player && canSeeInvisibility())) sendCreatureChangeOutfit(creature, creature->getCurrentOutfit());else if(visible == VISIBLE_DISAPPEAR || visible == VISIBLE_GHOST_DISAPPEAR) sendCreatureDisappear(creature, creature->getTile()->getClientIndexOfThing(this, creature));else sendCreatureAppear(creature);}void Player::sendAddContainerItem(const Container* container, const Item* item){if(!client) return;for(ContainerVector::const_iterator cl = containerVec.begin(); cl != containerVec.end(); ++cl){ if(cl->second == container) client->sendAddContainerItem(cl->first, item);}}void Player::sendUpdateContainerItem(const Container* container, uint8_t slot, const Item* oldItem, const Item* newItem){if(!client) return;for(ContainerVector::const_iterator cl = containerVec.begin(); cl != containerVec.end(); ++cl){ if(cl->second == container) client->sendUpdateContainerItem(cl->first, slot, newItem);}}void Player::sendRemoveContainerItem(const Container* container, uint8_t slot, const Item* item){if(!client) return;for(ContainerVector::const_iterator cl = containerVec.begin(); cl != containerVec.end(); ++cl){ if(cl->second == container) client->sendRemoveContainerItem(cl->first, slot);}}void Player::onUpdateTileItem(const Tile* tile, const Position& pos, const Item* oldItem,const ItemType& oldType, const Item* newItem, const ItemType& newType){Creature::onUpdateTileItem(tile, pos, oldItem, oldType, newItem, newType);if(oldItem != newItem) onRemoveTileItem(tile, pos, oldType, oldItem);if(tradeState != TRADE_TRANSFER && tradeItem && oldItem == tradeItem) g_game.internalCloseTrade(this);}void Player::onRemoveTileItem(const Tile* tile, const Position& pos, const ItemType& iType, const Item* item){Creature::onRemoveTileItem(tile, pos, iType, item);if(tradeState == TRADE_TRANSFER) return;checkTradeState(item);if(tradeItem){ const Container* container = item->getContainer(); if(container && container->isHoldingItem(tradeItem)) g_game.internalCloseTrade(this);}}void Player::onCreatureAppear(const Creature* creature){Creature::onCreatureAppear(creature);if(creature != this) return;Item* item = NULL;for(int32_t slot = SLOT_FIRST; slot < SLOT_LAST; ++slot){ if(!(item = getInventoryItem((slots_t)slot))) continue; item->__startDecaying(); g_moveEvents->onPlayerEquip(this, item, (slots_t)slot, false);}if(BedItem* bed = Beds::getInstance()->getBedBySleeper(guid)) bed->wakeUp();Outfit outfit;if(Outfits::getInstance()->getOutfit(defaultOutfit.lookType, outfit)) outfitAttributes = Outfits::getInstance()->addAttributes(getID(), outfit.outfitId, sex, defaultOutfit.lookAddons);if(lastLogout && stamina < STAMINA_MAX){ int64_t ticks = (int64_t)time(NULL) - lastLogout - 600; if(ticks > 0) { ticks = (int64_t)((double)(ticks * 1000) / g_config.getDouble(ConfigManager::RATE_STAMINA_GAIN)); int64_t premium = g_config.getNumber(ConfigManager::STAMINA_LIMIT_TOP) * STAMINA_MULTIPLIER, period = ticks; if((int64_t)stamina <= premium) { period += stamina; if(period > premium) period -= premium; else period = 0; useStamina(ticks - period); } if(period > 0) { ticks = (int64_t)((g_config.getDouble(ConfigManager::RATE_STAMINA_GAIN) * period) / g_config.getDouble(ConfigManager::RATE_STAMINA_THRESHOLD)); if(stamina + ticks > STAMINA_MAX) ticks = STAMINA_MAX - stamina; useStamina(ticks); } sendStats(); }}g_game.checkPlayersRecord(this);if(!isGhost()) IOLoginData::getInstance()->updateOnlineStatus(guid, true);#if defined(WINDOWS) && !defined(__CONSOLE__)GUI::getInstance()->m_pBox.addPlayer(this);#endifif(g_config.getBool(ConfigManager::DISPLAY_LOGGING)) std::cout << name << " has logged in." << std::endl;}void Player::onAttackedCreatureDisappear(bool isLogout){sendCancelTarget();if(!isLogout) sendTextMessage(MSG_STATUS_SMALL, "Target lost.");}void Player::onFollowCreatureDisappear(bool isLogout){sendCancelTarget();if(!isLogout) sendTextMessage(MSG_STATUS_SMALL, "Target lost.");}void Player::onChangeZone(ZoneType_t zone){if(attackedCreature && zone == ZONE_PROTECTION && !hasFlag(PlayerFlag_IgnoreProtectionZone)){ setAttackedCreature(NULL); onAttackedCreatureDisappear(false);}sendIcons();}void Player::onAttackedCreatureChangeZone(ZoneType_t zone){if(zone == ZONE_PROTECTION && !hasFlag(PlayerFlag_IgnoreProtectionZone)){ setAttackedCreature(NULL); onAttackedCreatureDisappear(false);}else if(zone == ZONE_NOPVP && attackedCreature->getPlayer() && !hasFlag(PlayerFlag_IgnoreProtectionZone)){ setAttackedCreature(NULL); onAttackedCreatureDisappear(false);}else if(zone == ZONE_NORMAL && g_game.getWorldType() == WORLD_TYPE_NO_PVP && attackedCreature->getPlayer()){ //attackedCreature can leave a pvp zone if not pzlocked setAttackedCreature(NULL); onAttackedCreatureDisappear(false);}}void Player::onCreatureDisappear(const Creature* creature, bool isLogout){Creature::onCreatureDisappear(creature, isLogout);if(creature != this) return;if(isLogout){ loginPosition = getPosition(); lastLogout = time(NULL);}if(eventWalk) setFollowCreature(NULL);closeShopWindow();if(tradePartner) g_game.internalCloseTrade(this);clearPartyInvitations();if(party) party->leave(this);g_game.cancelRuleViolation(this);if(hasFlag(PlayerFlag_CanAnswerRuleViolations)){ PlayerVector closeReportList; for(RuleViolationsMap::const_iterator it = g_game.getRuleViolations().begin(); it != g_game.getRuleViolations().end(); ++it) { if(it->second->gamemaster == this) closeReportList.push_back(it->second->reporter); } for(PlayerVector::iterator it = closeReportList.begin(); it != closeReportList.end(); ++it) g_game.closeRuleViolation(*it);}g_chat.removeUserFromAllChannels(this);if(!isGhost()) IOLoginData::getInstance()->updateOnlineStatus(guid, false);#if defined(WINDOWS) && !defined(__CONSOLE__)GUI::getInstance()->m_pBox.removePlayer(this);#endifif(g_config.getBool(ConfigManager::DISPLAY_LOGGING)) std::cout << getName() << " has logged out." << std::endl;bool saved = false;for(uint32_t tries = 0; !saved && tries < 3; ++tries){ if(IOLoginData::getInstance()->savePlayer(this)) saved = true;#ifdef __DEBUG__ else std::cout << "Error while saving player: " << getName() << ", strike " << tries << "." << std::endl;#endif}if(!saved)#ifndef __DEBUG__ std::cout << "Error while saving player: " << getName() << "." << std::endl;#else std::cout << "Player " << getName() << " couldn't be saved." << std::endl;#endif}void Player::openShopWindow(){sendShop();sendGoods();}void Player::closeShopWindow(Npc* npc/* = NULL*/, int32_t onBuy/* = -1*/, int32_t onSell/* = -1*/){if(npc || (npc = getShopOwner(onBuy, onSell))) npc->onPlayerEndTrade(this, onBuy, onSell);if(shopOwner) sendCloseShop();shopOwner = NULL;purchaseCallback = saleCallback = -1;shopOffer.clear();}bool Player::canShopItem(uint16_t itemId, uint8_t subType, ShopEvent_t event){for(ShopInfoList::iterator sit = shopOffer.begin(); sit != shopOffer.end(); ++sit){ if(sit->itemId != itemId || ((event != SHOPEVENT_BUY || sit->buyPrice < 0) && (event != SHOPEVENT_SELL || sit->sellPrice < 0))) continue; if(event == SHOPEVENT_SELL) return true; const ItemType& it = Item::items[id]; if(it.isFluidContainer() || it.isSplash() || it.isRune()) return sit->subType == subType; return true;}return false;}void Player::onWalk(Direction& dir){Creature::onWalk(dir);setNextActionTask(NULL);setNextAction(OTSYS_TIME() + getStepDuration(dir));}void Player::onCreatureMove(const Creature* creature, const Tile* newTile, const Position& newPos,const Tile* oldTile, const Position& oldPos, bool teleport){Creature::onCreatureMove(creature, newTile, newPos, oldTile, oldPos, teleport);if(creature != this) return;if(getParty()) getParty()->updateSharedExperience();//check if we should close tradeif(tradeState != TRADE_TRANSFER && ((tradeItem && !Position::areInRange<1,1,0>(tradeItem->getPosition(), getPosition())) || (tradePartner && !Position::areInRange<2,2,0>(tradePartner->getPosition(), getPosition())))) g_game.internalCloseTrade(this);if((teleport || oldPos.z != newPos.z) && !hasCustomFlag(PlayerCustomFlag_CanStairhop)){ int32_t ticks = g_config.getNumber(ConfigManager::STAIRHOP_DELAY); if(ticks > 0) { addExhaust(ticks, EXHAUST_COMBAT); if(Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_PACIFIED, ticks)) addCondition(condition); }}}void Player::onAddContainerItem(const Container* container, const Item* item){checkTradeState(item);}void Player::onUpdateContainerItem(const Container* container, uint8_t slot,const Item* oldItem, const ItemType& oldType, const Item* newItem, const ItemType& newType){if(oldItem != newItem) onRemoveContainerItem(container, slot, oldItem);if(tradeState != TRADE_TRANSFER) checkTradeState(oldItem);}void Player::onRemoveContainerItem(const Container* container, uint8_t slot, const Item* item){if(tradeState == TRADE_TRANSFER) return;checkTradeState(item);if(tradeItem){ if(tradeItem->getParent() != container && container->isHoldingItem(tradeItem)) g_game.internalCloseTrade(this);}}void Player::onCloseContainer(const Container* container){if(!client) return;for(ContainerVector::const_iterator cl = containerVec.begin(); cl != containerVec.end(); ++cl){ if(cl->second == container) client->sendCloseContainer(cl->first);}}void Player::onSendContainer(const Container* container){if(!client) return;bool hasParent = dynamic_cast<const Container*>(container->getParent()) != NULL;for(ContainerVector::const_iterator cl = containerVec.begin(); cl != containerVec.end(); ++cl){ if(cl->second == container) client->sendContainer(cl->first, container, hasParent);}}void Player::onUpdateInventoryItem(slots_t slot, Item* oldItem, const ItemType& oldType,Item* newItem, const ItemType& newType){if(oldItem != newItem) onRemoveInventoryItem(slot, oldItem);if(tradeState != TRADE_TRANSFER) checkTradeState(oldItem);}void Player::onRemoveInventoryItem(slots_t slot, Item* item){if(tradeState == TRADE_TRANSFER) return;checkTradeState(item);if(tradeItem){ const Container* container = item->getContainer(); if(container && container->isHoldingItem(tradeItem)) g_game.internalCloseTrade(this);}}void Player::checkTradeState(const Item* item){if(!tradeItem || tradeState == TRADE_TRANSFER) return;if(tradeItem != item){ const Container* container = dynamic_cast<const Container*>(item->getParent()); while(container != NULL) { if(container == tradeItem) { g_game.internalCloseTrade(this); break; } container = dynamic_cast<const Container*>(container->getParent()); }}else g_game.internalCloseTrade(this);}void Player::setNextWalkActionTask(SchedulerTask* task){if(walkTaskEvent){ Scheduler::getInstance().stopEvent(walkTaskEvent); walkTaskEvent = 0;}delete walkTask;walkTask = task;setIdleTime(0);}void Player::setNextWalkTask(SchedulerTask* task){if(nextStepEvent){ Scheduler::getInstance().stopEvent(nextStepEvent); nextStepEvent = 0;}if(task){ nextStepEvent = Scheduler::getInstance().addEvent(task); setIdleTime(0);}}void Player::setNextActionTask(SchedulerTask* task){if(actionTaskEvent){ Scheduler::getInstance().stopEvent(actionTaskEvent); actionTaskEvent = 0;}if(task){ actionTaskEvent = Scheduler::getInstance().addEvent(task); setIdleTime(0);}}uint32_t Player::getNextActionTime() const{int64_t time = nextAction - OTSYS_TIME();if(time < SCHEDULER_MINTICKS) return SCHEDULER_MINTICKS;return time;}void Player::onThink(uint32_t interval){Creature::onThink(interval);int64_t timeNow = OTSYS_TIME();if(timeNow - lastPing >= 5000){ lastPing = timeNow; if(client) client->sendPing(); else if(g_config.getBool(ConfigManager::STOP_ATTACK_AT_EXIT)) setAttackedCreature(NULL);}if((timeNow - lastPong) >= 60000 && canLogout(true)){ if(client) client->logout(true, true); else if(g_creatureEvents->playerLogout(this, true)) g_game.removeCreature(this, true);}messageTicks += interval;if(messageTicks >= 1500){ messageTicks = 0; addMessageBuffer();}}bool Player::isMuted(uint16_t channelId, SpeakClasses type, uint32_t& time){time = 0;if(hasFlag(PlayerFlag_CannotBeMuted)) return false;int32_t muteTicks = 0;for(ConditionList::iterator it = conditions.begin(); it != conditions.end(); ++it){ if((*it)->getType() == CONDITION_MUTED && (*it)->getSubId() == 0 && (*it)->getTicks() > muteTicks) muteTicks = (*it)->getTicks();}time = (uint32_t)muteTicks / 1000;return time > 0 && type != SPEAK_PRIVATE_PN && (type != SPEAK_CHANNEL_Y || (channelId != CHANNEL_GUILD && !g_chat.isPrivateChannel(channelId)));}void Player::addMessageBuffer(){if(!hasFlag(PlayerFlag_CannotBeMuted) && g_config.getNumber( ConfigManager::MAX_MESSAGEBUFFER) != 0 && messageBuffer > 0) messageBuffer--;}void Player::removeMessageBuffer(){int32_t maxBuffer = g_config.getNumber(ConfigManager::MAX_MESSAGEBUFFER);if(!hasFlag(PlayerFlag_CannotBeMuted) && maxBuffer != 0 && messageBuffer <= maxBuffer + 1){ if(++messageBuffer > maxBuffer) { uint32_t muteCount = 1; MuteCountMap::iterator it = muteCountMap.find(guid); if(it != muteCountMap.end()) muteCount = it->second; uint32_t muteTime = 5 * muteCount * muteCount; muteCountMap[guid] = muteCount + 1; if(Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_MUTED, muteTime * 1000)) addCondition(condition); char buffer[50]; sprintf(buffer, "You are muted for %d seconds.", muteTime); sendTextMessage(MSG_STATUS_SMALL, buffer); }}}void Player::drainHealth(Creature* attacker, CombatType_t combatType, int32_t damage){Creature::drainHealth(attacker, combatType, damage);char buffer[150];if(attacker) sprintf(buffer, "You lose %d hitpoint%s due to an attack by %s.", damage, (damage != 1 ? "s" : ""), attacker->getNameDescription().c_str());else sprintf(buffer, "You lose %d hitpoint%s.", damage, (damage != 1 ? "s" : ""));sendStats();sendTextMessage(MSG_EVENT_DEFAULT, buffer);}void Player::drainMana(Creature* attacker, CombatType_t combatType, int32_t damage){Creature::drainMana(attacker, combatType, damage);char buffer[150];if(attacker) sprintf(buffer, "You lose %d mana blocking an attack by %s.", damage, attacker->getNameDescription().c_str());else sprintf(buffer, "You lose %d mana.", damage);sendStats();}void Player::addManaSpent(uint64_t amount, bool useMultiplier/* = true*/){if(!amount) return;uint64_t currReqMana = vocation->getReqMana(magLevel), nextReqMana = vocation->getReqMana(magLevel + 1);if(currReqMana > nextReqMana) //player has reached max magic level return;if(useMultiplier) amount = uint64_t((double)amount * rates[sKILL__MAGLEVEL] * g_config.getDouble(ConfigManager::RATE_MAGIC));bool advance = false;while(manaSpent + amount >= nextReqMana){ amount -= nextReqMana - manaSpent; manaSpent = 0; magLevel++; char advMsg[50]; sprintf(advMsg, "You advanced to magic level %d.", magLevel); sendTextMessage(MSG_EVENT_ADVANCE, advMsg); advance = true; CreatureEventList advanceEvents = getCreatureEvents(CREATURE_EVENT_ADVANCE); for(CreatureEventList::iterator it = advanceEvents.begin(); it != advanceEvents.end(); ++it) (*it)->executeAdvance(this, SKILL__MAGLEVEL, (magLevel - 1), magLevel); currReqMana = nextReqMana; nextReqMana = vocation->getReqMana(magLevel + 1); if(currReqMana > nextReqMana) { amount = 0; break; }}if(amount) manaSpent += amount;uint32_t newPercent = Player::getPercentLevel(manaSpent, nextReqMana);if(magLevelPercent != newPercent){ magLevelPercent = newPercent; sendStats();}else if(advance) sendStats();}void Player::addExperience(uint64_t exp){uint32_t prevLevel = level;uint64_t nextLevelExp = Player::getExpForLevel(level + 1);if(Player::getExpForLevel(level) > nextLevelExp){ //player has reached max level levelPercent = 0; sendStats(); return;}experience += exp;while(experience >= nextLevelExp){ healthMax += vocation->getGain(GAIN_HEALTH); health += vocation->getGain(GAIN_HEALTH); manaMax += vocation->getGain(GAIN_MANA); mana += vocation->getGain(GAIN_MANA); capacity += vocation->getGainCap(); ++level; nextLevelExp = Player::getExpForLevel(level + 1); if(Player::getExpForLevel(level) > nextLevelExp) //player has reached max level break;}if(prevLevel != level){ updateBaseSpeed(); setBaseSpeed(getBaseSpeed()); g_game.changeSpeed(this, 0); g_game.addCreatureHealth(this); if(getParty()) getParty()->updateSharedExperience(); char advMsg[60]; sprintf(advMsg, "You advanced from Level %d to Level %d.", prevLevel, level); sendTextMessage(MSG_EVENT_ADVANCE, advMsg); CreatureEventList advanceEvents = getCreatureEvents(CREATURE_EVENT_ADVANCE); for(CreatureEventList::iterator it = advanceEvents.begin(); it != advanceEvents.end(); ++it) (*it)->executeAdvance(this, SKILL__LEVEL, prevLevel, level);}uint64_t currLevelExp = Player::getExpForLevel(level);nextLevelExp = Player::getExpForLevel(level + 1);levelPercent = 0;if(nextLevelExp > currLevelExp) levelPercent = Player::getPercentLevel(experience - currLevelExp, nextLevelExp - currLevelExp);sendStats();}void Player::removeExperience(uint64_t exp, bool updateStats/* = true*/){uint32_t prevLevel = level;experience -= std::min(exp, experience);while(level > 1 && experience < Player::getExpForLevel(level)){ level--; healthMax = std::max((int32_t)0, (healthMax - (int32_t)vocation->getGain(GAIN_HEALTH))); manaMax = std::max((int32_t)0, (manaMax - (int32_t)vocation->getGain(GAIN_MANA))); capacity = std::max((double)0, (capacity - (double)vocation->getGainCap()));}if(prevLevel != level){ if(updateStats) { updateBaseSpeed(); setBaseSpeed(getBaseSpeed()); g_game.changeSpeed(this, 0); g_game.addCreatureHealth(this); } char advMsg[90]; sprintf(advMsg, "You were downgraded from Level %d to Level %d.", prevLevel, level); sendTextMessage(MSG_EVENT_ADVANCE, advMsg);}uint64_t currLevelExp = Player::getExpForLevel(level);uint64_t nextLevelExp = Player::getExpForLevel(level + 1);if(nextLevelExp > currLevelExp) levelPercent = Player::getPercentLevel(experience - currLevelExp, nextLevelExp - currLevelExp);else levelPercent = 0;if(updateStats) sendStats();}uint32_t Player::getPercentLevel(uint64_t count, uint64_t nextLevelCount){if(nextLevelCount > 0) return std::min((uint32_t)100, std::max((uint32_t)0, uint32_t(count * 100 / nextLevelCount)));return 0;}void Player::onBlockHit(BlockType_t blockType){if(shieldBlockCount > 0){ --shieldBlockCount; if(hasShield()) addSkillAdvance(SKILL_SHIELD, 1);}}void Player::onAttackedCreatureBlockHit(Creature* target, BlockType_t blockType){Creature::onAttackedCreatureBlockHit(target, blockType);lastAttackBlockType = blockType;switch(blockType){ case BLOCK_NONE: { addAttackSkillPoint = true; bloodHitCount = 30; shieldBlockCount = 30; break; } case BLOCK_DEFENSE: case BLOCK_ARMOR: { //need to draw blood every 30 hits if(bloodHitCount > 0) { addAttackSkillPoint = true; --bloodHitCount; } else addAttackSkillPoint = false; break; } default: { addAttackSkillPoint = false; break; }}}bool Player::hasShield() const{bool result = false;Item* item = getInventoryItem(SLOT_LEFT);if(item && item->getWeaponType() == WEAPON_SHIELD) result = true;item = getInventoryItem(SLOT_RIGHT);if(item && item->getWeaponType() == WEAPON_SHIELD) result = true;return result;}BlockType_t Player::blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage,bool checkDefense/* = false*/, bool checkArmor/* = false*/){BlockType_t blockType = Creature::blockHit(attacker, combatType, damage, checkDefense, checkArmor);if(attacker){ int16_t color = g_config.getNumber(ConfigManager::SQUARE_COLOR); if(color < 0) color = random_range(0, 255); sendCreatureSquare(attacker, (SquareColor_t)color);}if(blockType != BLOCK_NONE) return blockType;if(vocation->getMultiplier(MULTIPLIER_MAGICDEFENSE) != 1.0 && combatType != COMBAT_NONE && combatType != COMBAT_PHYSICALDAMAGE && combatType == COMBAT_UNDEFINEDDAMAGE && combatType != COMBAT_DROWNDAMAGE) damage -= (int32_t)std::ceil((double)(damage * vocation->getMultiplier(MULTIPLIER_MAGICDEFENSE)) / 100.);if(damage > 0){ Item* item = NULL; int32_t blocked = 0, reflected = 0; for(int32_t slot = SLOT_FIRST; slot < SLOT_LAST; ++slot) { if(!(item = getInventoryItem((slots_t)slot)) || (g_moveEvents->hasEquipEvent(item) && !isItemAbilityEnabled((slots_t)slot))) continue; const ItemType& it = Item::items[item->getID()]; if(it.abilities.absorb[combatType]) { blocked += (int32_t)std::ceil((double)(damage * it.abilities.absorb[combatType]) / 100.); if(item->hasCharges()) g_game.transformItem(item, item->getID(), std::max((int32_t)0, (int32_t)item->getCharges() - 1)); } if(it.abilities.reflect[REFLECT_PERCENT][combatType] && it.abilities.reflect[REFLECT_CHANCE][combatType] < random_range(0, 100)) { reflected += (int32_t)std::ceil((double)(damage * it.abilities.reflect[REFLECT_PERCENT][combatType]) / 100.); if(item->hasCharges() && !it.abilities.absorb[combatType]) g_game.transformItem(item, item->getID(), std::max((int32_t)0, (int32_t)item->getCharges() - 1)); } } if(outfitAttributes) { uint32_t tmp = Outfits::getInstance()->getOutfitAbsorb(defaultOutfit.lookType, sex, combatType); if(tmp) blocked += (int32_t)std::ceil((double)(damage * tmp) / 100.); tmp = Outfits::getInstance()->getOutfitReflect(defaultOutfit.lookType, sex, combatType); if(tmp) reflected += (int32_t)std::ceil((double)(damage * tmp) / 100.); } if(vocation->getAbsorb(combatType)) blocked += (int32_t)std::ceil((double)(damage * vocation->getAbsorb(combatType)) / 100.); if(vocation->getReflect(combatType)) reflected += (int32_t)std::ceil((double)(damage * vocation->getReflect(combatType)) / 100.); if(damage <= 0) { damage = 0; blockType = BLOCK_DEFENSE; }}return blockType;}uint32_t Player::getIP() const{if(client) return client->getIP();return lastIP;}bool Player::onDeath(){Item* preventLoss = NULL;Item* preventDrop = NULL;if(getZone() == ZONE_PVP){ setDropLoot(LOOT_DROP_NONE); setLossSkill(false);}else if(skull < SKULL_RED && g_game.getWorldType() != WORLD_TYPE_PVP_ENFORCED){ Item* item = NULL; for(int32_t i = SLOT_FIRST; ((skillLoss || lootDrop == LOOT_DROP_FULL) && i < SLOT_LAST); ++i) { if(!(item = getInventoryItem((slots_t)i)) || (g_moveEvents->hasEquipEvent(item) && !isItemAbilityEnabled((slots_t)i))) continue; const ItemType& it = Item::items[item->getID()]; if(lootDrop == LOOT_DROP_FULL && it.abilities.preventDrop) { setDropLoot(LOOT_DROP_PREVENT); preventDrop = item; } if(skillLoss && !preventLoss && it.abilities.preventLoss) preventLoss = item; }}if(!Creature::onDeath()){ if(preventDrop) setDropLoot(LOOT_DROP_FULL); return false;}if(preventLoss){ setLossSkill(false); if(preventLoss->getCharges() > 1) //weird, but transform failed to remove for some hosters g_game.transformItem(preventLoss, preventLoss->getID(), std::max(0, ((int32_t)preventLoss->getCharges() - 1))); else g_game.internalRemoveItem(NULL, preventDrop);}if(preventDrop && preventDrop != preventLoss){ if(preventDrop->getCharges() > 1) //weird, but transform failed to remove for some hosters g_game.transformItem(preventDrop, preventDrop->getID(), std::max(0, ((int32_t)preventDrop->getCharges() - 1))); else g_game.internalRemoveItem(NULL, preventDrop);}removeConditions(CONDITIONEND_DEATH);if(skillLoss){ uint64_t lossExperience = getLostExperience(); removeExperience(lossExperience, false); double percent = 1. - ((double)(experience - lossExperience) / experience); //Magic level loss uint32_t sumMana = 0; uint64_t lostMana = 0; for(uint32_t i = 1; i <= magLevel; ++i) sumMana += vocation->getReqMana(i); sumMana += manaSpent; lostMana = (uint64_t)std::ceil(sumMana * ((double)(percent * lossPercent[LOSS_MANA]) / 100.)); while(lostMana > manaSpent && magLevel > 0) { lostMana -= manaSpent; manaSpent = vocation->getReqMana(magLevel); magLevel--; } manaSpent -= std::max((int32_t)0, (int32_t)lostMana); uint64_t nextReqMana = vocation->getReqMana(magLevel + 1); if(nextReqMana > vocation->getReqMana(magLevel)) magLevelPercent = Player::getPercentLevel(manaSpent, nextReqMana); else magLevelPercent = 0; //Skill loss uint32_t lostSkillTries, sumSkillTries; for(int16_t i = 0; i < 7; ++i) //for each skill { lostSkillTries = sumSkillTries = 0; for(uint32_t c = 11; c <= skills[i][sKILL_LEVEL]; ++c) //sum up all required tries for all skill levels sumSkillTries += vocation->getReqSkillTries(i, c); sumSkillTries += skills[i][sKILL_TRIES]; lostSkillTries = (uint32_t)std::ceil(sumSkillTries * ((double)(percent * lossPercent[LOSS_SKILLS]) / 100.)); while(lostSkillTries > skills[i][sKILL_TRIES]) { lostSkillTries -= skills[i][sKILL_TRIES]; skills[i][sKILL_TRIES] = vocation->getReqSkillTries(i, skills[i][sKILL_LEVEL]); if(skills[i][sKILL_LEVEL] < 11) { skills[i][sKILL_LEVEL] = 10; skills[i][sKILL_TRIES] = lostSkillTries = 0; break; } else skills[i][sKILL_LEVEL]--; } skills[i][sKILL_TRIES] = std::max((int32_t)0, (int32_t)(skills[i][sKILL_TRIES] - lostSkillTries)); } blessings = 0; loginPosition = masterPosition; if(!inventory[sLOT_BACKPACK]) __internalAddThing(SLOT_BACKPACK, Item::CreateItem(g_config.getNumber(ConfigManager::DEATH_CONTAINER))); sendIcons(); sendStats(); sendSkills(); sendReLoginWindow(); g_game.removeCreature(this, false);}else{ setLossSkill(true); if(preventLoss) { loginPosition = masterPosition; sendReLoginWindow(); g_game.removeCreature(this, false); }}return true;}void Player::dropCorpse(DeathList deathList){if(lootDrop == LOOT_DROP_NONE){ pzLocked = false; if(health <= 0) { health = healthMax; mana = manaMax; } setDropLoot(LOOT_DROP_FULL); sendStats(); sendIcons(); onIdleStatus(); g_game.addCreatureHealth(this); g_game.internalTeleport(this, masterPosition, true);}else{ Creature::dropCorpse(deathList); if(g_config.getBool(ConfigManager::DEATH_LIST)) IOLoginData::getInstance()->playerDeath(this, deathList);}}Item* Player::createCorpse(DeathList deathList){Item* corpse = Creature::createCorpse(deathList);if(!corpse) return NULL;std::stringstream ss;ss << "You recognize " << getNameDescription() << ". " << (sex % 2 ? "He" : "She") << " was killed by ";if(deathList[0].isCreatureKill()){ ss << deathList[0].getKillerCreature()->getNameDescription(); if(deathList[0].getKillerCreature()->getMaster()) ss << " summoned by " << deathList[0].getKillerCreature()->getMaster()->getNameDescription();}else ss << deathList[0].getKillerName();if(deathList.size() > 1){ if(deathList[0].getKillerType() != deathList[1].getKillerType()) { if(deathList[1].isCreatureKill()) { ss << " and by " << deathList[1].getKillerCreature()->getNameDescription(); if(deathList[1].getKillerCreature()->getMaster()) ss << " summoned by " << deathList[1].getKillerCreature()->getMaster()->getNameDescription(); } else ss << " and by " << deathList[1].getKillerName(); } else if(deathList[1].isCreatureKill()) { if(deathList[0].getKillerCreature()->getName() != deathList[1].getKillerCreature()->getName()) { ss << " and by " << deathList[1].getKillerCreature()->getNameDescription(); if(deathList[1].getKillerCreature()->getMaster()) ss << " summoned by " << deathList[1].getKillerCreature()->getMaster()->getNameDescription(); } } else if(asLowerCaseString(deathList[0].getKillerName()) != asLowerCaseString(deathList[1].getKillerName())) ss << " and by " << deathList[1].getKillerName();}ss << ".";corpse->setSpecialDescription(ss.str().c_str());return corpse;}void Player::addExhaust(uint32_t ticks, Exhaust_t type){if(Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_EXHAUST, ticks, 0, false, type)) addCondition(condition);}void Player::addInFightTicks(bool pzLock/* = false*/){if(hasFlag(PlayerFlag_NotGainInFight)) return;if(pzLock) pzLocked = true;if(Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_INFIGHT, g_config.getNumber(ConfigManager::PZ_LOCKED))) addCondition(condition);}void Player::addDefaultRegeneration(uint32_t addTicks){Condition* condition = getCondition(CONDITION_REGENERATION, CONDITIONID_DEFAULT);if(condition) condition->setTicks(condition->getTicks() + addTicks);else if((condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_REGENERATION, addTicks))){ condition->setParam(CONDITIONPARAM_HEALTHGAIN, vocation->getGainAmount(GAIN_HEALTH)); condition->setParam(CONDITIONPARAM_HEALTHTICKS, vocation->getGainTicks(GAIN_HEALTH) * 1000); condition->setParam(CONDITIONPARAM_MANAGAIN, vocation->getGainAmount(GAIN_MANA)); condition->setParam(CONDITIONPARAM_MANATICKS, vocation->getGainTicks(GAIN_MANA) * 1000); addCondition(condition);}}void Player::removeList(){autoList.erase(id);if(!isGhost()){ for(AutoList<Player>::iterator it = autoList.begin(); it != autoList.end(); ++it) it->second->notifyLogOut(this);}else{ for(AutoList<Player>::iterator it = autoList.begin(); it != autoList.end(); ++it) { if(it->second->canSeeCreature(this)) it->second->notifyLogOut(this); }}}void Player::addList(){if(!isGhost()){ for(AutoList<Player>::iterator it = autoList.begin(); it != autoList.end(); ++it) it->second->notifyLogIn(this);}else{ for(AutoList<Player>::iterator it = autoList.begin(); it != autoList.end(); ++it) { if(it->second->canSeeCreature(this)) it->second->notifyLogIn(this); }}autoList[id] = this;}void Player::kickPlayer(bool displayEffect, bool forceLogout){if(!client){ if(g_creatureEvents->playerLogout(this, forceLogout)) g_game.removeCreature(this);}else client->logout(displayEffect, forceLogout);}void Player::notifyLogIn(Player* loginPlayer){if(!client) return;VIPListSet::iterator it = VIPList.find(loginPlayer->getGUID());if(it != VIPList.end()) client->sendVIPLogIn(loginPlayer->getGUID());}void Player::notifyLogOut(Player* logoutPlayer){if(!client) return;VIPListSet::iterator it = VIPList.find(logoutPlayer->getGUID());if(it != VIPList.end()) client->sendVIPLogOut(logoutPlayer->getGUID());}bool Player::removeVIP(uint32_t _guid){VIPListSet::iterator it = VIPList.find(_guid);if(it == VIPList.end()) return false;VIPList.erase(it);return true;}bool Player::addVIP(uint32_t _guid, std::string& name, bool isOnline, bool internal/* = false*/){if(guid == _guid){ if(!internal) sendTextMessage(MSG_STATUS_SMALL, "You cannot add yourself."); return false;}if(VIPList.size() > (group ? group->getMaxVips(isPremium()) : 20)){ if(!internal) sendTextMessage(MSG_STATUS_SMALL, "You cannot add more buddies."); return false;}VIPListSet::iterator it = VIPList.find(_guid);if(it != VIPList.end()){ if(!internal) sendTextMessage(MSG_STATUS_SMALL, "This player is already in your list."); return false;}VIPList.insert(_guid);if(client && !internal) client->sendVIP(_guid, name, isOnline);return true;}//close container and its child containersvoid Player::autoCloseContainers(const Container* container){typedef std::vector<uint32_t> CloseList;CloseList closeList;for(ContainerVector::iterator it = containerVec.begin(); it != containerVec.end(); ++it){ Container* tmp = it->second; while(tmp != NULL) { if(tmp->isRemoved() || tmp == container) { closeList.push_back(it->first); break; } tmp = dynamic_cast<Container*>(tmp->getParent()); }}for(CloseList::iterator it = closeList.begin(); it != closeList.end(); ++it){ closeContainer(*it); if(client) client->sendCloseContainer(*it);}}bool Player::hasCapacity(const Item* item, uint32_t count) const{if(hasFlag(PlayerFlag_CannotPickupItem)) return false;if(hasFlag(PlayerFlag_HasInfiniteCapacity) || item->getTopParent() == this) return true;double itemWeight = 0;if(item->isStackable()) itemWeight = Item::items[item->getID()].weight * count;else itemWeight = item->getWeight();return (itemWeight < getFreeCapacity());}ReturnValue Player::__queryAdd(int32_t index, const Thing* thing, uint32_t count, uint32_t flags) const{const Item* item = thing->getItem();if(!item) return RET_NOTPOSSIBLE;bool childIsOwner = ((flags & FLAG_CHILDISOWNER) == FLAG_CHILDISOWNER), skipLimit = ((flags & FLAG_NOLIMIT) == FLAG_NOLIMIT);if(childIsOwner){ //a child container is querying the player, just check if enough capacity if(skipLimit || hasCapacity(item, count)) return RET_NOERROR; return RET_NOTENOUGHCAPACITY;}if(!item->isPickupable()) return RET_CANNOTPICKUP;ReturnValue ret = RET_NOERROR;if((item->getSlotPosition() & SLOTP_HEAD) || (item->getSlotPosition() & SLOTP_NECKLACE) || (item->getSlotPosition() & SLOTP_BACKPACK) || (item->getSlotPosition() & SLOTP_ARMOR) || (item->getSlotPosition() & SLOTP_LEGS) || (item->getSlotPosition() & SLOTP_FEET) || (item->getSlotPosition() & SLOTP_RING)) ret = RET_CANNOTBEDRESSED;else if(item->getSlotPosition() & SLOTP_TWO_HAND) ret = RET_PUTTHISOBJECTINBOTHHANDS;else if((item->getSlotPosition() & SLOTP_RIGHT) || (item->getSlotPosition() & SLOTP_LEFT)) ret = RET_PUTTHISOBJECTINYOURHAND;switch(index){ case SLOT_HEAD: if(item->getSlotPosition() & SLOTP_HEAD) ret = RET_NOERROR; break; case SLOT_NECKLACE: if(item->getSlotPosition() & SLOTP_NECKLACE) ret = RET_NOERROR; break; case SLOT_BACKPACK: if(item->getSlotPosition() & SLOTP_BACKPACK) ret = RET_NOERROR; break; case SLOT_ARMOR: if(item->getSlotPosition() & SLOTP_ARMOR) ret = RET_NOERROR; break; case SLOT_RIGHT: if(item->getSlotPosition() & SLOTP_RIGHT) { //check if we already carry an item in the other hand if(item->getSlotPosition() & SLOTP_TWO_HAND) { if(inventory[sLOT_LEFT] && inventory[sLOT_LEFT] != item) ret = RET_BOTHHANDSNEEDTOBEFREE; else ret = RET_NOERROR; } else if(inventory[sLOT_LEFT]) { const Item* leftItem = inventory[sLOT_LEFT]; WeaponType_t type = item->getWeaponType(), leftType = leftItem->getWeaponType(); if(leftItem->getSlotPosition() & SLOTP_TWO_HAND) ret = RET_DROPTWOHANDEDITEM; else if(item == leftItem && count == item->getItemCount()) ret = RET_NOERROR; else if(leftType == WEAPON_SHIELD && type == WEAPON_SHIELD) ret = RET_CANONLYUSEONESHIELD; else if(!leftItem->isWeapon() || !item->isWeapon() || leftType == WEAPON_SHIELD || leftType == WEAPON_AMMO || type == WEAPON_SHIELD || type == WEAPON_AMMO) ret = RET_NOERROR; else ret = RET_CANONLYUSEONEWEAPON; } else ret = RET_NOERROR; } break; case SLOT_LEFT: if(item->getSlotPosition() & SLOTP_LEFT) { //check if we already carry an item in the other hand if(item->getSlotPosition() & SLOTP_TWO_HAND) { if(inventory[sLOT_RIGHT] && inventory[sLOT_RIGHT] != item) ret = RET_BOTHHANDSNEEDTOBEFREE; else ret = RET_NOERROR; } else if(inventory[sLOT_RIGHT]) { const Item* rightItem = inventory[sLOT_RIGHT]; WeaponType_t type = item->getWeaponType(), rightType = rightItem->getWeaponType(); if(rightItem->getSlotPosition() & SLOTP_TWO_HAND) ret = RET_DROPTWOHANDEDITEM; else if(item == rightItem && count == item->getItemCount()) ret = RET_NOERROR; else if(rightType == WEAPON_SHIELD && type == WEAPON_SHIELD) ret = RET_CANONLYUSEONESHIELD; else if(!rightItem->isWeapon() || !item->isWeapon() || rightType == WEAPON_SHIELD || rightType == WEAPON_AMMO || type == WEAPON_SHIELD || type == WEAPON_AMMO) ret = RET_NOERROR; else ret = RET_CANONLYUSEONEWEAPON; } else ret = RET_NOERROR; } break; case SLOT_LEGS: if(item->getSlotPosition() & SLOTP_LEGS) ret = RET_NOERROR; break; case SLOT_FEET: if(item->getSlotPosition() & SLOTP_FEET) ret = RET_NOERROR; break; case SLOT_RING: if(item->getSlotPosition() & SLOTP_RING) ret = RET_NOERROR; break; case SLOT_AMMO: if(item->getSlotPosition() & SLOTP_AMMO) ret = RET_NOERROR; break; case SLOT_WHEREEVER: case -1: ret = RET_NOTENOUGHROOM; break; default: ret = RET_NOTPOSSIBLE; break;}if(ret == RET_NOERROR || ret == RET_NOTENOUGHROOM){ //need an exchange with source? if(getInventoryItem((slots_t)index) != NULL && (!getInventoryItem((slots_t)index)->isStackable() || getInventoryItem((slots_t)index)->getID() != item->getID())) return RET_NEEDEXCHANGE; if(!g_moveEvents->onPlayerEquip(const_cast<Player*>(this), const_cast<Item*>(item), (slots_t)index, true)) return RET_CANNOTBEDRESSED; //check if enough capacity if(!hasCapacity(item, count)) return RET_NOTENOUGHCAPACITY;}return ret;}ReturnValue Player::__queryMaxCount(int32_t index, const Thing* thing, uint32_t count, uint32_t& maxQueryCount,uint32_t flags) const{const Item* item = thing->getItem();if(!item){ maxQueryCount = 0; return RET_NOTPOSSIBLE;}const Thing* destThing = __getThing(index);const Item* destItem = NULL;if(destThing) destItem = destThing->getItem();if(destItem){ if(destItem->isStackable() && item->getID() == destItem->getID()) maxQueryCount = 100 - destItem->getItemCount(); else maxQueryCount = 0;}else{ if(item->isStackable()) maxQueryCount = 100; else maxQueryCount = 1; return RET_NOERROR;}if(maxQueryCount < count) return RET_NOTENOUGHROOM;return RET_NOERROR;}ReturnValue Player::__queryRemove(const Thing* thing, uint32_t count, uint32_t flags) const{int32_t index = __getIndexOfThing(thing);if(index == -1) return RET_NOTPOSSIBLE;const Item* item = thing->getItem();if(!item) return RET_NOTPOSSIBLE;if(count == 0 || (item->isStackable() && count > item->getItemCount())) return RET_NOTPOSSIBLE; if(item->isNotMoveable() && !hasBitSet(FLAG_IGNORENOTMOVEABLE, flags)) return RET_NOTMOVEABLE;return RET_NOERROR;}Cylinder* Player::__queryDestination(int32_t& index, const Thing* thing, Item** destItem,uint32_t& flags){if(index == 0 /*drop to capacity window*/ || index == INDEX_WHEREEVER){ *destItem = NULL; const Item* item = thing->getItem(); if(!item) return this; //find a appropiate slot for(int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i) { if(!inventory[i] && __queryAdd(i, item, item->getItemCount(), 0) == RET_NOERROR) { index = i; return this; } } //try containers std::list<std::pair<Container*, int32_t> > deepList; for(int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i) { if(inventory[i] == tradeItem) continue; if(Container* container = dynamic_cast<Container*>(inventory[i])) { if(container->__queryAdd(-1, item, item->getItemCount(), 0) == RET_NOERROR) { index = INDEX_WHEREEVER; *destItem = NULL; return container; } deepList.push_back(std::make_pair(container, 0)); } } //check deeper in the containers int32_t deepness = g_config.getNumber(ConfigManager::PLAYER_DEEPNESS); for(std::list<std::pair<Container*, int32_t> >::iterator dit = deepList.begin(); dit != deepList.end(); ++dit) { Container* c = (*dit).first; if(!c || c->empty()) continue; int32_t level = (*dit).second; for(ItemList::const_iterator it = c->getItems(); it != c->getEnd(); ++it) { if((*it) == tradeItem) continue; if(Container* subContainer = dynamic_cast<Container*>(*it)) { if(subContainer->__queryAdd(-1, item, item->getItemCount(), 0) == RET_NOERROR) { index = INDEX_WHEREEVER; *destItem = NULL; return subContainer; } if(deepness < 0 || level < deepness) deepList.push_back(std::make_pair(subContainer, (level + 1))); } } } return this;}Thing* destThing = __getThing(index);if(destThing) *destItem = destThing->getItem();if(Cylinder* subCylinder = dynamic_cast<Cylinder*>(destThing)){ index = INDEX_WHEREEVER; *destItem = NULL; return subCylinder;}return this;}void Player::__addThing(Creature* actor, Thing* thing){__addThing(actor, 0, thing);}void Player::__addThing(Creature* actor, int32_t index, Thing* thing){if(index < 0 || index > 11){#ifdef __DEBUG_MOVESYS__ std::cout << "Failure: [Player::__addThing], " << "player: " << getName() << ", index: " << index << ", index < 0 || index > 11" << std::endl; DEBUG_REPORT#endif return /*RET_NOTPOSSIBLE*/;}if(index == 0){#ifdef __DEBUG_MOVESYS__ std::cout << "Failure: [Player::__addThing], " << "player: " << getName() << ", index == 0" << std::endl; DEBUG_REPORT#endif return /*RET_NOTENOUGHROOM*/;}Item* item = thing->getItem();if(!item){#ifdef __DEBUG_MOVESYS__ std::cout << "Failure: [Player::__addThing], " << "player: " << getName() << ", item == NULL" << std::endl; DEBUG_REPORT#endif return /*RET_NOTPOSSIBLE*/;}item->setParent(this);inventory[index] = item;//send to clientsendAddInventoryItem((slots_t)index, item);//event methodsonAddInventoryItem((slots_t)index, item);}void Player::__updateThing(Thing* thing, uint16_t itemId, uint32_t count){int32_t index = __getIndexOfThing(thing);if(index == -1){#ifdef __DEBUG_MOVESYS__ std::cout << "Failure: [Player::__updateThing], " << "player: " << getName() << ", index == -1" << std::endl; DEBUG_REPORT#endif return /*RET_NOTPOSSIBLE*/;}Item* item = thing->getItem();if(item == NULL){#ifdef __DEBUG_MOVESYS__ std::cout << "Failure: [Player::__updateThing], " << "player: " << getName() << ", item == NULL" << std::endl; DEBUG_REPORT#endif return /*RET_NOTPOSSIBLE*/;}const ItemType& oldType = Item::items[item->getID()];const ItemType& newType = Item::items[itemId];item->setID(itemId);item->setSubType(count);//send to clientsendUpdateInventoryItem((slots_t)index, item, item);//event methodsonUpdateInventoryItem((slots_t)index, item, oldType, item, newType);}void Player::__replaceThing(uint32_t index, Thing* thing){if(index < 0 || index > 11){#ifdef __DEBUG_MOVESYS__ std::cout << "Failure: [Player::__replaceThing], " << "player: " << getName() << ", index: " << index << ", index < 0 || index > 11" << std::endl; DEBUG_REPORT#endif return /*RET_NOTPOSSIBLE*/;}Item* oldItem = getInventoryItem((slots_t)index);if(!oldItem){#ifdef __DEBUG_MOVESYS__ std::cout << "Failure: [Player::__updateThing], " << "player: " << getName() << ", oldItem == NULL" << std::endl; DEBUG_REPORT#endif return /*RET_NOTPOSSIBLE*/;}Item* item = thing->getItem();if(!item){#ifdef __DEBUG_MOVESYS__ std::cout << "Failure: [Player::__updateThing], " << "player: " << getName() << ", item == NULL" << std::endl; DEBUG_REPORT#endif return /*RET_NOTPOSSIBLE*/;}const ItemType& oldType = Item::items[oldItem->getID()];const ItemType& newType = Item::items[item->getID()];//send to clientsendUpdateInventoryItem((slots_t)index, oldItem, item);//event methodsonUpdateInventoryItem((slots_t)index, oldItem, oldType, item, newType);item->setParent(this);inventory[index] = item;}void Player::__removeThing(Thing* thing, uint32_t count){Item* item = thing->getItem();if(!item){#ifdef __DEBUG_MOVESYS__ std::cout << "Failure: [Player::__removeThing], " << "player: " << getName() << ", item == NULL" << std::endl; DEBUG_REPORT#endif return /*RET_NOTPOSSIBLE*/;}int32_t index = __getIndexOfThing(thing);if(index == -1){#ifdef __DEBUG_MOVESYS__ std::cout << "Failure: [Player::__removeThing], " << "player: " << getName() << ", index == -1" << std::endl; DEBUG_REPORT#endif return /*RET_NOTPOSSIBLE*/;}if(item->isStackable()){ if(count == item->getItemCount()) { //send change to client sendRemoveInventoryItem((slots_t)index, item); //event methods onRemoveInventoryItem((slots_t)index, item); item->setParent(NULL); inventory[index] = NULL; } else { item->setItemCount(std::max(0, (int32_t)(item->getItemCount() - count))); const ItemType& it = Item::items[item->getID()]; //send change to client sendUpdateInventoryItem((slots_t)index, item, item); //event methods onUpdateInventoryItem((slots_t)index, item, it, item, it); }}else{ //send change to client sendRemoveInventoryItem((slots_t)index, item); //event methods onRemoveInventoryItem((slots_t)index, item); item->setParent(NULL); inventory[index] = NULL;}}Thing* Player::__getThing(uint32_t index) const{if(index > SLOT_PRE_FIRST && index < SLOT_LAST) return inventory[index];return NULL;}int32_t Player::__getIndexOfThing(const Thing* thing) const{for(int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i){ if(inventory[i] == thing) return i;}return -1;}int32_t Player::__getFirstIndex() const{return SLOT_FIRST;}int32_t Player::__getLastIndex() const{return SLOT_LAST;}uint32_t Player::__getItemTypeCount(uint16_t itemId, int32_t subType /*= -1*/, bool itemCount /*= true*/) const{Item* item = NULL;Container* container = NULL;uint32_t count = 0;for(int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i){ if(!(item = inventory[i])) continue; if(item->getID() == itemId) count += Item::countByType(item, subType, itemCount); if(!(container = item->getContainer())) continue; for(ContainerIterator it = container->begin(), end = container->end(); it != end; ++it) { if((*it)->getID() == itemId) count += Item::countByType(*it, subType, itemCount); }}return count;}std::map<uint32_t, uint32_t>& Player::__getAllItemTypeCount(std::map<uint32_t,uint32_t>& countMap, bool itemCount/* = true*/) const{Item* item = NULL;Container* container = NULL;for(int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i){ if(!(item = inventory[i])) continue; countMap[item->getID()] += Item::countByType(item, -1, itemCount); if(!(container = item->getContainer())) continue; for(ContainerIterator it = container->begin(), end = container->end(); it != end; ++it) countMap[(*it)->getID()] += Item::countByType(*it, -1, itemCount);}return countMap;}void Player::postAddNotification(Creature* actor, Thing* thing, const Cylinder* oldParent,int32_t index, cylinderlink_t link /*= LINK_OWNER*/){if(link == LINK_OWNER) //calling movement scripts g_moveEvents->onPlayerEquip(this, thing->getItem(), (slots_t)index, false);bool requireListUpdate = true;if(link == LINK_OWNER || link == LINK_TOPPARENT){ if(const Item* item = (oldParent ? oldParent->getItem() : NULL)) { assert(item->getContainer() != NULL); requireListUpdate = item->getContainer()->getHoldingPlayer() != this; } else requireListUpdate = oldParent != this; updateInventoryWeight(); updateItemsLight(); sendStats();}if(const Item* item = thing->getItem()){ if(const Container* container = item->getContainer()) onSendContainer(container); if(shopOwner && requireListUpdate) updateInventoryGoods(item->getID());}else if(const Creature* creature = thing->getCreature()){ if(creature != this) return; typedef std::vector<Container*> Containers; Containers containers; for(ContainerVector::iterator it = containerVec.begin(); it != containerVec.end(); ++it) { if(!Position::areInRange<1,1,0>(it->second->getPosition(), getPosition())) containers.push_back(it->second); } for(Containers::const_iterator it = containers.begin(); it != containers.end(); ++it) autoCloseContainers(*it);}}void Player::postRemoveNotification(Creature* actor, Thing* thing, const Cylinder* newParent,int32_t index, bool isCompleteRemoval, cylinderlink_t link /*= LINK_OWNER*/){if(link == LINK_OWNER) //calling movement scripts g_moveEvents->onPlayerDeEquip(this, thing->getItem(), (slots_t)index, isCompleteRemoval);bool requireListUpdate = true;if(link == LINK_OWNER || link == LINK_TOPPARENT){ if(const Item* item = (newParent ? newParent->getItem() : NULL)) { assert(item->getContainer() != NULL); requireListUpdate = item->getContainer()->getHoldingPlayer() != this; } else requireListUpdate = newParent != this; updateInventoryWeight(); updateItemsLight(); sendStats();}if(const Item* item = thing->getItem()){ if(const Container* container = item->getContainer()) { if(container->isRemoved() || !Position::areInRange<1,1,0>(getPosition(), container->getPosition())) autoCloseContainers(container); else if(container->getTopParent() == this) onSendContainer(container); else if(const Container* topContainer = dynamic_cast<const Container*>(container->getTopParent())) { if(const Depot* depot = dynamic_cast<const Depot*>(topContainer)) { bool isOwner = false; for(DepotMap::iterator it = depots.begin(); it != depots.end(); ++it) { if(it->second.first != depot) continue; isOwner = true; onSendContainer(container); } if(!isOwner) autoCloseContainers(container); } else onSendContainer(container); } else autoCloseContainers(container); } if(shopOwner && requireListUpdate) updateInventoryGoods(item->getID());}}void Player::__internalAddThing(Thing* thing){__internalAddThing(0, thing);}void Player::__internalAddThing(uint32_t index, Thing* thing){#ifdef __DEBUG_MOVESYS__std::cout << "[Player::__internalAddThing] index: " << index << std::endl;#endifItem* item = thing->getItem();if(!item){#ifdef __DEBUG_MOVESYS__ std::cout << "Failure: [Player::__internalAddThing] item == NULL" << std::endl;#endif return;}//index == 0 means we should equip this item at the most appropiate slotif(index == 0){#ifdef __DEBUG_MOVESYS__ std::cout << "Failure: [Player::__internalAddThing] index == 0" << std::endl; DEBUG_REPORT#endif return;}if(index > 0 && index < 11){ if(inventory[index]) {#ifdef __DEBUG_MOVESYS__ std::cout << "Warning: [Player::__internalAddThing], player: " << getName() << ", items[index] is not empty." << std::endl; //DEBUG_REPORT#endif return; } inventory[index] = item; item->setParent(this);}}bool Player::setFollowCreature(Creature* creature, bool fullPathSearch /*= false*/){bool deny = false;CreatureEventList followEvents = getCreatureEvents(CREATURE_EVENT_FOLLOW);for(CreatureEventList::iterator it = followEvents.begin(); it != followEvents.end(); ++it){ if(creature && !(*it)->executeFollow(this, creature)) deny = true;}if(deny || !Creature::setFollowCreature(creature, fullPathSearch)){ setFollowCreature(NULL); setAttackedCreature(NULL); if(!deny) sendCancelMessage(RET_THEREISNOWAY); sendCancelTarget(); stopEventWalk(); return false;}return true;}bool Player::setAttackedCreature(Creature* creature){if(!Creature::setAttackedCreature(creature)){ sendCancelTarget(); return false;}if(chaseMode == CHASEMODE_FOLLOW && creature){ if(followCreature != creature) //chase opponent setFollowCreature(creature);}else setFollowCreature(NULL);if(creature) Dispatcher::getInstance().addTask(createTask(boost::bind(&Game::checkCreatureAttack, &g_game, getID())));return true;}void Player::getPathSearchParams(const Creature* creature, FindPathParams& fpp) const{Creature::getPathSearchParams(creature, fpp);fpp.fullPathSearch = true;}void Player::doAttacking(uint32_t interval){if(!lastAttack) lastAttack = OTSYS_TIME() - getAttackSpeed() - 1;else if((OTSYS_TIME() - lastAttack) < getAttackSpeed()) return;if(hasCondition(CONDITION_PACIFIED) && !hasCustomFlag(PlayerCustomFlag_IgnorePacification)){ lastAttack = OTSYS_TIME(); return;}Item* tool = getWeapon();if(const Weapon* weapon = g_weapons->getWeapon(tool)){ if(weapon->interruptSwing() && !canDoAction()) { SchedulerTask* task = createSchedulerTask(getNextActionTime(), boost::bind(&Game::checkCreatureAttack, &g_game, getID())); setNextActionTask(task); } else if((!weapon->hasExhaustion() || !hasCondition(CONDITION_EXHAUST, EXHAUST_COMBAT)) && weapon->useWeapon(this, tool, attackedCreature)) lastAttack = OTSYS_TIME();}else if(Weapon::useFist(this, attackedCreature)) lastAttack = OTSYS_TIME();}double Player::getGainedExperience(Creature* attacker) const{if(!skillLoss) return 0;double rate = g_config.getDouble(ConfigManager::RATE_PVP_EXPERIENCE);if(rate <= 0) return 0;Player* attackerPlayer = attacker->getPlayer();if(!attackerPlayer || attackerPlayer == this) return 0;double attackerLevel = (double)attackerPlayer->getLevel(), min = g_config.getDouble( ConfigManager::EFP_MIN_THRESHOLD), max = g_config.getDouble(ConfigManager::EFP_MAX_THRESHOLD);if((min > 0 && level < (uint32_t)std::floor(attackerLevel * min)) || (max > 0 && level > (uint32_t)std::floor(attackerLevel * max))) return 0;/* Formula a = attackers level * 0.9 b = victims level c = victims experience result = (1 - (a / b)) * 0.05 * c Not affected by special multipliers(!)*/uint32_t a = (uint32_t)std::floor(attackerLevel * 0.9), b = level;uint64_t c = getExperience();return (double)std::max((uint64_t)0, (uint64_t)std::floor(getDamageRatio(attacker) * std::max((double)0, ((double)(1 - (((double)a / b))))) * 0.05 * c)) * rate;}void Player::onFollowCreature(const Creature* creature){if(!creature) stopEventWalk();}void Player::setChaseMode(chaseMode_t mode){chaseMode_t prevChaseMode = chaseMode;chaseMode = mode;if(prevChaseMode == chaseMode) return;if(chaseMode == CHASEMODE_FOLLOW){ if(!followCreature && attackedCreature) //chase opponent setFollowCreature(attackedCreature);}else if(attackedCreature){ setFollowCreature(NULL); stopEventWalk();}}void Player::onWalkAborted(){setNextWalkActionTask(NULL);sendCancelWalk();}void Player::onWalkComplete(){if(!walkTask) return;walkTaskEvent = Scheduler::getInstance().addEvent(walkTask);walkTask = NULL;}void Player::stopWalk(){if(listWalkDir.empty()) return;stopEventWalk();}void Player::getCreatureLight(LightInfo& light) const{if(internalLight.level > itemsLight.level) light = internalLight;else light = itemsLight;}void Player::updateItemsLight(bool internal /*=false*/){LightInfo maxLight;LightInfo curLight;for(int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i){ if(Item* item = getInventoryItem((slots_t)i)) { item->getLight(curLight); if(curLight.level > maxLight.level) maxLight = curLight; }}if(itemsLight.level != maxLight.level || itemsLight.color != maxLight.color){ itemsLight = maxLight; if(!internal) g_game.changeLight(this);}}void Player::onAddCondition(ConditionType_t type, bool hadCondition){Creature::onAddCondition(type, hadCondition);if(getLastPosition().x && type != CONDITION_GAMEMASTER) // don't send if player have just logged in (its already done in protocolgame), or condition have no icons sendIcons();}void Player::onAddCombatCondition(ConditionType_t type, bool hadCondition){std::string tmp;switch(type){ //client hardcoded case CONDITION_FIRE: tmp = "burning"; break; case CONDITION_BUG: tmp = "dashing"; break; case CONDITION_FLY: tmp = "dashing"; break; case CONDITION_DRAGON: tmp = "dashing"; break; case CONDITION_VENOM: tmp = "dashing"; break; case CONDITION_TEST: tmp = "dashing"; break; case CONDITION_FIGHT: tmp = "dashing"; break; case CONDITION_ROCK: tmp = "dashing"; break; case CONDITION_ELECTRIC: tmp = "dashing"; break; case CONDITION_POISON: tmp = "poisoned"; break; case CONDITION_ENERGY: tmp = "electrified"; break; case CONDITION_FREEZING: tmp = "freezing"; break; case CONDITION_DAZZLED: tmp = "dazzled"; break; case CONDITION_CURSED: tmp = "cursed"; break; case CONDITION_DROWN: tmp = "drowning"; break; case CONDITION_DRUNK: tmp = "drunk"; break; case CONDITION_MANASHIELD: tmp = "protected by a magic shield"; break; case CONDITION_PARALYZE: tmp = "paralyzed"; break; case CONDITION_HASTE: tmp = "hasted"; break; case CONDITION_ATTRIBUTES: tmp = "strengthened"; break; default: break;}if(!tmp.empty()) sendTextMessage(MSG_STATUS_DEFAULT, "You are " + tmp + ".");}void Player::onEndCondition(ConditionType_t type){Creature::onEndCondition(type);if(type == CONDITION_INFIGHT){ onIdleStatus(); clearAttacked(); pzLocked = false; if(skull < SKULL_RED) setSkull(SKULL_NONE); g_game.updateCreatureSkull(this);}sendIcons();}void Player::onCombatRemoveCondition(const Creature* attacker, Condition* condition){//Creature::onCombatRemoveCondition(attacker, condition);bool remove = true;if(condition->getId() > 0){ remove = false; //Means the condition is from an item, id == slot if(g_game.getWorldType() == WORLD_TYPE_PVP_ENFORCED) { if(Item* item = getInventoryItem((slots_t)condition->getId())) { //25% chance to destroy the item if(25 >= random_range(0, 100)) g_game.internalRemoveItem(NULL, item); } }}if(remove){ if(!canDoAction()) { uint32_t delay = getNextActionTime(); delay -= (delay % EVENT_CREATURE_THINK_INTERVAL); if(delay < 0) removeCondition(condition); else condition->setTicks(delay); } else removeCondition(condition);}}void Player::onTickCondition(ConditionType_t type, int32_t interval, bool& _remove){Creature::onTickCondition(type, interval, _remove);if(type == CONDITION_HUNTING) useStamina(-(interval * g_config.getNumber(ConfigManager::RATE_STAMINA_LOSS)));}void Player::onAttackedCreature(Creature* target){Creature::onAttackedCreature(target);if(hasFlag(PlayerFlag_NotGainInFight)) return;addInFightTicks();Player* targetPlayer = target->getPlayer();if(!targetPlayer) return;addAttacked(targetPlayer);if(targetPlayer == this && targetPlayer->getZone() != ZONE_PVP){ targetPlayer->sendCreatureSkull(this); return;}if(Combat::isInPvpZone(this, targetPlayer) || isPartner(targetPlayer) || (g_config.getBool( ConfigManager::ALLOW_FIGHTBACK) && targetPlayer->hasAttacked(this))) return;if(!pzLocked){ pzLocked = true; sendIcons();}if(getZone() != target->getZone()) return;if(skull == SKULL_NONE){ if(targetPlayer->getSkull() != SKULL_NONE) targetPlayer->sendCreatureSkull(this); else if(!hasCustomFlag(PlayerCustomFlag_NotGainSkull)) { setSkull(SKULL_WHITE); g_game.updateCreatureSkull(this); }}}void Player::onSummonAttackedCreature(Creature* summon, Creature* target){Creature::onSummonAttackedCreature(summon, target);onAttackedCreature(target);}void Player::onAttacked(){Creature::onAttacked();addInFightTicks();}bool Player::checkLoginDelay(uint32_t playerId) const{return (!hasCustomFlag(PlayerCustomFlag_IgnoreLoginDelay) && OTSYS_TIME() <= (lastLoad + g_config.getNumber( ConfigManager::LOGIN_PROTECTION)) && !hasBeenAttacked(playerId));}void Player::onIdleStatus(){Creature::onIdleStatus();if(getParty()) getParty()->clearPlayerPoints(this);}void Player::onPlacedCreature(){//scripting event - onLoginif(!g_creatureEvents->playerLogin(this)) kickPlayer(true, true);}void Player::onAttackedCreatureDrain(Creature* target, int32_t points){Creature::onAttackedCreatureDrain(target, points);if(party && target && (!target->getMaster() || !target->getMaster()->getPlayer()) && target->getMonster() && target->getMonster()->isHostile()) //we have fulfilled a requirement for shared experience getParty()->addPlayerDamageMonster(this, points);char buffer[100];sprintf(buffer, "Your pokemon dealt %d damage to %s.", points, target->getNameDescription().c_str());sendTextMessage(MSG_STATUS_DEFAULT, buffer);}void Player::onSummonAttackedCreatureDrain(Creature* summon, Creature* target, int32_t points){Creature::onSummonAttackedCreatureDrain(summon, target, points);char buffer[100];sprintf(buffer, "Your %s deals %d damage to %s.", summon->getName().c_str(), points, target->getNameDescription().c_str());sendTextMessage(MSG_EVENT_DEFAULT, buffer);}void Player::onTargetCreatureGainHealth(Creature* target, int32_t points){Creature::onTargetCreatureGainHealth(target, points);if(target && getParty()){ Player* tmpPlayer = NULL; if(target->getPlayer()) tmpPlayer = target->getPlayer(); else if(target->getMaster() && target->getMaster()->getPlayer()) tmpPlayer = target->getMaster()->getPlayer(); if(isPartner(tmpPlayer)) getParty()->addPlayerHealedMember(this, points);}}bool Player::onKilledCreature(Creature* target, uint32_t& flags){if(!Creature::onKilledCreature(target, flags)) return false;if(hasFlag(PlayerFlag_NotGenerateLoot)) target->setDropLoot(LOOT_DROP_NONE);Condition* condition = NULL;if(target->getMonster() && !target->isPlayerSummon() && !hasFlag(PlayerFlag_HasInfiniteStamina) && (condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_HUNTING, g_config.getNumber(ConfigManager::HUNTING_DURATION)))) addCondition(condition);if(hasFlag(PlayerFlag_NotGainInFight) || !hasBitSet((uint32_t)KILLFLAG_JUSTIFY, flags) || getZone() != target->getZone()) return true;Player* targetPlayer = target->getPlayer();if(!targetPlayer || Combat::isInPvpZone(this, targetPlayer) || !hasCondition(CONDITION_INFIGHT) || isPartner(targetPlayer)) return true;if(!targetPlayer->hasAttacked(this) && target->getSkull() == SKULL_NONE && targetPlayer != this && ((g_config.getBool(ConfigManager::USE_FRAG_HANDLER) && addUnjustifiedKill( targetPlayer)) || hasBitSet((uint32_t)KILLFLAG_LASTHIT, flags))) flags |= (uint32_t)KILLFLAG_UNJUSTIFIED;pzLocked = true;if((condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_INFIGHT, g_config.getNumber(ConfigManager::WHITE_SKULL_TIME)))) addCondition(condition);return true;}bool Player::gainExperience(double& gainExp, bool fromMonster){if(!rateExperience(gainExp, fromMonster)) return false;//soul regenerationif(gainExp >= level){ if(Condition* condition = Condition::createCondition( CONDITIONID_DEFAULT, CONDITION_SOUL, 4 * 60 * 1000)) { condition->setParam(CONDITIONPARAM_SOULGAIN, vocation->getGainAmount(GAIN_SOUL)); condition->setParam(CONDITIONPARAM_SOULTICKS, (vocation->getGainTicks(GAIN_SOUL) * 1000)); addCondition(condition); }}addExperience((uint64_t)gainExp);return true;}bool Player::rateExperience(double& gainExp, bool fromMonster){if(hasFlag(PlayerFlag_NotGainExperience) || gainExp <= 0) return false;if(!fromMonster) return true;gainExp *= rates[sKILL__LEVEL] * g_game.getExperienceStage(level, vocation->getExperienceMultiplier());if(!hasFlag(PlayerFlag_HasInfiniteStamina)){ int32_t minutes = getStaminaMinutes(); if(minutes >= g_config.getNumber(ConfigManager::STAMINA_LIMIT_TOP)) { if(isPremium() || !g_config.getNumber(ConfigManager::STAMINA_BONUS_PREMIUM)) gainExp *= g_config.getDouble(ConfigManager::RATE_STAMINA_ABOVE); } else if(minutes < (g_config.getNumber(ConfigManager::STAMINA_LIMIT_BOTTOM)) && minutes > 0) gainExp *= g_config.getDouble(ConfigManager::RATE_STAMINA_UNDER); else if(minutes <= 0) gainExp = 0;}else if(isPremium() || !g_config.getNumber(ConfigManager::STAMINA_BONUS_PREMIUM)) gainExp *= g_config.getDouble(ConfigManager::RATE_STAMINA_ABOVE);return true;}void Player::onGainExperience(double& gainExp, bool fromMonster, bool multiplied){if(party && party->isSharedExperienceEnabled() && party->isSharedExperienceActive()){ party->shareExperience(gainExp, fromMonster, multiplied); rateExperience(gainExp, fromMonster); return; //we will get a share of the experience through the sharing mechanism}if(gainExperience(gainExp, fromMonster)) Creature::onGainExperience(gainExp, fromMonster, true);}void Player::onGainSharedExperience(double& gainExp, bool fromMonster, bool multiplied){if(gainExperience(gainExp, fromMonster)) Creature::onGainSharedExperience(gainExp, fromMonster, true);}bool Player::isImmune(CombatType_t type) const{return hasCustomFlag(PlayerCustomFlag_IsImmune) || Creature::isImmune(type);}bool Player::isImmune(ConditionType_t type) const{return hasCustomFlag(PlayerCustomFlag_IsImmune) || Creature::isImmune(type);}bool Player::isAttackable() const{return (!hasFlag(PlayerFlag_CannotBeAttacked) && !isAccountManager());}void Player::changeHealth(int32_t healthChange){Creature::changeHealth(healthChange);sendStats();}void Player::changeMana(int32_t manaChange){if(!hasFlag(PlayerFlag_HasInfiniteMana)) Creature::changeMana(manaChange);sendStats();}void Player::changeSoul(int32_t soulChange){if(!hasFlag(PlayerFlag_HasInfiniteSoul)) soul = std::min((int32_t)soulMax, (int32_t)soul + soulChange);sendStats();}bool Player::canLogout(bool checkInfight){if(checkInfight && hasCondition(CONDITION_INFIGHT)) return false;return !isConnecting && !pzLocked && !getTile()->hasFlag(TILESTATE_NOLOGOUT);}bool Player::changeOutfit(Outfit_t outfit, bool checkList){uint32_t outfitId = Outfits::getInstance()->getOutfitId(outfit.lookType);if(checkList && (!canWearOutfit(outfitId, outfit.lookAddons) || !requestedOutfit)) return false;requestedOutfit = false;if(outfitAttributes){ uint32_t oldId = Outfits::getInstance()->getOutfitId(defaultOutfit.lookType); outfitAttributes = !Outfits::getInstance()->removeAttributes(getID(), oldId, sex);}defaultOutfit = outfit;outfitAttributes = Outfits::getInstance()->addAttributes(getID(), outfitId, sex, defaultOutfit.lookAddons);return true;}bool Player::canWearOutfit(uint32_t outfitId, uint32_t addons){OutfitMap::iterator it = outfits.find(outfitId);if(it == outfits.end() || (it->second.isPremium && !isPremium()) || getAccess() < it->second.accessLevel || ((it->second.addons & addons) != addons && !hasCustomFlag(PlayerCustomFlag_CanWearAllAddons))) return false;if(!it->second.storageId) return true;std::string value;return getStorage(it->second.storageId, value) && value == it->second.storageValue;}bool Player::addOutfit(uint32_t outfitId, uint32_t addons){Outfit outfit;if(!Outfits::getInstance()->getOutfit(outfitId, sex, outfit)) return false;OutfitMap::iterator it = outfits.find(outfitId);if(it != outfits.end()) outfit.addons |= it->second.addons;outfit.addons |= addons;outfits[outfitId] = outfit;return true;}bool Player::removeOutfit(uint32_t outfitId, uint32_t addons){OutfitMap::iterator it = outfits.find(outfitId);if(it == outfits.end()) return false;if(addons == 0xFF) //remove outfit outfits.erase(it);else //remove addons outfits[outfitId].addons = it->second.addons & (~addons);return true;}void Player::generateReservedStorage(){uint32_t baseKey = PSTRG_OUTFITSID_RANGE_START + 1;const OutfitMap& defaultOutfits = Outfits::getInstance()->getOutfits(sex);for(OutfitMap::const_iterator it = outfits.begin(); it != outfits.end(); ++it){ OutfitMap::const_iterator dit = defaultOutfits.find(it->first); if(dit == defaultOutfits.end() || (dit->second.isDefault && (dit->second.addons & it->second.addons) == it->second.addons)) continue; std::stringstream ss; ss << ((it->first << 16) | (it->second.addons & 0xFF)); storageMap[baseKey] = ss.str(); baseKey++; if(baseKey <= PSTRG_OUTFITSID_RANGE_START + PSTRG_OUTFITSID_RANGE_SIZE) continue; std::cout << "[Warning - Player::genReservedStorageRange] Player " << getName() << " with more than 500 outfits!" << std::endl; break;}}void Player::setSex(uint16_t newSex){sex = newSex;const OutfitMap& defaultOutfits = Outfits::getInstance()->getOutfits(sex);for(OutfitMap::const_iterator it = defaultOutfits.begin(); it != defaultOutfits.end(); ++it){ if(it->second.isDefault) addOutfit(it->first, it->second.addons);}}Skulls_t Player::getSkull() const{if(hasFlag(PlayerFlag_NotGainInFight) || hasCustomFlag(PlayerCustomFlag_NotGainSkull)) return SKULL_NONE;return skull;}Skulls_t Player::getSkullClient(const Creature* creature) const{if(const Player* player = creature->getPlayer()){ if(g_game.getWorldType() != WORLD_TYPE_PVP) return SKULL_NONE; if((player == this || (skull != SKULL_NONE && player->getSkull() < SKULL_RED)) && player->hasAttacked(this)) return SKULL_YELLOW; if(player->getSkull() == SKULL_NONE && isPartner(player) && g_game.getWorldType() != WORLD_TYPE_NO_PVP) return SKULL_GREEN;}return Creature::getSkullClient(creature);}bool Player::hasAttacked(const Player* attacked) const{return !hasFlag(PlayerFlag_NotGainInFight) && attacked && attackedSet.find(attacked->getID()) != attackedSet.end();}void Player::addAttacked(const Player* attacked){if(hasFlag(PlayerFlag_NotGainInFight) || !attacked) return;uint32_t attackedId = attacked->getID();if(attackedSet.find(attackedId) == attackedSet.end()) attackedSet.insert(attackedId);}void Player::setSkullEnd(time_t _time, bool login, Skulls_t _skull){if(g_game.getWorldType() == WORLD_TYPE_PVP_ENFORCED) return;bool requireUpdate = false;if(_time > time(NULL)){ requireUpdate = true; setSkull(_skull);}else if(skull == _skull){ requireUpdate = true; setSkull(SKULL_NONE); _time = 0;}if(requireUpdate){ skullEnd = _time; if(!login) g_game.updateCreatureSkull(this);}}bool Player::addUnjustifiedKill(const Player* attacked){if(g_game.getWorldType() == WORLD_TYPE_PVP_ENFORCED || attacked == this || hasFlag( PlayerFlag_NotGainInFight) || hasCustomFlag(PlayerCustomFlag_NotGainSkull)) return false;if(client){ char buffer[90]; sprintf(buffer, "Warning! The murder of %s was not justified.", attacked->getName().c_str()); client->sendTextMessage(MSG_STATUS_WARNING, buffer);}time_t now = time(NULL), today = (now - 84600), week = (now - (7 * 84600));std::vector<time_t> dateList;IOLoginData::getInstance()->getUnjustifiedDates(guid, dateList, now);dateList.push_back(now);uint32_t tc = 0, wc = 0, mc = dateList.size();for(std::vector<time_t>::iterator it = dateList.begin(); it != dateList.end(); ++it){ if((*it) > week) wc++; if((*it) > today) tc++;}uint32_t d = g_config.getNumber(ConfigManager::RED_DAILY_LIMIT), w = g_config.getNumber( ConfigManager::RED_WEEKLY_LIMIT), m = g_config.getNumber(ConfigManager::RED_MONTHLY_LIMIT);if(skull < SKULL_RED && ((d > 0 && tc >= d) || (w > 0 && wc >= w) || (m > 0 && mc >= m))) setSkullEnd(now + g_config.getNumber(ConfigManager::RED_SKULL_LENGTH), false, SKULL_RED);if(!g_config.getBool(ConfigManager::USE_BLACK_SKULL)){ d += g_config.getNumber(ConfigManager::BAN_DAILY_LIMIT); w += g_config.getNumber(ConfigManager::BAN_WEEKLY_LIMIT); m += g_config.getNumber(ConfigManager::BAN_MONTHLY_LIMIT); if((d <= 0 || tc < d) && (w <= 0 || wc < w) && (m <= 0 || mc < m)) return true; if(!IOBan::getInstance()->addAccountBanishment(accountId, (now + g_config.getNumber( ConfigManager::KILLS_BAN_LENGTH)), 20, ACTION_BANISHMENT, "Unjustified player killing.", 0, guid)) return true; sendTextMessage(MSG_INFO_DESCR, "You have been banished."); g_game.addMagicEffect(getPosition(), MAGIC_EFFECT_WRAPS_GREEN); Scheduler::getInstance().addEvent(createSchedulerTask(1000, boost::bind( &Game::kickPlayer, &g_game, getID(), false)));}else{ d += g_config.getNumber(ConfigManager::BLACK_DAILY_LIMIT); w += g_config.getNumber(ConfigManager::BLACK_WEEKLY_LIMIT); m += g_config.getNumber(ConfigManager::BLACK_MONTHLY_LIMIT); if(skull < SKULL_BLACK && ((d > 0 && tc >= d) || (w > 0 && wc >= w) || (m > 0 && mc >= m))) { setSkullEnd(now + g_config.getNumber(ConfigManager::BLACK_SKULL_LENGTH), false, SKULL_BLACK); setAttackedCreature(NULL); destroySummons(); }}return true;}void Player::setPromotionLevel(uint32_t pLevel){if(pLevel > promotionLevel){ uint32_t tmpLevel = 0, currentVoc = vocation_id; for(uint32_t i = promotionLevel; i < pLevel; ++i) { currentVoc = Vocations::getInstance()->getPromotedVocation(currentVoc); if(!currentVoc) break; tmpLevel++; Vocation* voc = Vocations::getInstance()->getVocation(currentVoc); if(voc->isPremiumNeeded() && !isPremium() && g_config.getBool(ConfigManager::PREMIUM_FOR_PROMOTION)) continue; vocation_id = currentVoc; } promotionLevel += tmpLevel;}else if(pLevel < promotionLevel){ uint32_t tmpLevel = 0, currentVoc = vocation_id; for(uint32_t i = pLevel; i < promotionLevel; ++i) { Vocation* voc = Vocations::getInstance()->getVocation(currentVoc); if(voc->getFromVocation() == currentVoc) break; tmpLevel++; currentVoc = voc->getFromVocation(); if(voc->isPremiumNeeded() && !isPremium() && g_config.getBool(ConfigManager::PREMIUM_FOR_PROMOTION)) continue; vocation_id = currentVoc; } promotionLevel -= tmpLevel;}setVocation(vocation_id);}uint16_t Player::getBlessings() const{if(!isPremium() && g_config.getBool(ConfigManager::BLESSING_ONLY_PREMIUM)) return 0;uint16_t count = 0;for(int16_t i = 0; i < 16; ++i){ if(hasBlessing(i)) count++;}return count;}uint64_t Player::getLostExperience() const{if(!skillLoss) return 0;double percent = (double)(lossPercent[LOSS_EXPERIENCE] - vocation->getLessLoss() - (getBlessings() * g_config.getNumber( ConfigManager::BLESS_REDUCTION))) / 100.;if(level <= 25) return (uint64_t)std::floor((double)(experience * percent) / 10.);int32_t base = level;double levels = (double)(base + 50) / 100.;uint64_t lost = 0;while(levels > 1.0f){ lost += (getExpForLevel(base) - getExpForLevel(base - 1)); base--; levels -= 1.;}if(levels > 0.) lost += (uint64_t)std::floor((double)(getExpForLevel(base) - getExpForLevel(base - 1)) * levels);return (uint64_t)std::floor((double)(lost * percent));}uint32_t Player::getAttackSpeed(){Item* weapon = getWeapon();if(weapon && weapon->getAttackSpeed() != 0) return weapon->getAttackSpeed();return vocation->getAttackSpeed();}void Player::learnInstantSpell(const std::string& name){if(!hasLearnedInstantSpell(name)) learnedInstantSpellList.push_back(name);}void Player::unlearnInstantSpell(const std::string& name){if(!hasLearnedInstantSpell(name)) return;LearnedInstantSpellList::iterator it = std::find(learnedInstantSpellList.begin(), learnedInstantSpellList.end(), name);if(it != learnedInstantSpellList.end()) learnedInstantSpellList.erase(it);}bool Player::hasLearnedInstantSpell(const std::string& name) const{if(hasFlag(PlayerFlag_CannotUseSpells)) return false;if(hasFlag(PlayerFlag_IgnoreSpellCheck)) return true;for(LearnedInstantSpellList::const_iterator it = learnedInstantSpellList.begin(); it != learnedInstantSpellList.end(); ++it){ if(!strcasecmp((*it).c_str(), name.c_str())) return true;}return false;}void Player::manageAccount(const std::string &text){std::stringstream msg;msg << "Account Manager: ";bool noSwap = true;switch(accountManager){ case MANAGER_NAMELOCK: { if(!talkState[1]) { managerString = text; trimString(managerString); if(managerString.length() < 4) msg << "Your name you want is too short, please select a longer name."; else if(managerString.length() > 20) msg << "The name you want is too long, please select a shorter name."; else if(!isValidName(managerString)) msg << "That name seems to contain invalid symbols, please choose another name."; else if(IOLoginData::getInstance()->playerExists(managerString, true)) msg << "A player with that name already exists, please choose another name."; else { std::string tmp = asLowerCaseString(managerString); if(tmp.substr(0, 4) != "god " && tmp.substr(0, 3) != "cm " && tmp.substr(0, 3) != "gm ") { talkState[1] = true; talkState[2] = true; msg << managerString << ", are you sure?"; } else msg << "Your character is not a staff member, please tell me another name!"; } } else if(checkText(text, "no") && talkState[2]) { talkState[1] = talkState[2] = false; msg << "What else would you like to name your character?"; } else if(checkText(text, "yes") && talkState[2]) { if(!IOLoginData::getInstance()->playerExists(managerString, true)) { uint32_t tmp; if(IOLoginData::getInstance()->getGuidByName(tmp, managerString2) && IOLoginData::getInstance()->changeName(tmp, managerString, managerString2) && IOBan::getInstance()->removePlayerBanishment(tmp, PLAYERBAN_LOCK)) { if(House* house = Houses::getInstance()->getHouseByPlayerId(tmp)) house->updateDoorDescription(managerString); talkState[1] = true; talkState[2] = false; msg << "Your character has been successfully renamed, you should now be able to login at it without any problems."; } else { talkState[1] = talkState[2] = false; msg << "Failed to change your name, please try again."; } } else { talkState[1] = talkState[2] = false; msg << "A player with that name already exists, please choose another name."; } } else msg << "Sorry, but I can't understand you, please try to repeat that!"; break; } case MANAGER_ACCOUNT: { Account account = IOLoginData::getInstance()->loadAccount(managerNumber); if(checkText(text, "cancel") || (checkText(text, "account") && !talkState[1])) { talkState[1] = true; for(int8_t i = 2; i <= 12; i++) talkState[i] = false; msg << "Do you want to change your 'password', request a 'recovery key', add a 'character', or 'delete' a character?"; } else if(checkText(text, "delete") && talkState[1]) { talkState[1] = false; talkState[2] = true; msg << "Which character would you like to delete?"; } else if(talkState[2]) { std::string tmp = text; trimString(tmp); if(!isValidName(tmp, false)) msg << "That name contains invalid characters, try to say your name again, you might have typed it wrong."; else { talkState[2] = false; talkState[3] = true; managerString = tmp; msg << "Do you really want to delete the character named " << managerString << "?"; } } else if(checkText(text, "yes") && talkState[3]) { switch(IOLoginData::getInstance()->deleteCharacter(managerNumber, managerString)) { case DELETE_INTERNAL: msg << "An error occured while deleting your character. Either the character does not belong to you or it doesn't exist."; break; case DELETE_SUCCESS: msg << "Your character has been deleted."; break; case DELETE_HOUSE: msg << "Your character owns a house. To make sure you really want to lose your house by deleting your character, you have to login and leave the house or pass it to someone else first."; break; case DELETE_LEADER: msg << "Your character is the leader of a guild. You need to disband or pass the leadership someone else to delete your character."; break; case DELETE_ONLINE: msg << "A character with that name is currently online, to delete a character it has to be offline."; break; } talkState[1] = true; for(int8_t i = 2; i <= 12; i++) talkState[i] = false; } else if(checkText(text, "no") && talkState[3]) { talkState[1] = true; talkState[3] = false; msg << "Tell me what character you want to delete."; } else if(checkText(text, "password") && talkState[1]) { talkState[1] = false; talkState[4] = true; msg << "Tell me your new password please."; } else if(talkState[4]) { std::string tmp = text; trimString(tmp); if(tmp.length() < 6) msg << "That password is too short, at least 6 digits are required. Please select a longer password."; else if(!isValidPassword(tmp)) msg << "Your password contains invalid characters... please tell me another one."; else { talkState[4] = false; talkState[5] = true; managerString = tmp; msg << "Should '" << managerString << "' be your new password?"; } } else if(checkText(text, "yes") && talkState[5]) { talkState[1] = true; for(int8_t i = 2; i <= 12; i++) talkState[i] = false; IOLoginData::getInstance()->setPassword(managerNumber, managerString); msg << "Your password has been changed."; } else if(checkText(text, "no") && talkState[5]) { talkState[1] = true; for(int8_t i = 2; i <= 12; i++) talkState[i] = false; msg << "Then not."; } else if(checkText(text, "character") && talkState[1]) { if(account.charList.size() <= 15) { talkState[1] = false; talkState[6] = true; msg << "What would you like as your character name?"; } else { talkState[1] = true; for(int8_t i = 2; i <= 12; i++) talkState[i] = false; msg << "Your account reach the limit of 15 players, you can 'delete' a character if you want to create a new one."; } } else if(talkState[6]) { managerString = text; trimString(managerString); if(managerString.length() < 4) msg << "Your name you want is too short, please select a longer name."; else if(managerString.length() > 20) msg << "The name you want is too long, please select a shorter name."; else if(!isValidName(managerString)) msg << "That name seems to contain invalid symbols, please choose another name."; else if(IOLoginData::getInstance()->playerExists(managerString, true)) msg << "A player with that name already exists, please choose another name."; else { std::string tmp = asLowerCaseString(managerString); if(tmp.substr(0, 4) != "god " && tmp.substr(0, 3) != "cm " && tmp.substr(0, 3) != "gm ") { talkState[6] = false; talkState[7] = true; msg << managerString << ", are you sure?"; } else msg << "Your character is not a staff member, please tell me another name!"; } } else if(checkText(text, "no") && talkState[7]) { talkState[6] = true; talkState[7] = false; msg << "What else would you like to name your character?"; } else if(checkText(text, "yes") && talkState[7]) { talkState[7] = false; talkState[8] = true; msg << "Should your character be a 'male' or a 'female'."; } else if(talkState[8] && (checkText(text, "female") || checkText(text, "male"))) { talkState[8] = false; talkState[9] = true; if(checkText(text, "female")) { msg << "A female, are you sure?"; managerSex = PLAYERSEX_FEMALE; } else { msg << "A male, are you sure?"; managerSex = PLAYERSEX_MALE; } } else if(checkText(text, "no") && talkState[9]) { talkState[8] = true; talkState[9] = false; msg << "Tell me... would you like to be a 'male' or a 'female'?"; } else if(checkText(text, "yes") && talkState[9]) { if(g_config.getBool(ConfigManager::START_CHOOSEVOC)) { talkState[9] = false; talkState[11] = true; bool firstPart = true; for(VocationsMap::iterator it = Vocations::getInstance()->getFirstVocation(); it != Vocations::getInstance()->getLastVocation(); ++it) { if(it->first == it->second->getFromVocation() && it->first != 0) { if(firstPart) { msg << "What do you want to be... " << it->second->getDescription(); firstPart = false; } else if(it->first - 1 != 0) msg << ", " << it->second->getDescription(); else msg << " or " << it->second->getDescription() << "."; } } } else if(!IOLoginData::getInstance()->playerExists(managerString, true)) { talkState[1] = true; for(int8_t i = 2; i <= 12; i++) talkState[i] = false; if(IOLoginData::getInstance()->createCharacter(managerNumber, managerString, managerNumber2, (uint16_t)managerSex)) msg << "Your character has been created."; else msg << "Your character couldn't be created, please try again."; } else { talkState[6] = true; talkState[9] = false; msg << "A player with that name already exists, please choose another name."; } } else if(talkState[11]) { for(VocationsMap::iterator it = Vocations::getInstance()->getFirstVocation(); it != Vocations::getInstance()->getLastVocation(); ++it) { std::string tmp = asLowerCaseString(it->second->getName()); if(checkText(text, tmp) && it != Vocations::getInstance()->getLastVocation() && it->first == it->second->getFromVocation() && it->first != 0) { msg << "So you would like to be " << it->second->getDescription() << "... are you sure?"; managerNumber2 = it->first; talkState[11] = false; talkState[12] = true; } } if(msg.str().length() == 17) msg << "I don't understand what vocation you would like to be... could you please repeat it?"; } else if(checkText(text, "yes") && talkState[12]) { if(!IOLoginData::getInstance()->playerExists(managerString, true)) { talkState[1] = true; for(int8_t i = 2; i <= 12; i++) talkState[i] = false; if(IOLoginData::getInstance()->createCharacter(managerNumber, managerString, managerNumber2, (uint16_t)managerSex)) msg << "Your character has been created."; else msg << "Your character couldn't be created, please try again."; } else { talkState[6] = true; talkState[9] = false; msg << "A player with that name already exists, please choose another name."; } } else if(checkText(text, "no") && talkState[12]) { talkState[11] = true; talkState[12] = false; msg << "No? Then what would you like to be?"; } else if(checkText(text, "recovery key") && talkState[1]) { talkState[1] = false; talkState[10] = true; msg << "Would you like a recovery key?"; } else if(checkText(text, "yes") && talkState[10]) { if(account.recoveryKey != "0") msg << "Sorry, you already have a recovery key, for security reasons I may not give you a new one."; else { managerString = generateRecoveryKey(4, 4); IOLoginData::getInstance()->setRecoveryKey(managerNumber, managerString); msg << "Your recovery key is: " << managerString << "."; } talkState[1] = true; for(int8_t i = 2; i <= 12; i++) talkState[i] = false; } else if(checkText(text, "no") && talkState[10]) { msg << "Then not."; talkState[1] = true; for(int8_t i = 2; i <= 12; i++) talkState[i] = false; } else msg << "Please read the latest message that I have specified, I don't understand the current requested action."; break; } case MANAGER_NEW: { if(checkText(text, "account") && !talkState[1]) { msg << "What would you like your password to be?"; talkState[1] = true; talkState[2] = true; } else if(talkState[2]) { std::string tmp = text; trimString(tmp); if(tmp.length() < 6) msg << "That password is too short, at least 6 digits are required. Please select a longer password."; else if(!isValidPassword(tmp)) msg << "Your password contains invalid characters... please tell me another one."; else { talkState[3] = true; talkState[2] = false; managerString = tmp; msg << managerString << " is it? 'yes' or 'no'?"; } } else if(checkText(text, "yes") && talkState[3]) { if(g_config.getBool(ConfigManager::GENERATE_ACCOUNT_NUMBER)) { do sprintf(managerChar, "%d%d%d%d%d%d%d", random_range(2, 9), random_range(2, 9), random_range(2, 9), random_range(2, 9), random_range(2, 9), random_range(2, 9), random_range(2, 9)); while(IOLoginData::getInstance()->accountNameExists(managerChar)); uint32_t id = (uint32_t)IOLoginData::getInstance()->createAccount(managerChar, managerString); if(id) { accountManager = MANAGER_ACCOUNT; managerNumber = id; noSwap = talkState[1] = false; msg << "Your account has been created, you may manage it now, but remember your account name: '" << managerChar << "' and password: '" << managerString << "'! If the account name is too hard to remember, please note it somewhere."; } else msg << "Your account could not be created, please try again."; for(int8_t i = 2; i <= 5; i++) talkState[i] = false; } else { msg << "What would you like your account name to be?"; talkState[3] = false; talkState[4] = true; } } else if(checkText(text, "no") && talkState[3]) { talkState[2] = true; talkState[3] = false; msg << "What would you like your password to be then?"; } else if(talkState[4]) { std::string tmp = text; trimString(tmp); if(tmp.length() < 3) msg << "That account name is too short, at least 3 digits are required. Please select a longer account name."; else if(tmp.length() > 25) msg << "That account name is too long, not more than 25 digits are required. Please select a shorter account name."; else if(!isValidAccountName(tmp)) msg << "Your account name contains invalid characters, please choose another one."; else if(asLowerCaseString(tmp) == asLowerCaseString(managerString)) msg << "Your account name cannot be same as password, please choose another one."; else { sprintf(managerChar, "%s", tmp.c_str()); msg << managerChar << ", are you sure?"; talkState[4] = false; talkState[5] = true; } } else if(checkText(text, "yes") && talkState[5]) { if(!IOLoginData::getInstance()->accountNameExists(managerChar)) { uint32_t id = (uint32_t)IOLoginData::getInstance()->createAccount(managerChar, managerString); if(id) { accountManager = MANAGER_ACCOUNT; managerNumber = id; noSwap = talkState[1] = false; msg << "Your account has been created, you may manage it now, but remember your account name: '" << managerChar << "' and password: '" << managerString << "'!"; } else msg << "Your account could not be created, please try again."; for(int8_t i = 2; i <= 5; i++) talkState[i] = false; } else { msg << "An account with that name already exists, please try another account name."; talkState[4] = true; talkState[5] = false; } } else if(checkText(text, "no") && talkState[5]) { talkState[5] = false; talkState[4] = true; msg << "What else would you like as your account name?"; } else if(checkText(text, "recover") && !talkState[6]) { talkState[6] = true; talkState[7] = true; msg << "What was your account name?"; } else if(talkState[7]) { managerString = text; if(IOLoginData::getInstance()->getAccountId(managerString, (uint32_t&)managerNumber)) { talkState[7] = false; talkState[8] = true; msg << "What was your recovery key?"; } else { msg << "Sorry, but account with such name doesn't exists."; talkState[6] = talkState[7] = false; } } else if(talkState[8]) { managerString2 = text; if(IOLoginData::getInstance()->validRecoveryKey(managerNumber, managerString2) && managerString2 != "0") { sprintf(managerChar, "%s%d", g_config.getString(ConfigManager::SERVER_NAME).c_str(), random_range(100, 999)); IOLoginData::getInstance()->setPassword(managerNumber, managerChar); msg << "Correct! Your new password is: " << managerChar << "."; } else msg << "Sorry, but this key doesn't match to account you gave me."; talkState[7] = talkState[8] = false; } else msg << "Sorry, but I can't understand you, please try to repeat that."; break; } default: return; break;}sendTextMessage(MSG_STATUS_CONSOLE_BLUE, msg.str().c_str());if(!noSwap) sendTextMessage(MSG_STATUS_CONSOLE_ORANGE, "Hint: Type 'account' to manage your account and if you want to start over then type 'cancel'.");}bool Player::isGuildInvited(uint32_t guildId) const{for(InvitedToGuildsList::const_iterator it = invitedToGuildsList.begin(); it != invitedToGuildsList.end(); ++it){ if((*it) == guildId) return true;}return false;}void Player::leaveGuild(){sendClosePrivate(CHANNEL_GUILD);guildLevel = GUILDLEVEL_NONE;guildId = rankId = 0;guildName = rankName = guildNick = "";}bool Player::isPremium() const{if(g_config.getBool(ConfigManager::FREE_PREMIUM) || hasFlag(PlayerFlag_IsAlwaysPremium)) return true;return premiumDays;}bool Player::setGuildLevel(GuildLevel_t newLevel, uint32_t rank/* = 0*/){std::string name;if(!IOGuild::getInstance()->getRankEx(rank, name, guildId, newLevel)) return false;guildLevel = newLevel;rankName = name;rankId = rank;return true;}void Player::setGroupId(int32_t newId){if(Group* tmp = Groups::getInstance()->getGroup(newId)){ groupId = newId; group = tmp;}}void Player::setGroup(Group* newGroup){if(newGroup){ group = newGroup; groupId = group->getId();}}PartyShields_t Player::getPartyShield(const Creature* creature) const{const Player* player = creature->getPlayer();if(!player) return Creature::getPartyShield(creature);if(Party* party = getParty()){ if(party->getLeader() == player) { if(party->isSharedExperienceActive()) { if(party->isSharedExperienceEnabled()) return SHIELD_YELLOW_SHAREDEXP; if(party->canUseSharedExperience(player)) return SHIELD_YELLOW_NOSHAREDEXP; return SHIELD_YELLOW_NOSHAREDEXP_BLINK; } return SHIELD_YELLOW; } if(party->isPlayerMember(player)) { if(party->isSharedExperienceActive()) { if(party->isSharedExperienceEnabled()) return SHIELD_BLUE_SHAREDEXP; if(party->canUseSharedExperience(player)) return SHIELD_BLUE_NOSHAREDEXP; return SHIELD_BLUE_NOSHAREDEXP_BLINK; } return SHIELD_BLUE; } if(isInviting(player)) return SHIELD_WHITEBLUE;}if(player->isInviting(this)) return SHIELD_WHITEYELLOW;return SHIELD_NONE;}bool Player::isInviting(const Player* player) const{if(!player || !getParty() || getParty()->getLeader() != this) return false;return getParty()->isPlayerInvited(player);}bool Player::isPartner(const Player* player) const{if(!player || !getParty() || !player->getParty()) return false;return (getParty() == player->getParty());}void Player::sendPlayerPartyIcons(Player* player){sendCreatureShield(player);sendCreatureSkull(player);}bool Player::addPartyInvitation(Party* party){if(!party) return false;PartyList::iterator it = std::find(invitePartyList.begin(), invitePartyList.end(), party);if(it != invitePartyList.end()) return false;invitePartyList.push_back(party);return true;}bool Player::removePartyInvitation(Party* party){if(!party) return false;PartyList::iterator it = std::find(invitePartyList.begin(), invitePartyList.end(), party);if(it != invitePartyList.end()){ invitePartyList.erase(it); return true;}return false;}void Player::clearPartyInvitations(){if(invitePartyList.empty()) return;PartyList list;for(PartyList::iterator it = invitePartyList.begin(); it != invitePartyList.end(); ++it) list.push_back(*it);invitePartyList.clear();for(PartyList::iterator it = list.begin(); it != list.end(); ++it) (*it)->removeInvite(this);}void Player::increaseCombatValues(int32_t& min, int32_t& max, bool useCharges, bool countWeapon){if(min > 0) min = (int32_t)(min * vocation->getMultiplier(MULTIPLIER_HEALING));else min = (int32_t)(min * vocation->getMultiplier(MULTIPLIER_MAGIC));if(max > 0) max = (int32_t)(max * vocation->getMultiplier(MULTIPLIER_HEALING));else max = (int32_t)(max * vocation->getMultiplier(MULTIPLIER_MAGIC));Item* weapon = NULL;if(!countWeapon) weapon = getWeapon();Item* item = NULL;int32_t minValue = 0, maxValue = 0;for(int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i){ if(!(item = getInventoryItem((slots_t)i)) || (g_moveEvents->hasEquipEvent(item) && !isItemAbilityEnabled((slots_t)i))) continue; const ItemType& it = Item::items[item->getID()]; if(min > 0) { minValue += it.abilities.increment[HEALING_VALUE]; if(it.abilities.increment[HEALING_PERCENT]) min = (int32_t)std::ceil((double)(min * it.abilities.increment[HEALING_PERCENT]) / 100.); } else { minValue -= it.abilities.increment[MAGIC_VALUE]; if(it.abilities.increment[MAGIC_PERCENT]) min = (int32_t)std::ceil((double)(min * it.abilities.increment[MAGIC_PERCENT]) / 100.); } if(max > 0) { maxValue += it.abilities.increment[HEALING_VALUE]; if(it.abilities.increment[HEALING_PERCENT]) max = (int32_t)std::ceil((double)(max * it.abilities.increment[HEALING_PERCENT]) / 100.); } else { maxValue -= it.abilities.increment[MAGIC_VALUE]; if(it.abilities.increment[MAGIC_PERCENT]) max = (int32_t)std::ceil((double)(max * it.abilities.increment[MAGIC_PERCENT]) / 100.); } bool removeCharges = false; for(int32_t j = INCREMENT_FIRST; j <= INCREMENT_LAST; ++j) { if(!it.abilities.increment[(Increment_t)j]) continue; removeCharges = true; break; } if(useCharges && removeCharges && item != weapon && item->hasCharges()) g_game.transformItem(item, item->getID(), std::max((int32_t)0, (int32_t)item->getCharges() - 1));}min += minValue;max += maxValue;}bool Player::transferMoneyTo(const std::string& name, uint64_t amount){if(!g_config.getBool(ConfigManager::BANK_SYSTEM) || amount > balance) return false;Player* target = g_game.getPlayerByNameEx(name);if(!target) return false;balance -= amount;target->balance += amount;if(target->isVirtual()){ IOLoginData::getInstance()->savePlayer(target); delete target;}return true;}void Player::sendCritical() const{if(g_config.getBool(ConfigManager::DISPLAY_CRITICAL_HIT)) g_game.addAnimatedText(getPosition(), TEXTCOLOR_DARKRED, "CRITICAL!");} Sera q tem como corrigir ? Editado Novembro 26, 2011 por AnyurCT Link para o comentário https://xtibia.com/forum/topic/173167-beta-duel-system-v11/page/2/#findComment-1139396 Compartilhar em outros sites More sharing options...
vitorcorreaxrm 0 Postado Novembro 26, 2011 Share Postado Novembro 26, 2011 Po, aquiie ta dando erro ao compilar, tem como voce postar o executavel ja compilaado seria mais facil . script parece ser mt bom ja ganho meu rep + Link para o comentário https://xtibia.com/forum/topic/173167-beta-duel-system-v11/page/2/#findComment-1139612 Compartilhar em outros sites More sharing options...
lailton 0 Postado Novembro 29, 2011 Share Postado Novembro 29, 2011 @Lailton Qual o erro ? Poste aqui o erro que arrumo. Alguma ideia ? Link para o comentário https://xtibia.com/forum/topic/173167-beta-duel-system-v11/page/2/#findComment-1141323 Compartilhar em outros sites More sharing options...
ferrari.renan 1 Postado Dezembro 2, 2011 Share Postado Dezembro 2, 2011 Lailton, altera este getID() para getGUID() e tente compilar. Qualquer coisa poste aqui. Link para o comentário https://xtibia.com/forum/topic/173167-beta-duel-system-v11/page/2/#findComment-1143506 Compartilhar em outros sites More sharing options...
Katxz 1 Postado Dezembro 2, 2011 Share Postado Dezembro 2, 2011 (editado) Renan 1995 Tenhu este error a compilar: In member function `bool Party::invitePlayer(Player*)': invalid conversion from `uint32_t' to `const char*' nitializing argument 1 of `std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]' invalid conversion from `uint32_t' to `const char*' initializing argument 1 of `std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]' Makefile.win [build Error] [obj//party.o] Error 1 Tenhu este error Enha linas leader->setStorage(93000,"7"); leader->setStorage(93000,"31"); leader->setStorage(93001,player->getGUID()); player->setStorage(93000,"8"); player->setStorage(93002,leader->getGUID()); } Ajuda pls AFF PORFAVOR POSTA UM PARTY.cpp QUE FUNCIONE OBRIGADO Editado Dezembro 2, 2011 por Katxz Link para o comentário https://xtibia.com/forum/topic/173167-beta-duel-system-v11/page/2/#findComment-1143527 Compartilhar em outros sites More sharing options...
lailton 0 Postado Dezembro 3, 2011 Share Postado Dezembro 3, 2011 O cara sumiu... Tambem tenho o msmo erro. foda q no nome ja diz BETA, e ainda ja ta com problemas no compilar. imagina depois disso no sistema ? no minimo deveria ter o server compilado ou video print screen para podermos analisar. Link para o comentário https://xtibia.com/forum/topic/173167-beta-duel-system-v11/page/2/#findComment-1143623 Compartilhar em outros sites More sharing options...
ferrari.renan 1 Postado Dezembro 3, 2011 Share Postado Dezembro 3, 2011 (editado) Entendo... teríamos aí, um erro do próprio party.cpp postado pelo autor do tópico. Verei o arquivo, e qualquer coisa posto corrigido aqui. Aqui está, não sei ao certo se irá funcionar, tenho muito pouca experiência em C++. Valeu, até mais! Download correto: http://www.4shared.com/file/PK_yvAIw/party.html Editado Dezembro 3, 2011 por Renan1995 Link para o comentário https://xtibia.com/forum/topic/173167-beta-duel-system-v11/page/2/#findComment-1143656 Compartilhar em outros sites More sharing options...
Katxz 1 Postado Dezembro 3, 2011 Share Postado Dezembro 3, 2011 Vou testa... Obrigado Link para o comentário https://xtibia.com/forum/topic/173167-beta-duel-system-v11/page/2/#findComment-1143667 Compartilhar em outros sites More sharing options...
ferrari.renan 1 Postado Dezembro 3, 2011 Share Postado Dezembro 3, 2011 (editado) Creio que haja um erro no arquivo postado acima. Pode ser que compile, mas o correto está aqui: http://www.4shared.com/file/PK_yvAIw/party.html Editado Dezembro 3, 2011 por Renan1995 Link para o comentário https://xtibia.com/forum/topic/173167-beta-duel-system-v11/page/2/#findComment-1143671 Compartilhar em outros sites More sharing options...
lailton 0 Postado Dezembro 3, 2011 Share Postado Dezembro 3, 2011 Tambem nao so ninja em C++ mais acho q tu se enganou aqui: linha 180 e 181 player->setStorage(91000, value); leader->setStorage(91000, value1); correto seria: player->setStorage(91000, value1); leader->setStorage(91000, value); Outra coisa setStorage 91000 2 vezes, pela logica isso desativaria a primeira sobescrevendo pela segunda. esta confuso o codigo... Link para o comentário https://xtibia.com/forum/topic/173167-beta-duel-system-v11/page/2/#findComment-1143809 Compartilhar em outros sites More sharing options...
ferrari.renan 1 Postado Dezembro 3, 2011 Share Postado Dezembro 3, 2011 Não, amigo, creio que você fez confusão quanto ao código. O value retorna o GUID do player convidado, e o value1 o GUID do player que está a convidar. Os storages estão corretos. Eles não irão se anular, pois estarão sendo executados em jogadores diferentes. Repare que um é o lider e o outro o player convidado. Link para o comentário https://xtibia.com/forum/topic/173167-beta-duel-system-v11/page/2/#findComment-1143981 Compartilhar em outros sites More sharing options...
lailton 0 Postado Dezembro 3, 2011 Share Postado Dezembro 3, 2011 verdade falha minha. teria como postar um server ja compilado com o script integrado para poder analisar o funcionamento se vale a pena instalar no meu server ? Obrigado +rep Link para o comentário https://xtibia.com/forum/topic/173167-beta-duel-system-v11/page/2/#findComment-1144004 Compartilhar em outros sites More sharing options...
Katxz 1 Postado Dezembro 4, 2011 Share Postado Dezembro 4, 2011 Eu install en meu server.. Nao funfa.. tira muitos error no console.. Esperando por el "Duel System 2.0" Ete tenhe muitos errores.. Arrumar pls. Obrigado. Link para o comentário https://xtibia.com/forum/topic/173167-beta-duel-system-v11/page/2/#findComment-1144070 Compartilhar em outros sites More sharing options...
ADMWolf 0 Postado Dezembro 15, 2011 Share Postado Dezembro 15, 2011 (editado) Excelente! bom trabalho espero que consiga a versão 2.0 se estiver interessado em entrar numa equipe de pokemon mande PM para min. Editado Dezembro 15, 2011 por AdimistradorWolf Link para o comentário https://xtibia.com/forum/topic/173167-beta-duel-system-v11/page/2/#findComment-1153868 Compartilhar em outros sites More sharing options...
Posts Recomendados