/* * Copyright (C) 2005-2012 MaNGOS * * 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 2 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __UNIT_H #define __UNIT_H #include "Common.h" #include "Object.h" #include "Opcodes.h" #include "SpellAuraDefines.h" #include "UpdateFields.h" #include "SharedDefines.h" #include "ThreatManager.h" #include "HostileRefManager.h" #include "FollowerReference.h" #include "FollowerRefManager.h" #include "Utilities/EventProcessor.h" #include "MotionMaster.h" #include "DBCStructure.h" #include "Path.h" #include "WorldPacket.h" #include "Timer.h" #include enum SpellInterruptFlags { SPELL_INTERRUPT_FLAG_MOVEMENT = 0x01, SPELL_INTERRUPT_FLAG_DAMAGE = 0x02, SPELL_INTERRUPT_FLAG_INTERRUPT = 0x04, SPELL_INTERRUPT_FLAG_AUTOATTACK = 0x08, SPELL_INTERRUPT_FLAG_ABORT_ON_DMG = 0x10, // _complete_ interrupt on direct damage // SPELL_INTERRUPT_UNK = 0x20 // unk, 564 of 727 spells having this spell start with "Glyph" }; enum SpellChannelInterruptFlags { CHANNEL_FLAG_DAMAGE = 0x0002, CHANNEL_FLAG_MOVEMENT = 0x0008, CHANNEL_FLAG_TURNING = 0x0010, CHANNEL_FLAG_DAMAGE2 = 0x0080, CHANNEL_FLAG_DELAY = 0x4000 }; enum SpellAuraInterruptFlags { AURA_INTERRUPT_FLAG_UNK0 = 0x00000001, // 0 removed when getting hit by a negative spell? AURA_INTERRUPT_FLAG_DAMAGE = 0x00000002, // 1 removed by any damage AURA_INTERRUPT_FLAG_UNK2 = 0x00000004, // 2 AURA_INTERRUPT_FLAG_MOVE = 0x00000008, // 3 removed by any movement AURA_INTERRUPT_FLAG_TURNING = 0x00000010, // 4 removed by any turning AURA_INTERRUPT_FLAG_ENTER_COMBAT = 0x00000020, // 5 removed by entering combat AURA_INTERRUPT_FLAG_NOT_MOUNTED = 0x00000040, // 6 removed by unmounting AURA_INTERRUPT_FLAG_NOT_ABOVEWATER = 0x00000080, // 7 removed by entering water AURA_INTERRUPT_FLAG_NOT_UNDERWATER = 0x00000100, // 8 removed by leaving water AURA_INTERRUPT_FLAG_NOT_SHEATHED = 0x00000200, // 9 removed by unsheathing AURA_INTERRUPT_FLAG_UNK10 = 0x00000400, // 10 AURA_INTERRUPT_FLAG_UNK11 = 0x00000800, // 11 AURA_INTERRUPT_FLAG_UNK12 = 0x00001000, // 12 removed by attack? AURA_INTERRUPT_FLAG_UNK13 = 0x00002000, // 13 AURA_INTERRUPT_FLAG_UNK14 = 0x00004000, // 14 AURA_INTERRUPT_FLAG_UNK15 = 0x00008000, // 15 removed by casting a spell? AURA_INTERRUPT_FLAG_UNK16 = 0x00010000, // 16 AURA_INTERRUPT_FLAG_MOUNTING = 0x00020000, // 17 removed by mounting AURA_INTERRUPT_FLAG_NOT_SEATED = 0x00040000, // 18 removed by standing up (used by food and drink mostly and sleep/Fake Death like) AURA_INTERRUPT_FLAG_CHANGE_MAP = 0x00080000, // 19 leaving map/getting teleported AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION = 0x00100000, // 20 removed by auras that make you invulnerable, or make other to loose selection on you AURA_INTERRUPT_FLAG_UNK21 = 0x00200000, // 21 AURA_INTERRUPT_FLAG_UNK22 = 0x00400000, // 22 AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT = 0x00800000, // 23 removed by entering pvp combat AURA_INTERRUPT_FLAG_DIRECT_DAMAGE = 0x01000000, // 24 removed by any direct damage AURA_INTERRUPT_FLAG_UNK25 = 0x02000000, // 25 AURA_INTERRUPT_FLAG_UNK26 = 0x04000000, // 26 AURA_INTERRUPT_FLAG_DAMAGE2 = 0x08000000, // 27 removed by damage spells + removed by damage, other than .. (diseases, Censure) AURA_INTERRUPT_FLAG_ENTER_COMBAT2 = 0x10000000, // 28 AURA_INTERRUPT_FLAG_UNK29 = 0x20000000, // 29 AURA_INTERRUPT_FLAG_UNK30 = 0x40000000, // 30 AURA_INTERRUPT_FLAG_UNK31 = 0x80000000, // 31 }; enum SpellModOp { SPELLMOD_DAMAGE = 0, SPELLMOD_DURATION = 1, SPELLMOD_THREAT = 2, SPELLMOD_EFFECT1 = 3, SPELLMOD_CHARGES = 4, SPELLMOD_RANGE = 5, SPELLMOD_RADIUS = 6, SPELLMOD_CRITICAL_CHANCE = 7, SPELLMOD_ALL_EFFECTS = 8, SPELLMOD_NOT_LOSE_CASTING_TIME = 9, SPELLMOD_CASTING_TIME = 10, SPELLMOD_COOLDOWN = 11, SPELLMOD_EFFECT2 = 12, // spellmod 13 unused SPELLMOD_COST = 14, SPELLMOD_CRIT_DAMAGE_BONUS = 15, SPELLMOD_RESIST_MISS_CHANCE = 16, SPELLMOD_JUMP_TARGETS = 17, SPELLMOD_CHANCE_OF_SUCCESS = 18, // Only used with SPELL_AURA_ADD_FLAT_MODIFIER and affects proc spells SPELLMOD_ACTIVATION_TIME = 19, SPELLMOD_EFFECT_PAST_FIRST = 20, SPELLMOD_GLOBAL_COOLDOWN = 21, SPELLMOD_DOT = 22, SPELLMOD_EFFECT3 = 23, SPELLMOD_SPELL_BONUS_DAMAGE = 24, // spellmod 25 unused SPELLMOD_FREQUENCY_OF_SUCCESS = 26, // Only used with SPELL_AURA_ADD_PCT_MODIFIER and affects used on proc spells SPELLMOD_MULTIPLE_VALUE = 27, SPELLMOD_RESIST_DISPEL_CHANCE = 28 }; #define MAX_SPELLMOD 32 enum SpellFacingFlags { SPELL_FACING_FLAG_INFRONT = 0x0001 }; #define BASE_MELEERANGE_OFFSET 1.33f #define BASE_MINDAMAGE 1.0f #define BASE_MAXDAMAGE 2.0f #define BASE_ATTACK_TIME 2000 // byte value (UNIT_FIELD_BYTES_1,0) enum UnitStandStateType { UNIT_STAND_STATE_STAND = 0, UNIT_STAND_STATE_SIT = 1, UNIT_STAND_STATE_SIT_CHAIR = 2, UNIT_STAND_STATE_SLEEP = 3, UNIT_STAND_STATE_SIT_LOW_CHAIR = 4, UNIT_STAND_STATE_SIT_MEDIUM_CHAIR = 5, UNIT_STAND_STATE_SIT_HIGH_CHAIR = 6, UNIT_STAND_STATE_DEAD = 7, UNIT_STAND_STATE_KNEEL = 8, UNIT_STAND_STATE_CUSTOM = 9 // Depends on model animation. Submerge, freeze, hide, hibernate, rest }; #define MAX_UNIT_STAND_STATE 10 // byte flags value (UNIT_FIELD_BYTES_1,1) // This corresponds to free talent points (pet case) // byte flags value (UNIT_FIELD_BYTES_1,2) enum UnitStandFlags { UNIT_STAND_FLAGS_UNK1 = 0x01, UNIT_STAND_FLAGS_CREEP = 0x02, UNIT_STAND_FLAGS_UNK3 = 0x04, UNIT_STAND_FLAGS_UNK4 = 0x08, UNIT_STAND_FLAGS_UNK5 = 0x10, UNIT_STAND_FLAGS_ALL = 0xFF }; // byte flags value (UNIT_FIELD_BYTES_1,3) enum UnitBytes1_Flags { UNIT_BYTE1_FLAG_ALWAYS_STAND = 0x01, UNIT_BYTE1_FLAG_UNK_2 = 0x02, // Creature that can fly and are not on the ground appear to have this flag. If they are on the ground, flag is not present. UNIT_BYTE1_FLAG_UNTRACKABLE = 0x04, UNIT_BYTE1_FLAG_ALL = 0xFF }; // byte value (UNIT_FIELD_BYTES_2,0) enum SheathState { SHEATH_STATE_UNARMED = 0, // non prepared weapon SHEATH_STATE_MELEE = 1, // prepared melee weapon SHEATH_STATE_RANGED = 2 // prepared ranged weapon }; #define MAX_SHEATH_STATE 3 // byte flags value (UNIT_FIELD_BYTES_2,1) enum UnitPVPStateFlags { UNIT_BYTE2_FLAG_PVP = 0x01, UNIT_BYTE2_FLAG_UNK1 = 0x02, UNIT_BYTE2_FLAG_FFA_PVP = 0x04, UNIT_BYTE2_FLAG_SANCTUARY = 0x08, UNIT_BYTE2_FLAG_UNK4 = 0x10, UNIT_BYTE2_FLAG_UNK5 = 0x20, UNIT_BYTE2_FLAG_UNK6 = 0x40, UNIT_BYTE2_FLAG_UNK7 = 0x80 }; // byte flags value (UNIT_FIELD_BYTES_2,2) enum UnitRename { UNIT_CAN_BE_RENAMED = 0x01, UNIT_CAN_BE_ABANDONED = 0x02, }; // byte flags value (UNIT_FIELD_BYTES_2,3) See enum ShapeshiftForm in SharedDefines.h #define CREATURE_MAX_SPELLS 4 enum Swing { NOSWING = 0, SINGLEHANDEDSWING = 1, TWOHANDEDSWING = 2 }; enum VictimState { VICTIMSTATE_UNAFFECTED = 0, // seen in relation with HITINFO_MISS VICTIMSTATE_NORMAL = 1, VICTIMSTATE_DODGE = 2, VICTIMSTATE_PARRY = 3, VICTIMSTATE_INTERRUPT = 4, VICTIMSTATE_BLOCKS = 5, VICTIMSTATE_EVADES = 6, VICTIMSTATE_IS_IMMUNE = 7, VICTIMSTATE_DEFLECTS = 8 }; enum HitInfo { HITINFO_NORMALSWING = 0x00000000, HITINFO_UNK0 = 0x00000001, // req correct packet structure HITINFO_NORMALSWING2 = 0x00000002, HITINFO_LEFTSWING = 0x00000004, HITINFO_UNK3 = 0x00000008, HITINFO_MISS = 0x00000010, HITINFO_ABSORB = 0x00000020, // absorbed damage HITINFO_ABSORB2 = 0x00000040, // absorbed damage HITINFO_RESIST = 0x00000080, // resisted atleast some damage HITINFO_RESIST2 = 0x00000100, // resisted atleast some damage HITINFO_CRITICALHIT = 0x00000200, // critical hit // 0x00000400 // 0x00000800 // 0x00001000 HITINFO_BLOCK = 0x00002000, // blocked damage // 0x00004000 // 0x00008000 HITINFO_GLANCING = 0x00010000, HITINFO_CRUSHING = 0x00020000, HITINFO_NOACTION = 0x00040000, // guessed // 0x00080000 // 0x00100000 HITINFO_SWINGNOHITSOUND = 0x00200000, // guessed // 0x00400000 HITINFO_UNK22 = 0x00800000 }; // i would like to remove this: (it is defined in item.h enum InventorySlot { NULL_BAG = 0, NULL_SLOT = 255 }; struct FactionTemplateEntry; struct Modifier; struct SpellEntry; struct SpellEntryExt; class Aura; class SpellAuraHolder; class Creature; class Spell; class DynamicObject; class GameObject; class Item; class Pet; class PetAura; class Totem; class VehicleInfo; struct SpellImmune { uint32 type; uint32 spellId; }; typedef std::list SpellImmuneList; enum UnitModifierType { BASE_VALUE = 0, BASE_PCT = 1, TOTAL_VALUE = 2, TOTAL_PCT = 3, MODIFIER_TYPE_END = 4 }; enum WeaponDamageRange { MINDAMAGE, MAXDAMAGE }; enum DamageTypeToSchool { RESISTANCE, DAMAGE_DEALT, DAMAGE_TAKEN }; enum AuraRemoveMode { AURA_REMOVE_BY_DEFAULT, AURA_REMOVE_BY_STACK, // at replace by similar aura AURA_REMOVE_BY_CANCEL, AURA_REMOVE_BY_DISPEL, AURA_REMOVE_BY_DEATH, AURA_REMOVE_BY_DELETE, // use for speedup and prevent unexpected effects at player logout/pet unsummon (must be used _only_ after save), delete. AURA_REMOVE_BY_SHIELD_BREAK, // when absorb shield is removed by damage, heal absorb debuf AURA_REMOVE_BY_EXPIRE, // at duration end }; enum UnitMods { UNIT_MOD_STAT_STRENGTH, // UNIT_MOD_STAT_STRENGTH..UNIT_MOD_STAT_SPIRIT must be in existing order, it's accessed by index values of Stats enum. UNIT_MOD_STAT_AGILITY, UNIT_MOD_STAT_STAMINA, UNIT_MOD_STAT_INTELLECT, UNIT_MOD_STAT_SPIRIT, UNIT_MOD_HEALTH, UNIT_MOD_MANA, // UNIT_MOD_MANA..UNIT_MOD_RUNIC_POWER must be in existing order, it's accessed by index values of Powers enum. UNIT_MOD_RAGE, UNIT_MOD_FOCUS, UNIT_MOD_ENERGY, UNIT_MOD_HAPPINESS, // REQUIRED for fast indexing to work. UNIT_MOD_RUNE, UNIT_MOD_RUNIC_POWER, UNIT_MOD_SOUL_SHARDS, UNIT_MOD_ECLIPSE, UNIT_MOD_HOLY_POWER, UNIT_MOD_ALTERNATIVE, UNIT_MOD_ARMOR, // UNIT_MOD_ARMOR..UNIT_MOD_RESISTANCE_ARCANE must be in existing order, it's accessed by index values of SpellSchools enum. UNIT_MOD_RESISTANCE_HOLY, UNIT_MOD_RESISTANCE_FIRE, UNIT_MOD_RESISTANCE_NATURE, UNIT_MOD_RESISTANCE_FROST, UNIT_MOD_RESISTANCE_SHADOW, UNIT_MOD_RESISTANCE_ARCANE, UNIT_MOD_ATTACK_POWER, UNIT_MOD_ATTACK_POWER_RANGED, UNIT_MOD_DAMAGE_MAINHAND, UNIT_MOD_DAMAGE_OFFHAND, UNIT_MOD_DAMAGE_RANGED, UNIT_MOD_END, // synonyms UNIT_MOD_STAT_START = UNIT_MOD_STAT_STRENGTH, UNIT_MOD_STAT_END = UNIT_MOD_STAT_SPIRIT + 1, UNIT_MOD_RESISTANCE_START = UNIT_MOD_ARMOR, UNIT_MOD_RESISTANCE_END = UNIT_MOD_RESISTANCE_ARCANE + 1, UNIT_MOD_POWER_START = UNIT_MOD_MANA, UNIT_MOD_POWER_END = UNIT_MOD_ALTERNATIVE + 1 }; static_assert(UNIT_MOD_POWER_END - UNIT_MOD_POWER_START == MAX_POWERS, "Power-related UnitMods are not updated."); enum BaseModGroup { CRIT_PERCENTAGE, RANGED_CRIT_PERCENTAGE, OFFHAND_CRIT_PERCENTAGE, SHIELD_BLOCK_VALUE, BASEMOD_END }; enum BaseModType { FLAT_MOD, PCT_MOD }; #define MOD_END (PCT_MOD+1) enum DeathState { ALIVE = 0, // show as alive JUST_DIED = 1, // temporary state at die, for creature auto converted to CORPSE, for player at next update call CORPSE = 2, // corpse state, for player this also meaning that player not leave corpse DEAD = 3, // for creature despawned state (corpse despawned), for player CORPSE/DEAD not clear way switches (FIXME), and use m_deathtimer > 0 check for real corpse state JUST_ALIVED = 4, // temporary state at resurrection, for creature auto converted to ALIVE, for player at next update call }; // internal state flags for some auras and movement generators, other. enum UnitState { // persistent state (applied by aura/etc until expire) UNIT_STAT_MELEE_ATTACKING = 0x00000001, // unit is melee attacking someone Unit::Attack UNIT_STAT_ATTACK_PLAYER = 0x00000002, // unit attack player or player's controlled unit and have contested pvpv timer setup, until timer expire, combat end and etc UNIT_STAT_DIED = 0x00000004, // Unit::SetFeignDeath UNIT_STAT_STUNNED = 0x00000008, // Aura::HandleAuraModStun UNIT_STAT_ROOT = 0x00000010, // Aura::HandleAuraModRoot UNIT_STAT_ISOLATED = 0x00000020, // area auras do not affect other players, Aura::HandleAuraModSchoolImmunity UNIT_STAT_CONTROLLED = 0x00000040, // Aura::HandleAuraModPossess // persistent movement generator state (all time while movement generator applied to unit (independent from top state of movegen) UNIT_STAT_TAXI_FLIGHT = 0x00000080, // player is in flight mode (in fact interrupted at far teleport until next map telport landing) UNIT_STAT_DISTRACTED = 0x00000100, // DistractedMovementGenerator active // persistent movement generator state with non-persistent mirror states for stop support // (can be removed temporary by stop command or another movement generator apply) // not use _MOVE versions for generic movegen state, it can be removed temporary for unit stop and etc UNIT_STAT_CONFUSED = 0x00000200, // ConfusedMovementGenerator active/onstack UNIT_STAT_CONFUSED_MOVE = 0x00000400, UNIT_STAT_ROAMING = 0x00000800, // RandomMovementGenerator/PointMovementGenerator/WaypointMovementGenerator active (now always set) UNIT_STAT_ROAMING_MOVE = 0x00001000, UNIT_STAT_CHASE = 0x00002000, // ChaseMovementGenerator active UNIT_STAT_CHASE_MOVE = 0x00004000, UNIT_STAT_FOLLOW = 0x00008000, // FollowMovementGenerator active UNIT_STAT_FOLLOW_MOVE = 0x00010000, UNIT_STAT_FLEEING = 0x00020000, // FleeMovementGenerator/TimedFleeingMovementGenerator active/onstack UNIT_STAT_FLEEING_MOVE = 0x00040000, UNIT_STAT_IGNORE_PATHFINDING = 0x00080000, // do not use pathfinding in any MovementGenerator // masks (only for check) // can't move currently UNIT_STAT_CAN_NOT_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED, // stay by different reasons UNIT_STAT_NOT_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED | UNIT_STAT_DISTRACTED, // stay or scripted movement for effect( = in player case you can't move by client command) UNIT_STAT_NO_FREE_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED | UNIT_STAT_TAXI_FLIGHT | UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING, // not react at move in sight or other UNIT_STAT_CAN_NOT_REACT = UNIT_STAT_STUNNED | UNIT_STAT_DIED | UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING, // AI disabled by some reason UNIT_STAT_LOST_CONTROL = UNIT_STAT_FLEEING | UNIT_STAT_CONTROLLED, // above 2 state cases UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL = UNIT_STAT_CAN_NOT_REACT | UNIT_STAT_LOST_CONTROL, // masks (for check or reset) // for real move using movegen check and stop (except unstoppable flight) UNIT_STAT_MOVING = UNIT_STAT_ROAMING_MOVE | UNIT_STAT_CHASE_MOVE | UNIT_STAT_FOLLOW_MOVE | UNIT_STAT_FLEEING_MOVE, UNIT_STAT_ALL_STATE = 0xFFFFFFFF }; enum UnitMoveType { MOVE_WALK = 0, MOVE_RUN = 1, MOVE_RUN_BACK = 2, MOVE_SWIM = 3, MOVE_SWIM_BACK = 4, MOVE_TURN_RATE = 5, MOVE_FLIGHT = 6, MOVE_FLIGHT_BACK = 7, MOVE_PITCH_RATE = 8 }; #define MAX_MOVE_TYPE 9 extern float baseMoveSpeed[MAX_MOVE_TYPE]; enum CombatRating { CR_WEAPON_SKILL = 0, CR_DEFENSE_SKILL = 1, CR_DODGE = 2, CR_PARRY = 3, CR_BLOCK = 4, CR_HIT_MELEE = 5, CR_HIT_RANGED = 6, CR_HIT_SPELL = 7, CR_CRIT_MELEE = 8, CR_CRIT_RANGED = 9, CR_CRIT_SPELL = 10, CR_HIT_TAKEN_MELEE = 11, // obsolete CR_HIT_TAKEN_RANGED = 12, // obsolete CR_HIT_TAKEN_SPELL = 13, // obsolete CR_CRIT_TAKEN_MELEE = 14, // COMBAT_RATING_RESILIENCE_CRIT_TAKEN obsolete CR_RESILIENCE_DAMAGE_TAKEN = 15, // old CR_CRIT_TAKEN_RANGED CR_CRIT_TAKEN_SPELL = 16, // obsolete CR_HASTE_MELEE = 17, CR_HASTE_RANGED = 18, CR_HASTE_SPELL = 19, CR_WEAPON_SKILL_MAINHAND = 20, // obsolete CR_WEAPON_SKILL_OFFHAND = 21, // obsolete CR_WEAPON_SKILL_RANGED = 22, // obsolete CR_EXPERTISE = 23, CR_ARMOR_PENETRATION = 24, CR_MASTERY = 25 }; #define MAX_COMBAT_RATING 26 /// internal used flags for marking special auras - for example some dummy-auras enum UnitAuraFlags { UNIT_AURAFLAG_ALIVE_INVISIBLE = 0x1, // aura which makes unit invisible for alive }; enum UnitVisibility { VISIBILITY_OFF = 0, // absolute, not detectable, GM-like, can see all other VISIBILITY_ON = 1, VISIBILITY_GROUP_STEALTH = 2, // detect chance, seen and can see group members VISIBILITY_GROUP_INVISIBILITY = 3, // invisibility, can see and can be seen only another invisible unit or invisible detection unit, set only if not stealthed, and in checks not used (mask used instead) VISIBILITY_GROUP_NO_DETECT = 4, // state just at stealth apply for update Grid state. Don't remove, otherwise stealth spells will break VISIBILITY_RESPAWN = 5 // special totally not detectable visibility for force delete object at respawn command }; // Value masks for UNIT_FIELD_FLAGS enum UnitFlags { UNIT_FLAG_UNK_0 = 0x00000001, UNIT_FLAG_NON_ATTACKABLE = 0x00000002, // not attackable UNIT_FLAG_DISABLE_MOVE = 0x00000004, UNIT_FLAG_PVP_ATTACKABLE = 0x00000008, // allow apply pvp rules to attackable state in addition to faction dependent state UNIT_FLAG_RENAME = 0x00000010, UNIT_FLAG_PREPARATION = 0x00000020, // don't take reagents for spells with SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP UNIT_FLAG_UNK_6 = 0x00000040, UNIT_FLAG_NOT_ATTACKABLE_1 = 0x00000080, // ?? (UNIT_FLAG_PVP_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1) is NON_PVP_ATTACKABLE UNIT_FLAG_OOC_NOT_ATTACKABLE = 0x00000100, // 2.0.8 - (OOC Out Of Combat) Can not be attacked when not in combat. Removed if unit for some reason enter combat (flag probably removed for the attacked and it's party/group only) UNIT_FLAG_PASSIVE = 0x00000200, // makes you unable to attack everything. Almost identical to our "civilian"-term. Will ignore it's surroundings and not engage in combat unless "called upon" or engaged by another unit. UNIT_FLAG_LOOTING = 0x00000400, // loot animation UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // in combat?, 2.0.8 UNIT_FLAG_PVP = 0x00001000, // changed in 3.0.3 UNIT_FLAG_SILENCED = 0x00002000, // silenced, 2.1.1 UNIT_FLAG_UNK_14 = 0x00004000, // 2.0.8 UNIT_FLAG_UNK_15 = 0x00008000, UNIT_FLAG_UNK_16 = 0x00010000, // removes attackable icon UNIT_FLAG_PACIFIED = 0x00020000, // 3.0.3 ok UNIT_FLAG_STUNNED = 0x00040000, // 3.0.3 ok UNIT_FLAG_IN_COMBAT = 0x00080000, UNIT_FLAG_TAXI_FLIGHT = 0x00100000, // disable casting at client side spell not allowed by taxi flight (mounted?), probably used with 0x4 flag UNIT_FLAG_DISARMED = 0x00200000, // 3.0.3, disable melee spells casting..., "Required melee weapon" added to melee spells tooltip. UNIT_FLAG_CONFUSED = 0x00400000, UNIT_FLAG_FLEEING = 0x00800000, UNIT_FLAG_PLAYER_CONTROLLED = 0x01000000, // used in spell Eyes of the Beast for pet... let attack by controlled creature UNIT_FLAG_NOT_SELECTABLE = 0x02000000, UNIT_FLAG_SKINNABLE = 0x04000000, UNIT_FLAG_MOUNT = 0x08000000, UNIT_FLAG_UNK_28 = 0x10000000, UNIT_FLAG_UNK_29 = 0x20000000, // used in Feing Death spell UNIT_FLAG_SHEATHE = 0x40000000, UNIT_FLAG_UNK_31 = 0x80000000 // set skinnable icon and also changes color of portrait }; // Value masks for UNIT_FIELD_FLAGS_2 enum UnitFlags2 { UNIT_FLAG2_FEIGN_DEATH = 0x00000001, UNIT_FLAG2_UNK1 = 0x00000002, // Hides body and body armor. Weapons and shoulder and head armor still visible UNIT_FLAG2_UNK2 = 0x00000004, UNIT_FLAG2_COMPREHEND_LANG = 0x00000008, UNIT_FLAG2_CLONED = 0x00000010, // Used in SPELL_AURA_MIRROR_IMAGE UNIT_FLAG2_UNK5 = 0x00000020, UNIT_FLAG2_FORCE_MOVE = 0x00000040, UNIT_FLAG2_DISARM_OFFHAND = 0x00000080, // also shield case UNIT_FLAG2_UNK8 = 0x00000100, UNIT_FLAG2_UNK9 = 0x00000200, UNIT_FLAG2_DISARM_RANGED = 0x00000400, UNIT_FLAG2_REGENERATE_POWER = 0x00000800, UNIT_FLAG2_WORGEN_TRANSFORM = 0x00080000, // transform to worgen UNIT_FLAG2_WORGEN_TRANSFORM2 = 0x00100000, // transform to worgen, but less animation? UNIT_FLAG2_WORGEN_TRANSFORM3 = 0x00200000 // transform to worgen, but less animation? }; /// Non Player Character flags enum NPCFlags { UNIT_NPC_FLAG_NONE = 0x00000000, UNIT_NPC_FLAG_GOSSIP = 0x00000001, // 100% UNIT_NPC_FLAG_QUESTGIVER = 0x00000002, // guessed, probably ok UNIT_NPC_FLAG_UNK1 = 0x00000004, UNIT_NPC_FLAG_UNK2 = 0x00000008, UNIT_NPC_FLAG_TRAINER = 0x00000010, // 100% UNIT_NPC_FLAG_TRAINER_CLASS = 0x00000020, // 100% UNIT_NPC_FLAG_TRAINER_PROFESSION = 0x00000040, // 100% UNIT_NPC_FLAG_VENDOR = 0x00000080, // 100% UNIT_NPC_FLAG_VENDOR_AMMO = 0x00000100, // 100%, general goods vendor UNIT_NPC_FLAG_VENDOR_FOOD = 0x00000200, // 100% UNIT_NPC_FLAG_VENDOR_POISON = 0x00000400, // guessed UNIT_NPC_FLAG_VENDOR_REAGENT = 0x00000800, // 100% UNIT_NPC_FLAG_REPAIR = 0x00001000, // 100% UNIT_NPC_FLAG_FLIGHTMASTER = 0x00002000, // 100% UNIT_NPC_FLAG_SPIRITHEALER = 0x00004000, // guessed UNIT_NPC_FLAG_SPIRITGUIDE = 0x00008000, // guessed UNIT_NPC_FLAG_INNKEEPER = 0x00010000, // 100% UNIT_NPC_FLAG_BANKER = 0x00020000, // 100% UNIT_NPC_FLAG_PETITIONER = 0x00040000, // 100% 0xC0000 = guild petitions, 0x40000 = arena team petitions UNIT_NPC_FLAG_TABARDDESIGNER = 0x00080000, // 100% UNIT_NPC_FLAG_BATTLEMASTER = 0x00100000, // 100% UNIT_NPC_FLAG_AUCTIONEER = 0x00200000, // 100% UNIT_NPC_FLAG_STABLEMASTER = 0x00400000, // 100% UNIT_NPC_FLAG_GUILD_BANKER = 0x00800000, // cause client to send 997 opcode UNIT_NPC_FLAG_SPELLCLICK = 0x01000000, // cause client to send 1015 opcode (spell click), dynamic, set at loading and don't must be set in DB }; // used in most movement packets (send and received), 30 bits in client enum MovementFlags { MOVEFLAG_NONE = 0x00000000, MOVEFLAG_FORWARD = 0x00000001, MOVEFLAG_BACKWARD = 0x00000002, MOVEFLAG_STRAFE_LEFT = 0x00000004, MOVEFLAG_STRAFE_RIGHT = 0x00000008, MOVEFLAG_TURN_LEFT = 0x00000010, MOVEFLAG_TURN_RIGHT = 0x00000020, MOVEFLAG_PITCH_UP = 0x00000040, MOVEFLAG_PITCH_DOWN = 0x00000080, MOVEFLAG_WALK_MODE = 0x00000100, // Walking MOVEFLAG_LEVITATING = 0x00000200, MOVEFLAG_ROOT = 0x00000400, MOVEFLAG_FALLING = 0x00000800, MOVEFLAG_FALLINGFAR = 0x00001000, MOVEFLAG_PENDINGSTOP = 0x00002000, MOVEFLAG_PENDINGSTRAFESTOP = 0x00004000, MOVEFLAG_PENDINGFORWARD = 0x00008000, MOVEFLAG_PENDINGBACKWARD = 0x00010000, MOVEFLAG_PENDINGSTRAFELEFT = 0x00020000, MOVEFLAG_PENDINGSTRAFERIGHT = 0x00040000, MOVEFLAG_PENDINGROOT = 0x00080000, MOVEFLAG_SWIMMING = 0x00100000, // appears with fly flag also MOVEFLAG_ASCENDING = 0x00200000, // swim up also MOVEFLAG_DESCENDING = 0x00400000, // swim down also MOVEFLAG_CAN_FLY = 0x00800000, // can fly in 3.3? MOVEFLAG_FLYING = 0x01000000, // Actual flying mode MOVEFLAG_SPLINE_ELEVATION = 0x02000000, // used for flight paths MOVEFLAG_WATERWALKING = 0x04000000, // prevent unit from falling through water MOVEFLAG_SAFE_FALL = 0x08000000, // active rogue safe fall spell (passive) MOVEFLAG_HOVER = 0x10000000, MOVEFLAG_LOCAL_DIRTY = 0x20000000, }; // flags that use in movement check for example at spell casting MovementFlags const movementFlagsMask = MovementFlags( MOVEFLAG_FORWARD | MOVEFLAG_BACKWARD | MOVEFLAG_STRAFE_LEFT | MOVEFLAG_STRAFE_RIGHT | MOVEFLAG_PITCH_UP | MOVEFLAG_PITCH_DOWN | MOVEFLAG_ROOT | MOVEFLAG_FALLING | MOVEFLAG_FALLINGFAR | MOVEFLAG_ASCENDING | MOVEFLAG_FLYING | MOVEFLAG_SPLINE_ELEVATION ); MovementFlags const movementOrTurningFlagsMask = MovementFlags( movementFlagsMask | MOVEFLAG_TURN_LEFT | MOVEFLAG_TURN_RIGHT ); // 12 bits in client enum MovementFlags2 { MOVEFLAG2_NONE = 0x0000, MOVEFLAG2_NO_STRAFE = 0x0001, MOVEFLAG2_NO_JUMPING = 0x0002, MOVEFLAG2_FULLSPEEDTURNING = 0x0004, MOVEFLAG2_FULLSPEEDPITCHING = 0x0008, MOVEFLAG2_ALLOW_PITCHING = 0x0010, MOVEFLAG2_UNK4 = 0x0020, MOVEFLAG2_UNK5 = 0x0040, MOVEFLAG2_UNK6 = 0x0080, // transport related MOVEFLAG2_UNK7 = 0x0100, MOVEFLAG2_INTERP_MOVEMENT = 0x0200, MOVEFLAG2_INTERP_TURNING = 0x0400, MOVEFLAG2_INTERP_PITCHING = 0x0800, MOVEFLAG2_INTERP_MASK = MOVEFLAG2_INTERP_MOVEMENT | MOVEFLAG2_INTERP_TURNING | MOVEFLAG2_INTERP_PITCHING }; class MovementInfo { public: MovementInfo() : moveFlags(MOVEFLAG_NONE), moveFlags2(MOVEFLAG2_NONE), time(0), t_time(0), t_seat(-1), t_time2(0), s_pitch(0.0f), fallTime(0), splineElevation(0.0f) {} // Read/Write methods void Read(ByteBuffer& data, uint16 opcode); void Write(ByteBuffer& data, uint16 opcode) const; // Movement flags manipulations void AddMovementFlag(MovementFlags f) { moveFlags |= f; } void RemoveMovementFlag(MovementFlags f) { moveFlags &= ~f; } bool HasMovementFlag(MovementFlags f) const { return moveFlags & f; } bool HasMovementFlag2(MovementFlags2 f) const { return moveFlags2 & f; } MovementFlags GetMovementFlags() const { return MovementFlags(moveFlags); } void SetMovementFlags(MovementFlags f) { moveFlags = f; } MovementFlags2 GetMovementFlags2() const { return MovementFlags2(moveFlags2); } // Position manipulations Position const* GetPos() const { return &pos; } void SetTransportData(ObjectGuid guid, float x, float y, float z, float o, uint32 time, int8 seat) { t_guid = guid; t_pos.x = x; t_pos.y = y; t_pos.z = z; t_pos.o = o; t_time = time; t_seat = seat; } void ClearTransportData() { t_guid = ObjectGuid(); t_pos.x = 0.0f; t_pos.y = 0.0f; t_pos.z = 0.0f; t_pos.o = 0.0f; t_time = 0; t_seat = -1; } ObjectGuid const& GetGuid() const { return guid; } ObjectGuid const& GetTransportGuid() const { return t_guid; } Position const* GetTransportPos() const { return &t_pos; } int8 GetTransportSeat() const { return t_seat; } uint32 GetTransportTime() const { return t_time; } uint32 GetTransportTime2() const { return t_time2; } uint32 GetFallTime() const { return fallTime; } void ChangeOrientation(float o) { pos.o = o; } void ChangePosition(float x, float y, float z, float o) { pos.x = x; pos.y = y; pos.z = z; pos.o = o; } void UpdateTime(uint32 _time) { time = _time; } struct JumpInfo { JumpInfo() : velocity(0.f), sinAngle(0.f), cosAngle(0.f), xyspeed(0.f) {} float velocity, sinAngle, cosAngle, xyspeed; }; // used only for SMSG_PLAYER_MOVE currently struct StatusInfo { StatusInfo() : hasFallData(false), hasFallDirection(false), hasOrientation(false), hasPitch(false), hasSpline(false), hasSplineElevation(false), hasTimeStamp(false), hasTransportTime2(false), hasTransportTime3(false) { } bool hasFallData : 1; bool hasFallDirection : 1; bool hasOrientation : 1; bool hasPitch : 1; bool hasSpline : 1; bool hasSplineElevation : 1; bool hasTimeStamp : 1; bool hasTransportTime2 : 1; bool hasTransportTime3 : 1; }; JumpInfo const& GetJumpInfo() const { return jump; } StatusInfo const& GetStatusInfo() const { return si; } float GetSplineElevation() const { return splineElevation; } float GetPitch() const { return s_pitch; } private: // common ObjectGuid guid; uint32 moveFlags; // see enum MovementFlags uint16 moveFlags2; // see enum MovementFlags2 uint32 time; Position pos; // transport ObjectGuid t_guid; Position t_pos; uint32 t_time; int8 t_seat; uint32 t_time2; // swimming and flying float s_pitch; // last fall time uint32 fallTime; // jumping JumpInfo jump; // spline float splineElevation; // status info StatusInfo si; }; inline WorldPacket& operator<< (WorldPacket& buf, MovementInfo const& mi) { mi.Write(buf, buf.GetOpcode()); return buf; } inline WorldPacket& operator>> (WorldPacket& buf, MovementInfo& mi) { mi.Read(buf, buf.GetOpcode()); return buf; } namespace Movement { class MoveSpline; } enum DiminishingLevels { DIMINISHING_LEVEL_1 = 0, DIMINISHING_LEVEL_2 = 1, DIMINISHING_LEVEL_3 = 2, DIMINISHING_LEVEL_IMMUNE = 3 }; struct DiminishingReturn { DiminishingReturn(DiminishingGroup group, uint32 t, uint32 count) : DRGroup(group), stack(0), hitTime(t), hitCount(count) {} DiminishingGroup DRGroup: 16; uint16 stack: 16; uint32 hitTime; uint32 hitCount; }; // At least some values expected fixed and used in auras field, other custom enum MeleeHitOutcome { MELEE_HIT_EVADE = 0, MELEE_HIT_MISS = 1, MELEE_HIT_DODGE = 2, // used as misc in SPELL_AURA_IGNORE_COMBAT_RESULT MELEE_HIT_BLOCK = 3, // used as misc in SPELL_AURA_IGNORE_COMBAT_RESULT MELEE_HIT_PARRY = 4, // used as misc in SPELL_AURA_IGNORE_COMBAT_RESULT MELEE_HIT_GLANCING = 5, MELEE_HIT_CRIT = 6, MELEE_HIT_CRUSHING = 7, MELEE_HIT_NORMAL = 8, }; struct CleanDamage { CleanDamage(uint32 _damage, WeaponAttackType _attackType, MeleeHitOutcome _hitOutCome) : damage(_damage), attackType(_attackType), hitOutCome(_hitOutCome) {} uint32 damage; WeaponAttackType attackType; MeleeHitOutcome hitOutCome; }; // Struct for use in Unit::CalculateMeleeDamage // Need create structure like in SMSG_ATTACKERSTATEUPDATE opcode struct CalcDamageInfo { Unit* attacker; // Attacker Unit* target; // Target for damage SpellSchoolMask damageSchoolMask; uint32 damage; uint32 absorb; uint32 resist; uint32 blocked_amount; uint32 HitInfo; uint32 TargetState; // Helper WeaponAttackType attackType; // uint32 procAttacker; uint32 procVictim; uint32 procEx; uint32 cleanDamage; // Used only for rage calculation MeleeHitOutcome hitOutCome; // TODO: remove this field (need use TargetState) }; // Spell damage info structure based on structure sending in SMSG_SPELLNONMELEEDAMAGELOG opcode struct SpellNonMeleeDamage { SpellNonMeleeDamage(Unit* _attacker, Unit* _target, uint32 _SpellID, SpellSchoolMask _schoolMask) : target(_target), attacker(_attacker), SpellID(_SpellID), damage(0), schoolMask(_schoolMask), absorb(0), resist(0), physicalLog(false), unused(false), blocked(0), HitInfo(0) {} Unit* target; Unit* attacker; uint32 SpellID; uint32 damage; SpellSchoolMask schoolMask; uint32 absorb; uint32 resist; bool physicalLog; bool unused; uint32 blocked; uint32 HitInfo; }; struct SpellPeriodicAuraLogInfo { SpellPeriodicAuraLogInfo(Aura* _aura, uint32 _damage, uint32 _overDamage, uint32 _absorb, uint32 _resist, float _multiplier, bool _critical = false) : aura(_aura), damage(_damage), overDamage(_overDamage), absorb(_absorb), resist(_resist), multiplier(_multiplier), critical(_critical) {} Aura* aura; uint32 damage; uint32 overDamage; // overkill/overheal uint32 absorb; uint32 resist; float multiplier; bool critical; }; uint32 createProcExtendMask(SpellNonMeleeDamage* damageInfo, SpellMissInfo missCondition); enum SpellAuraProcResult { SPELL_AURA_PROC_OK = 0, // proc was processed, will remove charges SPELL_AURA_PROC_FAILED = 1, // proc failed - if at least one aura failed the proc, charges won't be taken SPELL_AURA_PROC_CANT_TRIGGER = 2 // aura can't trigger - skip charges taking, move to next aura if exists }; typedef SpellAuraProcResult(Unit::*pAuraProcHandler)(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); extern pAuraProcHandler AuraProcHandler[TOTAL_AURAS]; #define MAX_DECLINED_NAME_CASES 5 struct DeclinedName { std::string name[MAX_DECLINED_NAME_CASES]; }; enum CurrentSpellTypes { CURRENT_MELEE_SPELL = 0, CURRENT_GENERIC_SPELL = 1, CURRENT_AUTOREPEAT_SPELL = 2, CURRENT_CHANNELED_SPELL = 3 }; #define CURRENT_FIRST_NON_MELEE_SPELL 1 #define CURRENT_MAX_SPELL 4 struct GlobalCooldown { explicit GlobalCooldown(uint32 _dur = 0, uint32 _time = 0) : duration(_dur), cast_time(_time) {} uint32 duration; uint32 cast_time; }; typedef UNORDERED_MAP < uint32 /*category*/, GlobalCooldown > GlobalCooldownList; class GlobalCooldownMgr // Shared by Player and CharmInfo { public: GlobalCooldownMgr() {} public: bool HasGlobalCooldown(SpellEntry const* spellInfo) const; void AddGlobalCooldown(SpellEntry const* spellInfo, uint32 gcd); void CancelGlobalCooldown(SpellEntry const* spellInfo); private: GlobalCooldownList m_GlobalCooldowns; }; enum ActiveStates { ACT_PASSIVE = 0x01, // 0x01 - passive ACT_DISABLED = 0x81, // 0x80 - castable ACT_ENABLED = 0xC1, // 0x40 | 0x80 - auto cast + castable ACT_COMMAND = 0x07, // 0x01 | 0x02 | 0x04 ACT_REACTION = 0x06, // 0x02 | 0x04 ACT_DECIDE = 0x00 // custom }; enum ReactStates { REACT_PASSIVE = 0, REACT_DEFENSIVE = 1, REACT_AGGRESSIVE = 2 }; enum CommandStates { COMMAND_STAY = 0, COMMAND_FOLLOW = 1, COMMAND_ATTACK = 2, COMMAND_ABANDON = 3 }; #define UNIT_ACTION_BUTTON_ACTION(X) (uint32(X) & 0x00FFFFFF) #define UNIT_ACTION_BUTTON_TYPE(X) ((uint32(X) & 0xFF000000) >> 24) #define MAX_UNIT_ACTION_BUTTON_ACTION_VALUE (0x00FFFFFF+1) #define MAKE_UNIT_ACTION_BUTTON(A,T) (uint32(A) | (uint32(T) << 24)) struct UnitActionBarEntry { UnitActionBarEntry() : packedData(uint32(ACT_DISABLED) << 24) {} uint32 packedData; // helper ActiveStates GetType() const { return ActiveStates(UNIT_ACTION_BUTTON_TYPE(packedData)); } uint32 GetAction() const { return UNIT_ACTION_BUTTON_ACTION(packedData); } bool IsActionBarForSpell() const { ActiveStates Type = GetType(); return Type == ACT_DISABLED || Type == ACT_ENABLED || Type == ACT_PASSIVE; } void SetActionAndType(uint32 action, ActiveStates type) { packedData = MAKE_UNIT_ACTION_BUTTON(action, type); } void SetType(ActiveStates type) { packedData = MAKE_UNIT_ACTION_BUTTON(UNIT_ACTION_BUTTON_ACTION(packedData), type); } void SetAction(uint32 action) { packedData = (packedData & 0xFF000000) | UNIT_ACTION_BUTTON_ACTION(action); } }; typedef UnitActionBarEntry CharmSpellEntry; enum ActionBarIndex { ACTION_BAR_INDEX_START = 0, ACTION_BAR_INDEX_PET_SPELL_START = 3, ACTION_BAR_INDEX_PET_SPELL_END = 7, ACTION_BAR_INDEX_END = 10, }; #define MAX_UNIT_ACTION_BAR_INDEX (ACTION_BAR_INDEX_END-ACTION_BAR_INDEX_START) struct CharmInfo { public: explicit CharmInfo(Unit* unit); uint32 GetPetNumber() const { return m_petnumber; } void SetPetNumber(uint32 petnumber, bool statwindow); void SetCommandState(CommandStates st) { m_CommandState = st; } CommandStates GetCommandState() { return m_CommandState; } bool HasCommandState(CommandStates state) { return (m_CommandState == state); } void SetReactState(ReactStates st) { m_reactState = st; } ReactStates GetReactState() { return m_reactState; } bool HasReactState(ReactStates state) { return (m_reactState == state); } void InitPossessCreateSpells(); void InitCharmCreateSpells(); void InitPetActionBar(); void InitEmptyActionBar(); // return true if successful bool AddSpellToActionBar(uint32 spellid, ActiveStates newstate = ACT_DECIDE); bool RemoveSpellFromActionBar(uint32 spell_id); void LoadPetActionBar(const std::string& data); void BuildActionBar(WorldPacket* data); void SetSpellAutocast(uint32 spell_id, bool state); void SetActionBar(uint8 index, uint32 spellOrAction, ActiveStates type) { PetActionBar[index].SetActionAndType(spellOrAction, type); } UnitActionBarEntry const* GetActionBarEntry(uint8 index) const { return &(PetActionBar[index]); } void ToggleCreatureAutocast(uint32 spellid, bool apply); CharmSpellEntry* GetCharmSpell(uint8 index) { return &(m_charmspells[index]); } GlobalCooldownMgr& GetGlobalCooldownMgr() { return m_GlobalCooldownMgr; } private: Unit* m_unit; UnitActionBarEntry PetActionBar[MAX_UNIT_ACTION_BAR_INDEX]; CharmSpellEntry m_charmspells[CREATURE_MAX_SPELLS]; CommandStates m_CommandState; ReactStates m_reactState; uint32 m_petnumber; GlobalCooldownMgr m_GlobalCooldownMgr; }; // used in CallForAllControlledUnits/CheckAllControlledUnits enum ControlledUnitMask { CONTROLLED_PET = 0x01, CONTROLLED_MINIPET = 0x02, CONTROLLED_GUARDIANS = 0x04, // including PROTECTOR_PET CONTROLLED_CHARM = 0x08, CONTROLLED_TOTEMS = 0x10, }; // for clearing special attacks #define REACTIVE_TIMER_START 4000 enum ReactiveType { REACTIVE_DEFENSE = 0, REACTIVE_HUNTER_PARRY = 1, REACTIVE_OVERPOWER = 2 }; #define MAX_REACTIVE 3 // Used as MiscValue for SPELL_AURA_IGNORE_UNIT_STATE enum IgnoreUnitState { IGNORE_UNIT_TARGET_STATE = 0, // target health, aura states, or combopoints IGNORE_UNIT_COMBAT_STATE = 1, // ignore caster in combat state IGNORE_UNIT_TARGET_NON_FROZEN = 126, // ignore absent of frozen state }; // delay time next attack to prevent client attack animation problems #define ATTACK_DISPLAY_DELAY 200 #define MAX_PLAYER_STEALTH_DETECT_RANGE 45.0f // max distance for detection targets by player #define MAX_CREATURE_ATTACK_RADIUS 45.0f // max distance for creature aggro (use with CONFIG_FLOAT_RATE_CREATURE_AGGRO) // Regeneration defines #define REGEN_TIME_FULL 2000 // For this time difference is computed regen value #define REGEN_TIME_PRECISE 500 // Used in Spell::CheckPower for precise regeneration in spell cast time struct SpellProcEventEntry; // used only privately class MANGOS_DLL_SPEC Unit : public WorldObject { public: typedef std::set AttackerSet; typedef std::multimap< uint32, SpellAuraHolder*> SpellAuraHolderMap; typedef std::pair SpellAuraHolderBounds; typedef std::pair SpellAuraHolderConstBounds; typedef std::list SpellAuraHolderList; typedef std::list AuraList; typedef std::list Diminishing; typedef std::set ComboPointHolderSet; typedef std::map VisibleAuraMap; typedef std::map SingleCastSpellTargetMap; virtual ~Unit(); void AddToWorld() override; void RemoveFromWorld() override; void CleanupsBeforeDelete() override; // used in ~Creature/~Player (or before mass creature delete to remove cross-references to already deleted units) float GetObjectBoundingRadius() const override // overwrite WorldObject version { return m_floatValues[UNIT_FIELD_BOUNDINGRADIUS]; } DiminishingLevels GetDiminishing(DiminishingGroup group); void IncrDiminishing(DiminishingGroup group); void ApplyDiminishingToDuration(DiminishingGroup group, int32& duration, Unit* caster, DiminishingLevels Level, int32 limitduration, bool isReflected); void ApplyDiminishingAura(DiminishingGroup group, bool apply); void ClearDiminishings() { m_Diminishing.clear(); } void Update(uint32 update_diff, uint32 time) override; void setAttackTimer(WeaponAttackType type, uint32 time) { m_attackTimer[type] = time; } void resetAttackTimer(WeaponAttackType type = BASE_ATTACK); uint32 getAttackTimer(WeaponAttackType type) const { return m_attackTimer[type]; } bool isAttackReady(WeaponAttackType type = BASE_ATTACK) const { return m_attackTimer[type] == 0; } bool haveOffhandWeapon() const; bool UpdateMeleeAttackingState(); bool CanUseEquippedWeapon(WeaponAttackType attackType) const { if (IsInFeralForm()) return false; switch (attackType) { default: case BASE_ATTACK: return !HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED); case OFF_ATTACK: return !HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_DISARM_OFFHAND); case RANGED_ATTACK: return !HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_DISARM_RANGED); } } bool CanReachWithMeleeAttack(Unit* pVictim, float flat_mod = 0.0f) const; uint32 m_extraAttacks; void _addAttacker(Unit* pAttacker) // must be called only from Unit::Attack(Unit*) { AttackerSet::const_iterator itr = m_attackers.find(pAttacker); if (itr == m_attackers.end()) m_attackers.insert(pAttacker); } void _removeAttacker(Unit* pAttacker) // must be called only from Unit::AttackStop() { m_attackers.erase(pAttacker); } Unit* getAttackerForHelper() // If someone wants to help, who to give them { if (getVictim() != NULL) return getVictim(); if (!m_attackers.empty()) return *(m_attackers.begin()); return NULL; } bool Attack(Unit* victim, bool meleeAttack); void AttackedBy(Unit* attacker); void CastStop(uint32 except_spellid = 0); bool AttackStop(bool targetSwitch = false); void RemoveAllAttackers(); AttackerSet const& getAttackers() const { return m_attackers; } bool isAttackingPlayer() const; Unit* getVictim() const { return m_attacking; } void CombatStop(bool includingCast = false); void CombatStopWithPets(bool includingCast = false); void StopAttackFaction(uint32 faction_id); Unit* SelectRandomUnfriendlyTarget(Unit* except = NULL, float radius = ATTACK_DISTANCE) const; Unit* SelectRandomFriendlyTarget(Unit* except = NULL, float radius = ATTACK_DISTANCE) const; bool hasNegativeAuraWithInterruptFlag(uint32 flag); void SendMeleeAttackStop(Unit* victim); void SendMeleeAttackStart(Unit* pVictim); void addUnitState(uint32 f) { m_state |= f; } bool hasUnitState(uint32 f) const { return (m_state & f); } void clearUnitState(uint32 f) { m_state &= ~f; } bool CanFreeMove() const { return !hasUnitState(UNIT_STAT_NO_FREE_MOVE) && !GetOwnerGuid(); } uint32 getLevel() const { return GetUInt32Value(UNIT_FIELD_LEVEL); } virtual uint32 GetLevelForTarget(Unit const* /*target*/) const { return getLevel(); } void SetLevel(uint32 lvl); virtual uint8 getRace() const { return GetByteValue(UNIT_FIELD_BYTES_0, 0); } uint32 getRaceMask() const { return getRace() ? 1 << (getRace() - 1) : 0; } uint8 getClass() const { return GetByteValue(UNIT_FIELD_BYTES_0, 1); } uint32 getClassMask() const { return 1 << (getClass() - 1); } uint8 getGender() const { return GetByteValue(UNIT_FIELD_BYTES_0, 2); } float GetStat(Stats stat) const { return float(GetUInt32Value(UNIT_FIELD_STAT0 + stat)); } void SetStat(Stats stat, int32 val) { SetStatInt32Value(UNIT_FIELD_STAT0 + stat, val); } uint32 GetArmor() const { return GetResistance(SPELL_SCHOOL_NORMAL) ; } void SetArmor(int32 val) { SetResistance(SPELL_SCHOOL_NORMAL, val); } uint32 GetResistance(SpellSchools school) const { return GetUInt32Value(UNIT_FIELD_RESISTANCES + school); } void SetResistance(SpellSchools school, int32 val) { SetStatInt32Value(UNIT_FIELD_RESISTANCES + school, val); } uint32 GetHealth() const { return GetUInt32Value(UNIT_FIELD_HEALTH); } uint32 GetMaxHealth() const { return GetUInt32Value(UNIT_FIELD_MAXHEALTH); } float GetHealthPercent() const { return (GetHealth() * 100.0f) / GetMaxHealth(); } void SetHealth(uint32 val); void SetMaxHealth(uint32 val); void SetHealthPercent(float percent); int32 ModifyHealth(int32 val); Powers getPowerType() const { return Powers(GetByteValue(UNIT_FIELD_BYTES_0, 3)); } void setPowerType(Powers power); int32 GetPower(Powers power) const; int32 GetPowerByIndex(uint32 index) const; uint32 GetMaxPower(Powers power) const; uint32 GetMaxPowerByIndex(uint32 index) const; void SetPowerByIndex(uint32 power, int32 val); void SetMaxPowerByIndex(uint32 power, int32 val); void SetPower(Powers power, int32 val); void SetMaxPower(Powers power, int32 val); int32 ModifyPower(Powers power, int32 val); void ApplyPowerMod(Powers power, uint32 val, bool apply); void ApplyMaxPowerMod(Powers power, uint32 val, bool apply); static uint32 GetPowerIndexByClass(Powers power, uint32 classId); static Powers GetPowerTypeByIndex(uint32 index, uint32 classId); uint32 GetPowerIndex(Powers power) const { return GetPowerIndexByClass(power, getClass()); } Powers getPowerType(uint32 index) const { return GetPowerTypeByIndex(index, getClass()); } uint32 GetAttackTime(WeaponAttackType att) const { return (uint32)(GetFloatValue(UNIT_FIELD_BASEATTACKTIME + att) / m_modAttackSpeedPct[att]); } void SetAttackTime(WeaponAttackType att, uint32 val) { SetFloatValue(UNIT_FIELD_BASEATTACKTIME + att, val * m_modAttackSpeedPct[att]); } void ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply); void ApplyCastTimePercentMod(float val, bool apply); SheathState GetSheath() const { return SheathState(GetByteValue(UNIT_FIELD_BYTES_2, 0)); } virtual void SetSheath(SheathState sheathed) { SetByteValue(UNIT_FIELD_BYTES_2, 0, sheathed); } // faction template id uint32 getFaction() const { return GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE); } void setFaction(uint32 faction) { SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction); } FactionTemplateEntry const* getFactionTemplateEntry() const; bool IsHostileTo(Unit const* unit) const override; bool IsHostileToPlayers() const; bool IsFriendlyTo(Unit const* unit) const override; bool IsNeutralToAll() const; bool IsContestedGuard() const { if (FactionTemplateEntry const* entry = getFactionTemplateEntry()) return entry->IsContestedGuardFaction(); return false; } bool IsPvP() const { return HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP); } void SetPvP(bool state); bool IsFFAPvP() const { return HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); } void SetFFAPvP(bool state); uint32 GetCreatureType() const; uint32 GetCreatureTypeMask() const { uint32 creatureType = GetCreatureType(); return (creatureType >= 1) ? (1 << (creatureType - 1)) : 0; } uint8 getStandState() const { return GetByteValue(UNIT_FIELD_BYTES_1, 0); } bool IsSitState() const; bool IsStandState() const; void SetStandState(uint8 state); void SetStandFlags(uint8 flags) { SetByteFlag(UNIT_FIELD_BYTES_1, 2, flags); } void RemoveStandFlags(uint8 flags) { RemoveByteFlag(UNIT_FIELD_BYTES_1, 2, flags); } bool IsMounted() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT); } uint32 GetMountID() const { return GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID); } void Mount(uint32 mount, uint32 spellId = 0); void Unmount(bool from_aura = false); VehicleInfo* GetVehicleInfo() { return m_vehicleInfo; } bool IsVehicle() const { return m_vehicleInfo != NULL; } void SetVehicleId(uint32 entry); uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? GetLevelForTarget(target) : getLevel()) * 5; } void DealDamageMods(Unit* pVictim, uint32& damage, uint32* absorb); uint32 DealDamage(Unit* pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const* spellProto, bool durabilityLoss); int32 DealHeal(Unit* pVictim, uint32 addhealth, SpellEntry const* spellProto, bool critical = false, uint32 absorb = 0); void PetOwnerKilledUnit(Unit* pVictim); void ProcDamageAndSpell(Unit* pVictim, uint32 procAttacker, uint32 procVictim, uint32 procEx, uint32 amount, WeaponAttackType attType = BASE_ATTACK, SpellEntry const* procSpell = NULL); void ProcDamageAndSpellFor(bool isVictim, Unit* pTarget, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, SpellEntry const* procSpell, uint32 damage); void HandleEmote(uint32 emote_id); // auto-select command/state void HandleEmoteCommand(uint32 emote_id); void HandleEmoteState(uint32 emote_id); void AttackerStateUpdate(Unit* pVictim, WeaponAttackType attType = BASE_ATTACK, bool extra = false); float MeleeMissChanceCalc(const Unit* pVictim, WeaponAttackType attType) const; void CalculateMeleeDamage(Unit* pVictim, uint32 damage, CalcDamageInfo* damageInfo, WeaponAttackType attackType = BASE_ATTACK); void DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss); bool IsAllowedDamageInArea(Unit* pVictim) const; void CalculateSpellDamage(SpellNonMeleeDamage* damageInfo, int32 damage, SpellEntry const* spellInfo, WeaponAttackType attackType = BASE_ATTACK); void DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss); // player or player's pet resilience (-1%) uint32 GetCritDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_RESILIENCE_DAMAGE_TAKEN, 2.2f, 33.0f, damage); } // player or player's pet resilience (-1%), cap 100% uint32 GetDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_RESILIENCE_DAMAGE_TAKEN, 2.0f, 100.0f, damage); } float MeleeSpellMissChance(Unit* pVictim, WeaponAttackType attType, int32 skillDiff, SpellEntry const* spell); SpellMissInfo MeleeSpellHitResult(Unit* pVictim, SpellEntry const* spell); SpellMissInfo MagicSpellHitResult(Unit* pVictim, SpellEntry const* spell); SpellMissInfo SpellHitResult(Unit* pVictim, SpellEntry const* spell, bool canReflect = false); float GetUnitDodgeChance() const; float GetUnitParryChance() const; float GetUnitBlockChance() const; float GetUnitCriticalChance(WeaponAttackType attackType, const Unit* pVictim) const; virtual uint32 GetShieldBlockValue() const = 0; uint32 GetUnitMeleeSkill(Unit const* target = NULL) const { return (target ? GetLevelForTarget(target) : getLevel()) * 5; } uint32 GetDefenseSkillValue(Unit const* target = NULL) const; uint32 GetWeaponSkillValue(WeaponAttackType attType, Unit const* target = NULL) const; float GetWeaponProcChance() const; float GetPPMProcChance(uint32 WeaponSpeed, float PPM) const; MeleeHitOutcome RollMeleeOutcomeAgainst(const Unit* pVictim, WeaponAttackType attType) const; MeleeHitOutcome RollMeleeOutcomeAgainst(const Unit* pVictim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance) const; bool isVendor() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_VENDOR); } bool isTrainer() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TRAINER); } bool isQuestGiver() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); } bool isGossip() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); } bool isTaxi() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_FLIGHTMASTER); } bool isGuildMaster() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PETITIONER); } bool isBattleMaster() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_BATTLEMASTER); } bool isBanker() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_BANKER); } bool isInnkeeper() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_INNKEEPER); } bool isSpiritHealer() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITHEALER); } bool isSpiritGuide() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITGUIDE); } bool isTabardDesigner()const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TABARDDESIGNER); } bool isAuctioner() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_AUCTIONEER); } bool isArmorer() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_REPAIR); } bool isServiceProvider() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_VENDOR | UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_FLIGHTMASTER | UNIT_NPC_FLAG_PETITIONER | UNIT_NPC_FLAG_BATTLEMASTER | UNIT_NPC_FLAG_BANKER | UNIT_NPC_FLAG_INNKEEPER | UNIT_NPC_FLAG_SPIRITHEALER | UNIT_NPC_FLAG_SPIRITGUIDE | UNIT_NPC_FLAG_TABARDDESIGNER | UNIT_NPC_FLAG_AUCTIONEER); } bool isSpiritService() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITHEALER | UNIT_NPC_FLAG_SPIRITGUIDE); } bool IsTaxiFlying() const { return hasUnitState(UNIT_STAT_TAXI_FLIGHT); } bool isInCombat() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); } void SetInCombatState(bool PvP, Unit* enemy = NULL); void SetInCombatWith(Unit* enemy); void ClearInCombat(); uint32 GetCombatTimer() const { return m_CombatTimer; } SpellAuraHolderBounds GetSpellAuraHolderBounds(uint32 spell_id) { return m_spellAuraHolders.equal_range(spell_id); } SpellAuraHolderConstBounds GetSpellAuraHolderBounds(uint32 spell_id) const { return m_spellAuraHolders.equal_range(spell_id); } bool HasAuraType(AuraType auraType) const; bool HasAffectedAura(AuraType auraType, SpellEntry const* spellProto) const; bool HasAura(uint32 spellId, SpellEffectIndex effIndex) const; bool HasAura(uint32 spellId) const { return m_spellAuraHolders.find(spellId) != m_spellAuraHolders.end(); } bool HasAuraOfDifficulty(uint32 spellId) const; virtual bool HasSpell(uint32 /*spellID*/) const { return false; } bool HasStealthAura() const { return HasAuraType(SPELL_AURA_MOD_STEALTH); } bool HasInvisibilityAura() const { return HasAuraType(SPELL_AURA_MOD_INVISIBILITY); } bool isFeared() const { return HasAuraType(SPELL_AURA_MOD_FEAR); } bool isInRoots() const { return HasAuraType(SPELL_AURA_MOD_ROOT); } bool IsPolymorphed() const; bool isFrozen() const; bool IsIgnoreUnitState(SpellEntry const* spell, IgnoreUnitState ignoreState); bool isTargetableForAttack(bool inversAlive = false) const; bool isPassiveToHostile() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); } virtual bool IsInWater() const; virtual bool IsUnderWater() const; bool isInAccessablePlaceFor(Creature const* c) const; void SendHealSpellLog(Unit* pVictim, uint32 SpellID, uint32 Damage, uint32 OverHeal, bool critical = false, uint32 absorb = 0); void SendEnergizeSpellLog(Unit* pVictim, uint32 SpellID, uint32 Damage, Powers powertype); void EnergizeBySpell(Unit* pVictim, uint32 SpellID, uint32 Damage, Powers powertype); uint32 SpellNonMeleeDamageLog(Unit* pVictim, uint32 spellID, uint32 damage); void CastSpell(Unit* Victim, uint32 spellId, bool triggered, Item* castItem = NULL, Aura* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid(), SpellEntry const* triggeredBy = NULL); void CastSpell(Unit* Victim, SpellEntry const* spellInfo, bool triggered, Item* castItem = NULL, Aura* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid(), SpellEntry const* triggeredBy = NULL); void CastCustomSpell(Unit* Victim, uint32 spellId, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item* castItem = NULL, Aura* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid(), SpellEntry const* triggeredBy = NULL); void CastCustomSpell(Unit* Victim, SpellEntry const* spellInfo, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item* castItem = NULL, Aura* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid(), SpellEntry const* triggeredBy = NULL); void CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item* castItem = NULL, Aura* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid(), SpellEntry const* triggeredBy = NULL); void CastSpell(float x, float y, float z, SpellEntry const* spellInfo, bool triggered, Item* castItem = NULL, Aura* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid(), SpellEntry const* triggeredBy = NULL); void DeMorph(); void SendAttackStateUpdate(CalcDamageInfo* damageInfo); void SendAttackStateUpdate(uint32 HitInfo, Unit* target, uint8 SwingType, SpellSchoolMask damageSchoolMask, uint32 Damage, uint32 AbsorbDamage, uint32 Resist, VictimState TargetState, uint32 BlockedAmount); void SendSpellNonMeleeDamageLog(SpellNonMeleeDamage* log); void SendSpellNonMeleeDamageLog(Unit* target, uint32 SpellID, uint32 Damage, SpellSchoolMask damageSchoolMask, uint32 AbsorbedDamage, uint32 Resist, bool PhysicalDamage, uint32 Blocked, bool CriticalHit = false); void SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* pInfo); void SendSpellMiss(Unit* target, uint32 spellID, SpellMissInfo missInfo); void NearTeleportTo(float x, float y, float z, float orientation, bool casting = false); void MonsterMoveWithSpeed(float x, float y, float z, float speed, bool generatePath = false, bool forceDestination = false); // recommend use MonsterMove/MonsterMoveWithSpeed for most case that correctly work with movegens // if used additional args in ... part then floats must explicitly casted to double void SendHeartBeat(); bool IsLevitating() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_LEVITATING); } bool IsWalking() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_WALK_MODE); } bool IsRooted() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_ROOT); } virtual void SetRoot(bool enabled) {} virtual void SetWaterWalk(bool enabled) {} void SetInFront(Unit const* target); void SetFacingTo(float ori); void SetFacingToObject(WorldObject* pObject); void SendHighestThreatUpdate(HostileReference* pHostileReference); void SendThreatClear(); void SendThreatRemove(HostileReference* pHostileReference); void SendThreatUpdate(); bool isAlive() const { return (m_deathState == ALIVE); }; bool isDead() const { return (m_deathState == DEAD || m_deathState == CORPSE); }; DeathState getDeathState() const { return m_deathState; }; virtual void SetDeathState(DeathState s); // overwritten in Creature/Player/Pet ObjectGuid const& GetOwnerGuid() const { return GetGuidValue(UNIT_FIELD_SUMMONEDBY); } void SetOwnerGuid(ObjectGuid owner) { SetGuidValue(UNIT_FIELD_SUMMONEDBY, owner); } ObjectGuid const& GetCreatorGuid() const { return GetGuidValue(UNIT_FIELD_CREATEDBY); } void SetCreatorGuid(ObjectGuid creator) { SetGuidValue(UNIT_FIELD_CREATEDBY, creator); } ObjectGuid const& GetPetGuid() const { return GetGuidValue(UNIT_FIELD_SUMMON); } void SetPetGuid(ObjectGuid pet) { SetGuidValue(UNIT_FIELD_SUMMON, pet); } ObjectGuid const& GetCharmerGuid() const { return GetGuidValue(UNIT_FIELD_CHARMEDBY); } void SetCharmerGuid(ObjectGuid owner) { SetGuidValue(UNIT_FIELD_CHARMEDBY, owner); } ObjectGuid const& GetCharmGuid() const { return GetGuidValue(UNIT_FIELD_CHARM); } void SetCharmGuid(ObjectGuid charm) { SetGuidValue(UNIT_FIELD_CHARM, charm); } ObjectGuid const& GetTargetGuid() const { return GetGuidValue(UNIT_FIELD_TARGET); } void SetTargetGuid(ObjectGuid targetGuid) { SetGuidValue(UNIT_FIELD_TARGET, targetGuid); } ObjectGuid const& GetChannelObjectGuid() const { return GetGuidValue(UNIT_FIELD_CHANNEL_OBJECT); } void SetChannelObjectGuid(ObjectGuid targetGuid) { SetGuidValue(UNIT_FIELD_CHANNEL_OBJECT, targetGuid); } void SetCritterGuid(ObjectGuid critterGuid) { SetGuidValue(UNIT_FIELD_CRITTER, critterGuid); } ObjectGuid const& GetCritterGuid() const { return GetGuidValue(UNIT_FIELD_CRITTER); } void RemoveMiniPet(); Pet* GetMiniPet() const; void SetMiniPet(Unit* pet) { SetCritterGuid(pet ? pet->GetObjectGuid() : ObjectGuid()); } ObjectGuid const& GetCharmerOrOwnerGuid() const { return GetCharmerGuid() ? GetCharmerGuid() : GetOwnerGuid(); } ObjectGuid const& GetCharmerOrOwnerOrOwnGuid() const { if (ObjectGuid const& guid = GetCharmerOrOwnerGuid()) return guid; return GetObjectGuid(); } bool isCharmedOwnedByPlayerOrPlayer() const { return GetCharmerOrOwnerOrOwnGuid().IsPlayer(); } Player* GetSpellModOwner() const; Unit* GetOwner() const; Pet* GetPet() const; Unit* GetCharmer() const; Unit* GetCharm() const; void Uncharm(); Unit* GetCharmerOrOwner() const { return GetCharmerGuid() ? GetCharmer() : GetOwner(); } Unit* GetCharmerOrOwnerOrSelf() { if (Unit* u = GetCharmerOrOwner()) return u; return this; } bool IsCharmerOrOwnerPlayerOrPlayerItself() const; Player* GetCharmerOrOwnerPlayerOrPlayerItself(); Player const* GetCharmerOrOwnerPlayerOrPlayerItself() const; float GetCombatDistance(const Unit* target) const; void SetPet(Pet* pet); void SetCharm(Unit* pet); void AddGuardian(Pet* pet); void RemoveGuardian(Pet* pet); void RemoveGuardians(); Pet* FindGuardianWithEntry(uint32 entry); Pet* GetProtectorPet(); // expected single case in guardian list bool isCharmed() const { return !GetCharmerGuid().IsEmpty(); } CharmInfo* GetCharmInfo() { return m_charmInfo; } CharmInfo* InitCharmInfo(Unit* charm); ObjectGuid const& GetTotemGuid(TotemSlot slot) const { return m_TotemSlot[slot]; } Totem* GetTotem(TotemSlot slot) const; bool IsAllTotemSlotsUsed() const; void _AddTotem(TotemSlot slot, Totem* totem); // only for call from Totem summon code void _RemoveTotem(Totem* totem); // only for call from Totem class template void CallForAllControlledUnits(Func const& func, uint32 controlledMask); template bool CheckAllControlledUnits(Func const& func, uint32 controlledMask) const; bool AddSpellAuraHolder(SpellAuraHolder* holder); void AddAuraToModList(Aura* aura); // removing specific aura stack void RemoveAura(Aura* aura, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); void RemoveAura(uint32 spellId, SpellEffectIndex effindex, Aura* except = NULL); void RemoveSpellAuraHolder(SpellAuraHolder* holder, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); void RemoveSingleAuraFromSpellAuraHolder(SpellAuraHolder* holder, SpellEffectIndex index, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); void RemoveSingleAuraFromSpellAuraHolder(uint32 id, SpellEffectIndex index, ObjectGuid casterGuid, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); // removing specific aura stacks by diff reasons and selections void RemoveAurasDueToSpell(uint32 spellId, SpellAuraHolder* except = NULL, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); void RemoveAurasDueToItemSpell(Item* castItem, uint32 spellId); void RemoveAurasByCasterSpell(uint32 spellId, ObjectGuid casterGuid); void RemoveAurasDueToSpellBySteal(uint32 spellId, ObjectGuid casterGuid, Unit* stealer); void RemoveAurasDueToSpellByCancel(uint32 spellId); // removing unknown aura stacks by diff reasons and selections void RemoveNotOwnSingleTargetAuras(uint32 newPhase = 0x0); void RemoveAurasAtMechanicImmunity(uint32 mechMask, uint32 exceptSpellId, bool non_positive = false); void RemoveSpellsCausingAura(AuraType auraType); void RemoveSpellsCausingAura(AuraType auraType, SpellAuraHolder* except); void RemoveSpellsCausingAura(AuraType auraType, ObjectGuid casterGuid); void RemoveRankAurasDueToSpell(uint32 spellId); bool RemoveNoStackAurasDueToAuraHolder(SpellAuraHolder* holder); void RemoveAurasWithInterruptFlags(uint32 flags); void RemoveAurasWithAttribute(uint32 flags); void RemoveAurasWithDispelType(DispelType type, ObjectGuid casterGuid = ObjectGuid()); void RemoveAllAuras(AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); void RemoveArenaAuras(bool onleave = false); void RemoveAllAurasOnDeath(); // removing specific aura FROM stack by diff reasons and selections void RemoveAuraHolderFromStack(uint32 spellId, uint32 stackAmount = 1, ObjectGuid casterGuid = ObjectGuid(), AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); void RemoveAuraHolderDueToSpellByDispel(uint32 spellId, uint32 stackAmount, ObjectGuid casterGuid, Unit* dispeller); void DelaySpellAuraHolder(uint32 spellId, int32 delaytime, ObjectGuid casterGuid); float GetResistanceBuffMods(SpellSchools school, bool positive) const { return GetFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + school); } void SetResistanceBuffMods(SpellSchools school, bool positive, float val) { SetFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + school, val); } void ApplyResistanceBuffModsMod(SpellSchools school, bool positive, float val, bool apply) { ApplyModSignedFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + school, val, apply); } void ApplyResistanceBuffModsPercentMod(SpellSchools school, bool positive, float val, bool apply) { ApplyPercentModFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + school, val, apply); } void InitStatBuffMods() { for (int i = STAT_STRENGTH; i < MAX_STATS; ++i) SetFloatValue(UNIT_FIELD_POSSTAT0 + i, 0); for (int i = STAT_STRENGTH; i < MAX_STATS; ++i) SetFloatValue(UNIT_FIELD_NEGSTAT0 + i, 0); } void ApplyStatBuffMod(Stats stat, float val, bool apply) { ApplyModSignedFloatValue((val > 0 ? UNIT_FIELD_POSSTAT0 + stat : UNIT_FIELD_NEGSTAT0 + stat), val, apply); } void ApplyStatPercentBuffMod(Stats stat, float val, bool apply) { ApplyPercentModFloatValue(UNIT_FIELD_POSSTAT0 + stat, val, apply); ApplyPercentModFloatValue(UNIT_FIELD_NEGSTAT0 + stat, val, apply); } void SetCreateStat(Stats stat, float val) { m_createStats[stat] = val; } void SetCreateHealth(uint32 val) { SetUInt32Value(UNIT_FIELD_BASE_HEALTH, val); } uint32 GetCreateHealth() const { return GetUInt32Value(UNIT_FIELD_BASE_HEALTH); } void SetCreateMana(uint32 val) { SetUInt32Value(UNIT_FIELD_BASE_MANA, val); } uint32 GetCreateMana() const { return GetUInt32Value(UNIT_FIELD_BASE_MANA); } uint32 GetCreatePowers(Powers power) const; float GetPosStat(Stats stat) const { return GetFloatValue(UNIT_FIELD_POSSTAT0 + stat); } float GetNegStat(Stats stat) const { return GetFloatValue(UNIT_FIELD_NEGSTAT0 + stat); } float GetCreateStat(Stats stat) const { return m_createStats[stat]; } void SetCurrentCastedSpell(Spell* pSpell); virtual void ProhibitSpellSchool(SpellSchoolMask /*idSchoolMask*/, uint32 /*unTimeMs*/) { } void InterruptSpell(CurrentSpellTypes spellType, bool withDelayed = true, bool sendAutoRepeatCancelToClient = true); void FinishSpell(CurrentSpellTypes spellType, bool ok = true); // set withDelayed to true to account delayed spells as casted // delayed+channeled spells are always accounted as casted // we can skip channeled or delayed checks using flags bool IsNonMeleeSpellCasted(bool withDelayed, bool skipChanneled = false, bool skipAutorepeat = false) const; // set withDelayed to true to interrupt delayed spells too // delayed+channeled spells are always interrupted void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid = 0); Spell* GetCurrentSpell(CurrentSpellTypes spellType) const { return m_currentSpells[spellType]; } Spell* FindCurrentSpellBySpellId(uint32 spell_id) const; bool CheckAndIncreaseCastCounter(); void DecreaseCastCounter() { if (m_castCounter) --m_castCounter; } ObjectGuid m_ObjectSlotGuid[4]; uint32 m_detectInvisibilityMask; uint32 m_invisibilityMask; ShapeshiftForm GetShapeshiftForm() const { return ShapeshiftForm(GetByteValue(UNIT_FIELD_BYTES_2, 3)); } void SetShapeshiftForm(ShapeshiftForm form) { SetByteValue(UNIT_FIELD_BYTES_2, 3, form); } bool IsInFeralForm() const { ShapeshiftForm form = GetShapeshiftForm(); return form == FORM_CAT || form == FORM_BEAR || form == FORM_DIREBEAR; } bool IsInDisallowedMountForm() const { ShapeshiftForm form = GetShapeshiftForm(); return form != FORM_NONE && form != FORM_BATTLESTANCE && form != FORM_BERSERKERSTANCE && form != FORM_DEFENSIVESTANCE && form != FORM_SHADOW; } float m_modMeleeHitChance; float m_modRangedHitChance; float m_modSpellHitChance; int32 m_baseSpellCritChance; float m_threatModifier[MAX_SPELL_SCHOOL]; float m_modAttackSpeedPct[3]; // Event handler EventProcessor m_Events; // stat system bool HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply); void SetModifierValue(UnitMods unitMod, UnitModifierType modifierType, float value) { m_auraModifiersGroup[unitMod][modifierType] = value; } float GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) const; float GetTotalStatValue(Stats stat) const; float GetTotalAuraModValue(UnitMods unitMod) const; SpellSchools GetSpellSchoolByAuraGroup(UnitMods unitMod) const; Stats GetStatByAuraGroup(UnitMods unitMod) const; Powers GetPowerTypeByAuraGroup(UnitMods unitMod) const; bool CanModifyStats() const { return m_canModifyStats; } void SetCanModifyStats(bool modifyStats) { m_canModifyStats = modifyStats; } virtual bool UpdateStats(Stats stat) = 0; virtual bool UpdateAllStats() = 0; virtual void UpdateResistances(uint32 school) = 0; virtual void UpdateArmor() = 0; virtual void UpdateMaxHealth() = 0; virtual void UpdateMaxPower(Powers power) = 0; virtual void UpdateAttackPowerAndDamage(bool ranged = false) = 0; virtual void UpdateDamagePhysical(WeaponAttackType attType) = 0; float GetTotalAttackPowerValue(WeaponAttackType attType) const; float GetWeaponDamageRange(WeaponAttackType attType , WeaponDamageRange type) const; void SetBaseWeaponDamage(WeaponAttackType attType , WeaponDamageRange damageRange, float value) { m_weaponDamage[attType][damageRange] = value; } // Visibility system UnitVisibility GetVisibility() const { return m_Visibility; } void SetVisibility(UnitVisibility x); void UpdateVisibilityAndView() override; // overwrite WorldObject::UpdateVisibilityAndView() // common function for visibility checks for player/creatures with detection code bool isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, bool detect, bool inVisibleList = false, bool is3dDistance = true) const; bool canDetectInvisibilityOf(Unit const* u) const; void SetPhaseMask(uint32 newPhaseMask, bool update) override;// overwrite WorldObject::SetPhaseMask // virtual functions for all world objects types bool isVisibleForInState(Player const* u, WorldObject const* viewPoint, bool inVisibleList) const override; // function for low level grid visibility checks in player/creature cases virtual bool IsVisibleInGridForPlayer(Player* pl) const = 0; bool isInvisibleForAlive() const; SingleCastSpellTargetMap& GetSingleCastSpellTargets() { return m_singleCastSpellTargets; } SingleCastSpellTargetMap const& GetSingleCastSpellTargets() const { return m_singleCastSpellTargets; } SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY]; // Threat related methods bool CanHaveThreatList() const; void AddThreat(Unit* pVictim, float threat = 0.0f, bool crit = false, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NONE, SpellEntry const* threatSpell = NULL); float ApplyTotalThreatModifier(float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL); void DeleteThreatList(); bool IsSecondChoiceTarget(Unit* pTarget, bool checkThreatArea) const; bool SelectHostileTarget(); void TauntApply(Unit* pVictim); void TauntFadeOut(Unit* taunter); ThreatManager& getThreatManager() { return m_ThreatManager; } ThreatManager const& getThreatManager() const { return m_ThreatManager; } void addHatedBy(HostileReference* pHostileReference) { m_HostileRefManager.insertFirst(pHostileReference); }; void removeHatedBy(HostileReference* /*pHostileReference*/) { /* nothing to do yet */ } HostileRefManager& getHostileRefManager() { return m_HostileRefManager; } uint32 GetVisibleAura(uint8 slot) const { VisibleAuraMap::const_iterator itr = m_visibleAuras.find(slot); if (itr != m_visibleAuras.end()) return itr->second; return 0; } void SetVisibleAura(uint8 slot, uint32 spellid) { if (spellid == 0) m_visibleAuras.erase(slot); else m_visibleAuras[slot] = spellid; } VisibleAuraMap const& GetVisibleAuras() const { return m_visibleAuras; } uint8 GetVisibleAurasCount() const { return m_visibleAuras.size(); } Aura* GetAura(uint32 spellId, SpellEffectIndex effindex); Aura* GetAura(AuraType type, SpellFamily family, uint64 familyFlag, uint32 familyFlag2 = 0, ObjectGuid casterGuid = ObjectGuid()); SpellAuraHolder* GetSpellAuraHolder(uint32 spellid) const; SpellAuraHolder* GetSpellAuraHolder(uint32 spellid, ObjectGuid casterGUID) const; SpellAuraHolderMap& GetSpellAuraHolderMap() { return m_spellAuraHolders; } SpellAuraHolderMap const& GetSpellAuraHolderMap() const { return m_spellAuraHolders; } AuraList const& GetAurasByType(AuraType type) const { return m_modAuras[type]; } void ApplyAuraProcTriggerDamage(Aura* aura, bool apply); int32 GetTotalAuraModifier(AuraType auratype) const; float GetTotalAuraMultiplier(AuraType auratype) const; int32 GetMaxPositiveAuraModifier(AuraType auratype) const; int32 GetMaxNegativeAuraModifier(AuraType auratype) const; int32 GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const; float GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const; int32 GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const; int32 GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const; int32 GetTotalAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const; float GetTotalAuraMultiplierByMiscValue(AuraType auratype, int32 misc_value) const; int32 GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const; int32 GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const; // misc have plain value but we check it fit to provided values mask (mask & (1 << (misc-1))) float GetTotalAuraMultiplierByMiscValueForMask(AuraType auratype, uint32 mask) const; Aura* GetDummyAura(uint32 spell_id) const; uint32 m_AuraFlags; uint32 GetDisplayId() const { return GetUInt32Value(UNIT_FIELD_DISPLAYID); } void SetDisplayId(uint32 modelId); uint32 GetNativeDisplayId() const { return GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID); } void SetNativeDisplayId(uint32 modelId) { SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID, modelId); } void setTransForm(uint32 spellid) { m_transform = spellid;} uint32 getTransForm() const { return m_transform;} // at any changes to scale and/or displayId void UpdateModelData(); DynamicObject* GetDynObject(uint32 spellId, SpellEffectIndex effIndex); DynamicObject* GetDynObject(uint32 spellId); void AddDynObject(DynamicObject* dynObj); void RemoveDynObject(uint32 spellid); void RemoveDynObjectWithGUID(ObjectGuid guid) { m_dynObjGUIDs.remove(guid); } void RemoveAllDynObjects(); GameObject* GetGameObject(uint32 spellId) const; void AddGameObject(GameObject* gameObj); void AddWildGameObject(GameObject* gameObj); void RemoveGameObject(GameObject* gameObj, bool del); void RemoveGameObject(uint32 spellid, bool del); void RemoveAllGameObjects(); uint32 CalculateDamage(WeaponAttackType attType, bool normalized); float GetAPMultiplier(WeaponAttackType attType, bool normalized); void ModifyAuraState(AuraState flag, bool apply); bool HasAuraState(AuraState flag) const { return HasFlag(UNIT_FIELD_AURASTATE, 1 << (flag - 1)); } bool HasAuraStateForCaster(AuraState flag, ObjectGuid casterGuid) const; void UnsummonAllTotems(); Unit* SelectMagnetTarget(Unit* victim, Spell* spell = NULL, SpellEffectIndex eff = EFFECT_INDEX_0); int32 SpellBonusWithCoeffs(SpellEntry const* spellProto, int32 total, int32 benefit, int32 ap_benefit, DamageEffectType damagetype, bool donePart, float defCoeffMod = 1.0f); int32 SpellBaseDamageBonusDone(SpellSchoolMask schoolMask); int32 SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask); uint32 SpellDamageBonusDone(Unit* pVictim, SpellEntry const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack = 1); uint32 SpellDamageBonusTaken(Unit* pCaster, SpellEntry const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack = 1); int32 SpellBaseHealingBonusDone(SpellSchoolMask schoolMask); int32 SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask); uint32 SpellHealingBonusDone(Unit* pVictim, SpellEntry const* spellProto, int32 healamount, DamageEffectType damagetype, uint32 stack = 1); uint32 SpellHealingBonusTaken(Unit* pCaster, SpellEntry const* spellProto, int32 healamount, DamageEffectType damagetype, uint32 stack = 1); uint32 MeleeDamageBonusDone(Unit* pVictim, uint32 damage, WeaponAttackType attType, SpellEntry const* spellProto = NULL, DamageEffectType damagetype = DIRECT_DAMAGE, uint32 stack = 1); uint32 MeleeDamageBonusTaken(Unit* pCaster, uint32 pdamage, WeaponAttackType attType, SpellEntry const* spellProto = NULL, DamageEffectType damagetype = DIRECT_DAMAGE, uint32 stack = 1); bool IsSpellBlocked(Unit* pCaster, SpellEntry const* spellProto, WeaponAttackType attackType = BASE_ATTACK); bool IsSpellCrit(Unit* pVictim, SpellEntry const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK); uint32 SpellCriticalDamageBonus(SpellEntry const* spellProto, uint32 damage, Unit* pVictim); uint32 SpellCriticalHealingBonus(SpellEntry const* spellProto, uint32 damage, Unit* pVictim); bool IsTriggeredAtSpellProcEvent(Unit* pVictim, SpellAuraHolder* holder, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, SpellProcEventEntry const*& spellProcEvent); // Aura proc handlers SpellAuraProcResult HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleHasteAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleSpellCritChanceAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleProcTriggerDamageAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleOverrideClassScriptAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleMendingAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleModCastingSpeedNotStackAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleReflectSpellsSchoolAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleModPowerCostSchoolAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleMechanicImmuneResistanceAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleModDamageFromCasterAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleAddFlatModifierAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleAddPctModifierAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleModDamagePercentDoneAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleModRating(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleSpellMagnetAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleManaShieldAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleModResistanceAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleRemoveByDamageChanceProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleNULLProc(Unit* /*pVictim*/, uint32 /*damage*/, Aura* /*triggeredByAura*/, SpellEntry const* /*procSpell*/, uint32 /*procFlag*/, uint32 /*procEx*/, uint32 /*cooldown*/) { // no proc handler for this aura type return SPELL_AURA_PROC_OK; } SpellAuraProcResult HandleCantTrigger(Unit* /*pVictim*/, uint32 /*damage*/, Aura* /*triggeredByAura*/, SpellEntry const* /*procSpell*/, uint32 /*procFlag*/, uint32 /*procEx*/, uint32 /*cooldown*/) { // this aura type can't proc return SPELL_AURA_PROC_CANT_TRIGGER; } void SetLastManaUse() { if (GetTypeId() == TYPEID_PLAYER && !IsUnderLastManaUseEffect()) RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER); m_lastManaUseTimer = 5000; } bool IsUnderLastManaUseEffect() const { return m_lastManaUseTimer; } uint32 GetRegenTimer() const { return m_regenTimer; } void SetContestedPvP(Player* attackedPlayer = NULL); void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply); void ApplySpellDispelImmunity(const SpellEntry* spellProto, DispelType type, bool apply); virtual bool IsImmuneToSpell(SpellEntry const* spellInfo); // redefined in Creature bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask); virtual bool IsImmuneToSpellEffect(SpellEntry const* spellInfo, SpellEffectIndex index) const; // redefined in Creature uint32 CalcArmorReducedDamage(Unit* pVictim, const uint32 damage); void CalculateDamageAbsorbAndResist(Unit* pCaster, SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32* absorb, uint32* resist, bool canReflect = false); void CalculateAbsorbResistBlock(Unit* pCaster, SpellNonMeleeDamage* damageInfo, SpellEntry const* spellProto, WeaponAttackType attType = BASE_ATTACK); void CalculateHealAbsorb(uint32 heal, uint32* absorb); void UpdateSpeed(UnitMoveType mtype, bool forced, float ratio = 1.0f); float GetSpeed(UnitMoveType mtype) const; float GetSpeedRate(UnitMoveType mtype) const { return m_speed_rate[mtype]; } void SetSpeedRate(UnitMoveType mtype, float rate, bool forced = false); void KnockBackFrom(Unit* target, float horizontalSpeed, float verticalSpeed); void KnockBackWithAngle(float angle, float horizontalSpeed, float verticalSpeed); void _RemoveAllAuraMods(); void _ApplyAllAuraMods(); int32 CalculateSpellDamage(Unit const* target, SpellEntry const* spellProto, SpellEffectIndex effect_index, int32 const* basePoints = NULL); uint32 CalcNotIgnoreAbsorbDamage(uint32 damage, SpellSchoolMask damageSchoolMask, SpellEntry const* spellInfo = NULL); uint32 CalcNotIgnoreDamageReduction(uint32 damage, SpellSchoolMask damageSchoolMask); int32 CalculateAuraDuration(SpellEntry const* spellProto, uint32 effectMask, int32 duration, Unit const* caster); float CalculateLevelPenalty(SpellEntry const* spellProto) const; void addFollower(FollowerReference* pRef) { m_FollowingRefManager.insertFirst(pRef); } void removeFollower(FollowerReference* /*pRef*/) { /* nothing to do yet */ } MotionMaster* GetMotionMaster() { return &i_motionMaster; } bool IsStopped() const { return !(hasUnitState(UNIT_STAT_MOVING)); } void StopMoving(); void SetFeared(bool apply, ObjectGuid casterGuid = ObjectGuid(), uint32 spellID = 0, uint32 time = 0); void SetConfused(bool apply, ObjectGuid casterGuid = ObjectGuid(), uint32 spellID = 0); void SetFeignDeath(bool apply, ObjectGuid casterGuid = ObjectGuid(), uint32 spellID = 0); void AddComboPointHolder(uint32 lowguid) { m_ComboPointHolders.insert(lowguid); } void RemoveComboPointHolder(uint32 lowguid) { m_ComboPointHolders.erase(lowguid); } void ClearComboPointHolders(); ///----------Pet responses methods----------------- void SendPetCastFail(uint32 spellid, SpellCastResult msg); void SendPetActionFeedback(uint8 msg); void SendPetTalk(uint32 pettalk); void SendPetAIReaction(); ///----------End of Pet responses methods---------- void propagateSpeedChange() { GetMotionMaster()->propagateSpeedChange(); } // reactive attacks void ClearAllReactives(); void StartReactiveTimer(ReactiveType reactive) { m_reactiveTimer[reactive] = REACTIVE_TIMER_START;} void UpdateReactives(uint32 p_time); // group updates void UpdateAuraForGroup(uint8 slot); // pet auras typedef std::set PetAuraSet; PetAuraSet m_petAuras; void AddPetAura(PetAura const* petSpell); void RemovePetAura(PetAura const* petSpell); // Movement info MovementInfo m_movementInfo; Movement::MoveSpline* movespline; void ScheduleAINotify(uint32 delay); bool IsAINotifyScheduled() const { return m_AINotifyScheduled;} void _SetAINotifyScheduled(bool on) { m_AINotifyScheduled = on;} // only for call from RelocationNotifyEvent code void OnRelocated(); bool IsLinkingEventTrigger() const { return m_isCreatureLinkingTrigger; } bool IsSplineEnabled() const; bool IsInWorgenForm(bool inPermanent = false) const; // Packet builders void BuildForceMoveRootPacket(WorldPacket* data, bool apply, uint32 value); void BuildMoveWaterWalkPacket(WorldPacket* data, bool apply, uint32 value); void BuildSendPlayVisualPacket(WorldPacket* data, uint32 value, bool impact); void BuildMoveSetCanFlyPacket(WorldPacket* data, bool apply, uint32 value); protected: explicit Unit(); void _UpdateSpells(uint32 time); void _UpdateAutoRepeatSpell(); uint32 m_attackTimer[MAX_ATTACK]; float m_createStats[MAX_STATS]; AttackerSet m_attackers; Unit* m_attacking; DeathState m_deathState; SpellAuraHolderMap m_spellAuraHolders; SpellAuraHolderMap::iterator m_spellAuraHoldersUpdateIterator; // != end() in Unit::m_spellAuraHolders update and point to next element AuraList m_deletedAuras; // auras removed while in ApplyModifier and waiting deleted SpellAuraHolderList m_deletedHolders; SingleCastSpellTargetMap m_singleCastSpellTargets; // casted by unit single per-caster auras GuidList m_dynObjGUIDs; typedef std::list GameObjectList; GameObjectList m_gameObj; typedef std::map WildGameObjectMap; WildGameObjectMap m_wildGameObjs; bool m_isSorted; uint32 m_transform; AuraList m_modAuras[TOTAL_AURAS]; float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END]; float m_weaponDamage[MAX_ATTACK][2]; bool m_canModifyStats; // std::list< spellEffectPair > AuraSpells[TOTAL_AURAS]; // TODO: use this if ok for mem VisibleAuraMap m_visibleAuras; float m_speed_rate[MAX_MOVE_TYPE]; CharmInfo* m_charmInfo; virtual SpellSchoolMask GetMeleeDamageSchoolMask() const; MotionMaster i_motionMaster; uint32 m_reactiveTimer[MAX_REACTIVE]; uint32 m_regenTimer; uint32 m_lastManaUseTimer; VehicleInfo* m_vehicleInfo; void DisableSpline(); bool m_isCreatureLinkingTrigger; bool m_isSpawningLinked; private: void CleanupDeletedAuras(); void UpdateSplineMovement(uint32 t_diff); // player or player's pet float GetCombatRatingReduction(CombatRating cr) const; uint32 GetCombatRatingDamageReduction(CombatRating cr, float rate, float cap, uint32 damage) const; Unit* _GetTotem(TotemSlot slot) const; // for templated function without include need Pet* _GetPet(ObjectGuid guid) const; // for templated function without include need void JustKilledCreature(Creature* victim); // Wrapper called by DealDamage when a creature is killed uint32 m_state; // Even derived shouldn't modify uint32 m_CombatTimer; Spell* m_currentSpells[CURRENT_MAX_SPELL]; uint32 m_castCounter; // count casts chain of triggered spells for prevent infinity cast crashes UnitVisibility m_Visibility; Position m_last_notified_position; bool m_AINotifyScheduled; ShortTimeTracker m_movesplineTimer; Diminishing m_Diminishing; // Manage all Units threatening us ThreatManager m_ThreatManager; // Manage all Units that are threatened by us HostileRefManager m_HostileRefManager; FollowerRefManager m_FollowingRefManager; ComboPointHolderSet m_ComboPointHolders; GuidSet m_guardianPets; ObjectGuid m_TotemSlot[MAX_TOTEM_SLOT]; private: // Error traps for some wrong args using // this will catch and prevent build for any cases when all optional args skipped and instead triggered used non boolean type // no bodies expected for this declarations template void CastSpell(Unit* Victim, uint32 spell, TR triggered); template void CastSpell(Unit* Victim, SpellEntry const* spell, TR triggered); template void CastCustomSpell(Unit* Victim, uint32 spell, int32 const* bp0, int32 const* bp1, int32 const* bp2, TR triggered); template void CastCustomSpell(Unit* Victim, SpellEntry const* spell, int32 const* bp0, int32 const* bp1, int32 const* bp2, TR triggered); template void CastSpell(float x, float y, float z, uint32 spell, TR triggered); template void CastSpell(float x, float y, float z, SpellEntry const* spell, TR triggered); }; template void Unit::CallForAllControlledUnits(Func const& func, uint32 controlledMask) { if (controlledMask & CONTROLLED_PET) if (Pet* pet = GetPet()) func(pet); if (controlledMask & CONTROLLED_MINIPET) if (Unit* mini = GetMiniPet()) func(mini); if (controlledMask & CONTROLLED_GUARDIANS) { for (GuidSet::const_iterator itr = m_guardianPets.begin(); itr != m_guardianPets.end();) if (Pet* guardian = _GetPet(*(itr++))) func(guardian); } if (controlledMask & CONTROLLED_TOTEMS) { for (int i = 0; i < MAX_TOTEM_SLOT; ++i) if (Unit* totem = _GetTotem(TotemSlot(i))) func(totem); } if (controlledMask & CONTROLLED_CHARM) if (Unit* charm = GetCharm()) func(charm); } template bool Unit::CheckAllControlledUnits(Func const& func, uint32 controlledMask) const { if (controlledMask & CONTROLLED_PET) if (Pet const* pet = GetPet()) if (func(pet)) return true; if (controlledMask & CONTROLLED_MINIPET) if (Unit const* mini = GetMiniPet()) if (func(mini)) return true; if (controlledMask & CONTROLLED_GUARDIANS) { for (GuidSet::const_iterator itr = m_guardianPets.begin(); itr != m_guardianPets.end();) if (Pet const* guardian = _GetPet(*(itr++))) if (func(guardian)) return true; } if (controlledMask & CONTROLLED_TOTEMS) { for (int i = 0; i < MAX_TOTEM_SLOT; ++i) if (Unit const* totem = _GetTotem(TotemSlot(i))) if (func(totem)) return true; } if (controlledMask & CONTROLLED_CHARM) if (Unit const* charm = GetCharm()) if (func(charm)) return true; return false; } #endif