//////////////////////////////////////////////////////////////////////// // 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 . //////////////////////////////////////////////////////////////////////// #ifndef __CREATURE__ #define __CREATURE__ #include "otsystem.h" #include "templates.h" #include #include "const.h" #include "enums.h" #include "map.h" #include "condition.h" #include "creatureevent.h" enum slots_t { SLOT_PRE_FIRST = 0, SLOT_WHEREEVER = SLOT_PRE_FIRST, SLOT_FIRST = 1, SLOT_HEAD = SLOT_FIRST, SLOT_NECKLACE = 2, SLOT_BACKPACK = 3, SLOT_ARMOR = 4, SLOT_RIGHT = 5, SLOT_LEFT = 6, SLOT_LEGS = 7, SLOT_FEET = 8, SLOT_RING = 9, SLOT_AMMO = 10, SLOT_DEPOT = 11, SLOT_LAST = SLOT_DEPOT, SLOT_HAND = 12, SLOT_TWO_HAND = SLOT_HAND }; enum lootDrop_t { LOOT_DROP_FULL = 0, LOOT_DROP_PREVENT, LOOT_DROP_NONE }; enum killflags_t { KILLFLAG_NONE = 0, KILLFLAG_LASTHIT = 1 << 0, KILLFLAG_JUSTIFY = 1 << 1, KILLFLAG_UNJUSTIFIED = 1 << 2 }; enum Visible_t { VISIBLE_NONE = 0, VISIBLE_APPEAR = 1, VISIBLE_DISAPPEAR = 2, VISIBLE_GHOST_APPEAR = 3, VISIBLE_GHOST_DISAPPEAR = 4 }; struct FindPathParams { bool fullPathSearch, clearSight, allowDiagonal, keepDistance; int32_t maxSearchDist, minTargetDist, maxTargetDist; FindPathParams() { fullPathSearch = clearSight = allowDiagonal = true; maxSearchDist = minTargetDist = maxTargetDist = -1; keepDistance = false; } }; struct DeathLessThan; struct DeathEntry { DeathEntry(std::string name, int32_t dmg): data(name), damage(dmg), last(false), unjustified(false) {} DeathEntry(Creature* killer, int32_t dmg): data(killer), damage(dmg), last(false), unjustified(false) {} void setUnjustified(bool v) {unjustified = v;} bool isCreatureKill() const {return data.type() == typeid(Creature*);} bool isNameKill() const {return !isCreatureKill();} #ifdef __WAR_SYSTEM__ void setWar(War_t v) {war = v;} War_t getWar() const {return war;} #endif bool isUnjustified() const {return unjustified;} const std::type_info& getKillerType() const {return data.type();} Creature* getKillerCreature() const {return boost::any_cast(data);} std::string getKillerName() const {return boost::any_cast(data);} protected: boost::any data; int32_t damage; bool last; bool unjustified; #ifdef __WAR_SYSTEM__ War_t war; #endif friend struct DeathLessThan; }; struct DeathLessThan { bool operator()(const DeathEntry& d1, const DeathEntry& d2) {return d1.damage > d2.damage;} }; typedef std::vector DeathList; typedef std::list CreatureEventList; typedef std::list ConditionList; typedef std::map StorageMap; class Map; class Tile; class Thing; class Player; class Monster; class Npc; class Item; class Container; #define EVENT_CREATURECOUNT 4 #define EVENT_CREATURE_THINK_INTERVAL 200 #define EVENT_CHECK_CREATURE_INTERVAL (EVENT_CREATURE_THINK_INTERVAL / EVENT_CREATURECOUNT) class FrozenPathingConditionCall { public: FrozenPathingConditionCall(const Position& _targetPos); virtual ~FrozenPathingConditionCall() {} virtual bool operator()(const Position& startPos, const Position& testPos, const FindPathParams& fpp, int32_t& bestMatchDist) const; bool isInRange(const Position& startPos, const Position& testPos, const FindPathParams& fpp) const; protected: Position targetPos; }; class Creature : public AutoId, virtual public Thing { protected: Creature(); public: virtual ~Creature(); virtual Creature* getCreature() {return this;} virtual const Creature* getCreature()const {return this;} virtual Player* getPlayer() {return NULL;} virtual const Player* getPlayer() const {return NULL;} virtual Npc* getNpc() {return NULL;} virtual const Npc* getNpc() const {return NULL;} virtual Monster* getMonster() {return NULL;} virtual const Monster* getMonster() const {return NULL;} virtual const std::string& getName() const = 0; virtual const std::string& getNameDescription() const = 0; virtual std::string getDescription(int32_t lookDistance) const; uint32_t getID() const {return id;} void setID() { /* * 0x10000000 - Player * 0x40000000 - Monster * 0x80000000 - NPC */ if(!id) id = autoId | rangeId(); } void setRemoved() {removed = true;} virtual bool isRemoved() const {return removed;} virtual uint32_t rangeId() = 0; virtual void removeList() = 0; virtual void addList() = 0; virtual bool canSee(const Position& pos) const; virtual bool canSeeCreature(const Creature* creature) const; virtual bool canWalkthrough(const Creature* creature) const {return creature->isWalkable() || creature->isGhost();} Direction getDirection() const {return direction;} void setDirection(Direction dir) {direction = dir;} bool getHideName() const {return hideName;} void setHideName(bool v) {hideName = v;} bool getHideHealth() const {return hideHealth;} void setHideHealth(bool v) {hideHealth = v;} SpeakClasses getSpeakType() const {return speakType;} void setSpeakType(SpeakClasses type) {speakType = type;} Position getMasterPosition() const {return masterPosition;} void setMasterPosition(const Position& pos, uint32_t radius = 1) {masterPosition = pos; masterRadius = radius;} virtual int32_t getThrowRange() const {return 1;} virtual RaceType_t getRace() const {return RACE_NONE;} virtual bool isPushable() const {return getWalkDelay() <= 0;} virtual bool canSeeInvisibility() const {return false;} int32_t getWalkDelay(Direction dir) const; int32_t getWalkDelay() const; int32_t getStepDuration(Direction dir) const; int32_t getStepDuration() const; void getPathToFollowCreature(); int64_t getEventStepTicks() const; int64_t getTimeSinceLastMove() const; virtual int32_t getStepSpeed() const {return getSpeed();} int32_t getSpeed() const {return baseSpeed + varSpeed;} void setSpeed(int32_t varSpeedDelta) { int32_t oldSpeed = getSpeed(); varSpeed = varSpeedDelta; if(getSpeed() <= 0) stopEventWalk(); else if(oldSpeed <= 0 && !listWalkDir.empty()) addEventWalk(); } void setBaseSpeed(uint32_t newBaseSpeed) {baseSpeed = newBaseSpeed;} int32_t getBaseSpeed() {return baseSpeed;} virtual int32_t getHealth() const {return health;} virtual int32_t getMaxHealth() const {return healthMax;} virtual int32_t getMana() const {return mana;} virtual int32_t getMaxMana() const {return manaMax;} bool isWalking() const {return (eventWalk > 0 && !listWalkDir.empty());} const Outfit_t getCurrentOutfit() const {return currentOutfit;} const void setCurrentOutfit(Outfit_t outfit) {currentOutfit = outfit;} const Outfit_t getDefaultOutfit() const {return defaultOutfit;} bool isInvisible() const {return hasCondition(CONDITION_INVISIBLE, -1, false);} virtual bool isGhost() const {return false;} virtual bool isWalkable() const {return false;} ZoneType_t getZone() const {return getTile()->getZone();} //walk functions bool startAutoWalk(std::list& listDir); void addEventWalk(); void stopEventWalk(); //walk events virtual void onWalk(Direction& dir); virtual void onWalkAborted() {} virtual void onWalkComplete() {} //follow functions virtual Creature* getFollowCreature() const {return followCreature;} virtual bool setFollowCreature(Creature* creature, bool fullPathSearch = false); //follow events virtual void onFollowCreature(const Creature* creature) {} virtual void onFollowCreatureComplete(const Creature* creature) {} //combat functions Creature* getAttackedCreature() {return attackedCreature;} virtual bool setAttackedCreature(Creature* creature); virtual BlockType_t blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage, bool checkDefense = false, bool checkArmor = false); void setMaster(Creature* creature) {master = creature;} Creature* getMaster() {return master;} const Creature* getMaster() const {return master;} Player* getPlayerMaster() const {return isPlayerSummon() ? master->getPlayer() : NULL;} bool isSummon() const {return master != NULL;} bool isPlayerSummon() const {return master && master->getPlayer();} virtual void addSummon(Creature* creature); virtual void removeSummon(const Creature* creature); const std::list& getSummons() {return summons;} void destroySummons(); uint32_t getSummonCount() const {return summons.size();} virtual int32_t getArmor() const {return 0;} virtual int32_t getDefense() const {return 0;} virtual float getAttackFactor() const {return 1.0f;} virtual float getDefenseFactor() const {return 1.0f;} bool addCondition(Condition* condition); bool addCombatCondition(Condition* condition); void removeCondition(ConditionType_t type); void removeCondition(ConditionType_t type, ConditionId_t id); void removeCondition(Condition* condition); void removeCondition(const Creature* attacker, ConditionType_t type); void removeConditions(ConditionEnd_t reason, bool onlyPersistent = true); Condition* getCondition(ConditionType_t type, ConditionId_t id, uint32_t subId = 0) const; void executeConditions(uint32_t interval); bool hasCondition(ConditionType_t type, int32_t subId = 0, bool checkTime = true) const; virtual bool isImmune(ConditionType_t type) const; virtual bool isImmune(CombatType_t type) const; virtual bool isSuppress(ConditionType_t type) const; virtual uint32_t getDamageImmunities() const {return 0;} virtual uint32_t getConditionImmunities() const {return 0;} virtual uint32_t getConditionSuppressions() const {return 0;} virtual bool isAttackable() const {return true;} virtual bool isAccountManager() const {return false;} virtual void changeHealth(int32_t healthChange); void changeMaxHealth(uint32_t healthChange) {healthMax = healthChange;} virtual void changeMana(int32_t manaChange); void changeMaxMana(uint32_t manaChange) {manaMax = manaChange;} virtual bool getStorage(const uint32_t key, std::string& value) const; virtual bool setStorage(const uint32_t key, const std::string& value); virtual void eraseStorage(const uint32_t key) {storageMap.erase(key);} inline StorageMap::const_iterator getStorageBegin() const {return storageMap.begin();} inline StorageMap::const_iterator getStorageEnd() const {return storageMap.end();} virtual void gainHealth(Creature* caster, int32_t amount); virtual void drainHealth(Creature* attacker, CombatType_t combatType, int32_t damage); virtual void drainMana(Creature* attacker, CombatType_t combatType, int32_t damage); virtual bool challengeCreature(Creature* creature) {return false;} virtual bool convinceCreature(Creature* creature) {return false;} virtual bool onDeath(); virtual double getGainedExperience(Creature* attacker) const {return getDamageRatio(attacker) * (double)getLostExperience();} void addDamagePoints(Creature* attacker, int32_t damagePoints); void addHealPoints(Creature* caster, int32_t healthPoints); bool hasBeenAttacked(uint32_t attackerId) 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 onTickCondition(ConditionType_t type, int32_t interval, bool& _remove); virtual void onCombatRemoveCondition(const Creature* attacker, Condition* condition); virtual void onAttackedCreature(Creature* target) {} virtual void onSummonAttackedCreature(Creature* summon, Creature* target) {} virtual void onAttacked() {} virtual void onAttackedCreatureDrainHealth(Creature* target, int32_t points); virtual void onSummonAttackedCreatureDrainHealth(Creature* summon, Creature* target, int32_t points) {} virtual void onAttackedCreatureDrainMana(Creature* target, int32_t points); virtual void onSummonAttackedCreatureDrainMana(Creature* summon, Creature* target, int32_t points) {} 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 void onAttackedCreatureKilled(Creature* target); virtual bool onKilledCreature(Creature* target, uint32_t& flags, DeathEntry& entry); 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 getCreatureLight(LightInfo& light) const; virtual void setNormalCreatureLight(); void setCreatureLight(LightInfo& light) {internalLight = light;} virtual void onThink(uint32_t interval); virtual void onAttacking(uint32_t interval); virtual void onWalk(); virtual bool getNextStep(Direction& dir, uint32_t& flags); virtual void onAddTileItem(const Tile* tile, const Position& pos, const Item* item); 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 onUpdateTile(const Tile* tile, const Position& pos) {} 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) {} virtual void onCreatureTurn(const Creature* creature) {} virtual void onCreatureSay(const Creature* creature, SpeakClasses type, const std::string& text, Position* pos = NULL) {} virtual void onCreatureChangeOutfit(const Creature* creature, const Outfit_t& outfit) {} virtual void onCreatureConvinced(const Creature* convincer, const Creature* creature) {} virtual void onCreatureChangeVisible(const Creature* creature, Visible_t visible) {} virtual void onPlacedCreature() {} virtual void onRemovedCreature(); virtual WeaponType_t getWeaponType() {return WEAPON_NONE;} virtual bool getCombatValues(int32_t& min, int32_t& max) {return false;} virtual void setSkull(Skulls_t newSkull) {skull = newSkull;} virtual Skulls_t getSkull() const {return skull;} virtual Skulls_t getSkullClient(const Creature* creature) const {return creature->getSkull();} virtual void setShield(PartyShields_t newPartyShield) {partyShield = newPartyShield;} virtual PartyShields_t getShield() const {return partyShield;} virtual PartyShields_t getPartyShield(const Creature* creature) const {return creature->getShield();} virtual void setEmblem(GuildEmblems_t newGuildEmblem) {guildEmblem = newGuildEmblem;} virtual GuildEmblems_t getEmblem() const {return guildEmblem;} virtual GuildEmblems_t getGuildEmblem(const Creature* creature) const {return creature->getEmblem();} void setDropLoot(lootDrop_t _lootDrop) {lootDrop = _lootDrop;} void setLossSkill(bool _skillLoss) {skillLoss = _skillLoss;} bool getLossSkill() const {return skillLoss;} void setNoMove(bool _cannotMove) {cannotMove = _cannotMove;} bool getNoMove() const {return cannotMove;} //creature script events bool registerCreatureEvent(const std::string& name); CreatureEventList getCreatureEvents(CreatureEventType_t type); virtual void setParent(Cylinder* cylinder) { _tile = dynamic_cast(cylinder); Thing::setParent(cylinder); } virtual Position getPosition() const {return _tile->getPosition();} virtual Tile* getTile() {return _tile;} virtual const Tile* getTile() const {return _tile;} int32_t getWalkCache(const Position& pos) const; const Position& getLastPosition() {return lastPosition;} void setLastPosition(Position newLastPos) {lastPosition = newLastPos;} static bool canSee(const Position& myPos, const Position& pos, uint32_t viewRangeX, uint32_t viewRangeY); protected: static const int32_t mapWalkWidth = Map::maxViewportX * 2 + 1; static const int32_t mapWalkHeight = Map::maxViewportY * 2 + 1; bool localMapCache[mapWalkHeight][mapWalkWidth]; virtual bool useCacheMap() const {return false;} Tile* _tile; uint32_t id; bool removed; bool isMapLoaded; bool isUpdatingPath; bool checked; StorageMap storageMap; int32_t checkVector; int32_t health, healthMax; int32_t mana, manaMax; bool hideName, hideHealth, cannotMove; SpeakClasses speakType; Outfit_t currentOutfit; Outfit_t defaultOutfit; Position masterPosition; Position lastPosition; int32_t masterRadius; uint64_t lastStep; uint32_t lastStepCost; uint32_t baseSpeed; int32_t varSpeed; bool skillLoss; lootDrop_t lootDrop; Skulls_t skull; PartyShields_t partyShield; GuildEmblems_t guildEmblem; Direction direction; ConditionList conditions; LightInfo internalLight; //summon variables Creature* master; std::list summons; //follow variables Creature* followCreature; uint32_t eventWalk; std::list listWalkDir; uint32_t walkUpdateTicks; bool hasFollowPath; bool forceUpdateFollowPath; //combat variables Creature* attackedCreature; struct CountBlock_t { uint32_t total; int64_t ticks, start; CountBlock_t(uint32_t points) { start = ticks = OTSYS_TIME(); total = points; } CountBlock_t() {start = ticks = total = 0;} }; typedef std::map CountMap; CountMap damageMap; CountMap healMap; CreatureEventList eventsList; uint32_t scriptEventsBitField, blockCount, blockTicks, lastHitCreature; CombatType_t lastDamageSource; #ifdef __DEBUG__ void validateMapCache(); #endif void updateMapCache(); void updateTileCache(const Tile* tile, int32_t dx, int32_t dy); void updateTileCache(const Tile* tile, const Position& pos); bool hasEventRegistered(CreatureEventType_t event) const {return (0 != (scriptEventsBitField & ((uint32_t)1 << event)));} virtual bool hasExtraSwing() {return false;} virtual uint16_t getLookCorpse() const {return 0;} virtual uint64_t getLostExperience() const {return 0;} virtual double getDamageRatio(Creature* attacker) const; virtual void getPathSearchParams(const Creature* creature, FindPathParams& fpp) const; DeathList getKillers(); virtual Item* createCorpse(DeathList deathList); virtual void dropLoot(Container* corpse) {} virtual void dropCorpse(DeathList deathList); virtual void doAttacking(uint32_t interval) {} void internalCreatureDisappear(const Creature* creature, bool isLogout); friend class Game; friend class Map; friend class LuaScriptInterface; }; #endif