diff options
| author | treeston <treeston.mmoc@gmail.com> | 2016-03-24 16:12:53 +0100 |
|---|---|---|
| committer | treeston <treeston.mmoc@gmail.com> | 2016-04-10 19:49:40 +0200 |
| commit | 7b1560fccba77ecbdfecd7b33af740aea41b7087 (patch) | |
| tree | 19e4783dba7cde9f6f936f3e4d78ab3a191132c2 /src/server/game/Entities | |
| parent | 6ca400b35eb44ed1392fdab093f521ee4787a63b (diff) | |
Entities/Unit: Finally fix no-path evasion.
- When a creature cannot find a path to its victim, it begins evading all attacks and regenerating health.
- If this persists for 5 seconds, it evades back to spawn position with new EvadeReason value EVADE_REASON_NO_PATH.
- Also some SmartAI cleanup (why oh why does it have so much duplicated code) and getting rid of #defines in favor of type-checked compile-time constants.
Diffstat (limited to 'src/server/game/Entities')
| -rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 57 | ||||
| -rw-r--r-- | src/server/game/Entities/Creature/Creature.h | 21 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 4 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 14 |
4 files changed, 51 insertions, 45 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 61d5d7d9459..eefd24e203b 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -182,13 +182,13 @@ m_groupLootTimer(0), lootingGroupLowGUID(0), m_PlayerDamageReq(0), m_lootRecipient(), m_lootRecipientGroup(0), _skinner(), _pickpocketLootRestore(0), m_corpseRemoveTime(0), m_respawnTime(0), m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_boundaryCheckTime(2500), m_combatPulseTime(0), m_combatPulseDelay(0), m_reactState(REACT_AGGRESSIVE), m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false), -m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), +m_AlreadySearchedAssistance(false), m_regenHealth(true), m_cannotReachTarget(false), m_cannotReachTimer(0), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_waypointID(0), m_path_id(0), m_formation(nullptr), m_focusSpell(nullptr), m_focusDelay(0) { m_regenTimer = CREATURE_REGEN_INTERVAL; m_valuesCount = UNIT_END; - for (uint8 i = 0; i < CREATURE_MAX_SPELLS; ++i) + for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i) m_spells[i] = 0; DisableReputationGain = false; @@ -394,7 +394,7 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/) if (!m_respawnradius && m_defaultMovementType == RANDOM_MOTION_TYPE) m_defaultMovementType = IDLE_MOTION_TYPE; - for (uint8 i=0; i < CREATURE_MAX_SPELLS; ++i) + for (uint8 i=0; i < MAX_CREATURE_SPELLS; ++i) m_spells[i] = GetCreatureTemplate()->spells[i]; return true; @@ -648,33 +648,32 @@ void Creature::Update(uint32 diff) m_regenTimer -= diff; } - if (m_regenTimer != 0) - break; - - bool bInCombat = IsInCombat() && (!GetVictim() || // if IsInCombat() is true and this has no victim - !EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself() || // or the victim/owner/charmer is not a player - !EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()->IsGameMaster()); // or the victim/owner/charmer is not a GameMaster + if (m_regenTimer == 0) + { + bool bInCombat = IsInCombat() && (!GetVictim() || // if IsInCombat() is true and this has no victim + !EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself() || // or the victim/owner/charmer is not a player + !EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()->IsGameMaster()); // or the victim/owner/charmer is not a GameMaster - /*if (m_regenTimer <= diff) - {*/ - if (!IsInEvadeMode() && (!bInCombat || IsPolymorphed())) // regenerate health if not in combat or if polymorphed - RegenerateHealth(); + if (!IsInEvadeMode() && (!bInCombat || IsPolymorphed() || CanNotReachTarget())) // regenerate health if not in combat or if polymorphed + RegenerateHealth(); - if (HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER)) - { - if (getPowerType() == POWER_ENERGY) - Regenerate(POWER_ENERGY); - else - RegenerateMana(); + if (HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER)) + { + if (getPowerType() == POWER_ENERGY) + Regenerate(POWER_ENERGY); + else + RegenerateMana(); + } + m_regenTimer = CREATURE_REGEN_INTERVAL; } - /*if (!bIsPolymorphed) // only increase the timer if not polymorphed - m_regenTimer += CREATURE_REGEN_INTERVAL - diff; + if (CanNotReachTarget() && !IsInEvadeMode() && !GetMap()->IsRaid()) + { + m_cannotReachTimer += diff; + if (m_cannotReachTimer >= CREATURE_NOPATH_EVADE_TIME) + if (IsAIEnabled) + AI()->EnterEvadeMode(CreatureAI::EVADE_REASON_NO_PATH); } - else - if (!bIsPolymorphed) // if polymorphed, skip the timer - m_regenTimer -= diff;*/ - m_regenTimer = CREATURE_REGEN_INTERVAL; break; } default: @@ -1814,7 +1813,7 @@ SpellInfo const* Creature::reachWithSpellAttack(Unit* victim) if (!victim) return nullptr; - for (uint32 i=0; i < CREATURE_MAX_SPELLS; ++i) + for (uint32 i=0; i < MAX_CREATURE_SPELLS; ++i) { if (!m_spells[i]) continue; @@ -1862,7 +1861,7 @@ SpellInfo const* Creature::reachWithSpellCure(Unit* victim) if (!victim) return nullptr; - for (uint32 i=0; i < CREATURE_MAX_SPELLS; ++i) + for (uint32 i=0; i < MAX_CREATURE_SPELLS; ++i) { if (!m_spells[i]) continue; @@ -2307,10 +2306,10 @@ uint32 Creature::GetShieldBlockValue() const //dunno mob block bool Creature::HasSpell(uint32 spellID) const { uint8 i; - for (i = 0; i < CREATURE_MAX_SPELLS; ++i) + for (i = 0; i < MAX_CREATURE_SPELLS; ++i) if (spellID == m_spells[i]) break; - return i < CREATURE_MAX_SPELLS; //broke before end of iteration of known spells + return i < MAX_CREATURE_SPELLS; //broke before end of iteration of known spells } time_t Creature::GetRespawnTimeEx() const diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index c6b19dbb939..71b1d118485 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -67,12 +67,13 @@ enum CreatureFlagsExtra CREATURE_FLAG_EXTRA_NO_SKILLGAIN | CREATURE_FLAG_EXTRA_TAUNT_DIMINISH | CREATURE_FLAG_EXTRA_ALL_DIMINISH | \ CREATURE_FLAG_EXTRA_GUARD | CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING | CREATURE_FLAG_EXTRA_NO_PLAYER_DAMAGE_REQ | CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK) -#define CREATURE_REGEN_INTERVAL 2 * IN_MILLISECONDS +const uint32 CREATURE_REGEN_INTERVAL = 2 * IN_MILLISECONDS; +const uint32 CREATURE_NOPATH_EVADE_TIME = 5 * IN_MILLISECONDS; -#define MAX_KILL_CREDIT 2 -#define MAX_CREATURE_MODELS 4 -#define MAX_CREATURE_QUEST_ITEMS 6 -#define CREATURE_MAX_SPELLS 8 +const uint8 MAX_KILL_CREDIT = 2; +const uint32 MAX_CREATURE_MODELS = 4; +const uint32 MAX_CREATURE_QUEST_ITEMS = 6; +const uint32 MAX_CREATURE_SPELLS = 8; // from `creature_template` table struct TC_GAME_API CreatureTemplate @@ -117,7 +118,7 @@ struct TC_GAME_API CreatureTemplate uint32 pickpocketLootId; uint32 SkinLootId; int32 resistance[MAX_SPELL_SCHOOL]; - uint32 spells[CREATURE_MAX_SPELLS]; + uint32 spells[MAX_CREATURE_SPELLS]; uint32 PetSpellDataId; uint32 VehicleId; uint32 mingold; @@ -475,6 +476,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma uint8 getLevelForTarget(WorldObject const* target) const override; // overwrite Unit::getLevelForTarget for boss level support bool IsInEvadeMode() const { return HasUnitState(UNIT_STATE_EVADE); } + bool IsEvadingAttacks() const { return IsInEvadeMode() || CanNotReachTarget(); } bool AIM_Initialize(CreatureAI* ai = NULL); void Motion_Initialize(); @@ -566,7 +568,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma SpellInfo const* reachWithSpellAttack(Unit* victim); SpellInfo const* reachWithSpellCure(Unit* victim); - uint32 m_spells[CREATURE_MAX_SPELLS]; + uint32 m_spells[MAX_CREATURE_SPELLS]; bool CanStartAttack(Unit const* u, bool force) const; float GetAttackDistance(Unit const* player) const; @@ -631,6 +633,9 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma virtual uint8 GetPetAutoSpellSize() const { return MAX_SPELL_CHARM; } virtual uint32 GetPetAutoSpellOnPos(uint8 pos) const; + void SetCannotReachTarget(bool cannotReach) { if (cannotReach == m_cannotReachTarget) return; m_cannotReachTarget = cannotReach; m_cannotReachTimer = 0; } + bool CanNotReachTarget() const { return m_cannotReachTarget; } + void SetPosition(float x, float y, float z, float o); void SetPosition(const Position &pos) { SetPosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()); } @@ -718,6 +723,8 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma bool m_AlreadyCallAssistance; bool m_AlreadySearchedAssistance; bool m_regenHealth; + bool m_cannotReachTarget; + uint32 m_cannotReachTimer; bool m_AI_locked; SpellSchoolMask m_meleeDamageSchoolMask; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 0af1fc87f6b..4a21a6d0fd7 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -20485,7 +20485,7 @@ void Player::VehicleSpellInitialize() data << uint8(0); // Command State data << uint16(0x800); // DisableActions (set for all vehicles) - for (uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i) + for (uint32 i = 0; i < MAX_CREATURE_SPELLS; ++i) { uint32 spellId = vehicle->m_spells[i]; SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); @@ -20509,7 +20509,7 @@ void Player::VehicleSpellInitialize() data << uint32(MAKE_UNIT_ACTION_BUTTON(spellId, i+8)); } - for (uint32 i = CREATURE_MAX_SPELLS; i < MAX_SPELL_CONTROL_BAR; ++i) + for (uint32 i = MAX_CREATURE_SPELLS; i < MAX_SPELL_CONTROL_BAR; ++i) data << uint32(0); data << uint8(0); // Auras? diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 319b939d899..45577f5cf1c 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -578,7 +578,7 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) cons void Unit::DealDamageMods(Unit* victim, uint32 &damage, uint32* absorb) { - if (!victim || !victim->IsAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode())) + if (!victim || !victim->IsAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks())) { if (absorb) *absorb += damage; @@ -1120,7 +1120,7 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss) if (!victim) return; - if (!victim->IsAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode())) + if (!victim->IsAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks())) return; SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(damageInfo->SpellID); @@ -1346,7 +1346,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss) { Unit* victim = damageInfo->target; - if (!victim->IsAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode())) + if (!victim->IsAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks())) return; // Hmmmm dont like this emotes client must by self do all animations @@ -2044,7 +2044,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit* victim, WeaponAttackTy MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance) const { - if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode()) + if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks()) return MELEE_HIT_EVADE; int32 attackerMaxSkillValueForLevel = GetMaxSkillValueForLevel(victim); @@ -2656,7 +2656,7 @@ SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spellInfo, boo return SPELL_MISS_NONE; // Return evade for units in evade mode - if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode()) + if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks()) return SPELL_MISS_EVADE; // Try victim reflect spell @@ -8990,7 +8990,7 @@ bool Unit::Attack(Unit* victim, bool meleeAttack) } else { - if (victim->ToCreature()->IsInEvadeMode()) + if (victim->ToCreature()->IsEvadingAttacks()) return false; } @@ -13887,7 +13887,7 @@ void CharmInfo::InitPossessCreateSpells() break; } - for (uint8 i = 0; i < CREATURE_MAX_SPELLS; ++i) + for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i) { uint32 spellId = _unit->ToCreature()->m_spells[i]; SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); |
