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.
This commit is contained in:
1 parent
cf47ef8be0
commit
a71da1c603
12 files changed
+82
-70
No files matched your search
@@ -50,7 +50,7 @@ void AggressorAI::UpdateAI(uint32 /*diff*/)
|
||||
|
||||
void CombatAI::InitializeAI()
|
||||
{
|
||||
for (uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i)
|
||||
for (uint32 i = 0; i < MAX_CREATURE_SPELLS; ++i)
|
||||
if (me->m_spells[i] && sSpellMgr->GetSpellInfo(me->m_spells[i]))
|
||||
spells.push_back(me->m_spells[i]);
|
||||
|
||||
|
||||
@@ -270,6 +270,7 @@ bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/)
|
||||
me->SetLootRecipient(NULL);
|
||||
me->ResetPlayerDamageReq();
|
||||
me->SetLastDamagedTime(0);
|
||||
me->SetCannotReachTarget(false);
|
||||
|
||||
if (me->IsInEvadeMode())
|
||||
return false;
|
||||
@@ -277,11 +278,11 @@ bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/)
|
||||
return true;
|
||||
}
|
||||
|
||||
#define BOUNDARY_VISUALIZE_CREATURE 15425
|
||||
#define BOUNDARY_VISUALIZE_CREATURE_SCALE 0.25f
|
||||
#define BOUNDARY_VISUALIZE_STEP_SIZE 1
|
||||
#define BOUNDARY_VISUALIZE_FAILSAFE_LIMIT 750
|
||||
#define BOUNDARY_VISUALIZE_SPAWN_HEIGHT 5
|
||||
const uint32 BOUNDARY_VISUALIZE_CREATURE = 15425;
|
||||
const float BOUNDARY_VISUALIZE_CREATURE_SCALE = 0.25f;
|
||||
const int8 BOUNDARY_VISUALIZE_STEP_SIZE = 1;
|
||||
const int32 BOUNDARY_VISUALIZE_FAILSAFE_LIMIT = 750;
|
||||
const float BOUNDARY_VISUALIZE_SPAWN_HEIGHT = 5.0f;
|
||||
int32 CreatureAI::VisualizeBoundary(uint32 duration, Unit* owner, bool fill) const
|
||||
{
|
||||
typedef std::pair<int32, int32> coordinate;
|
||||
@@ -297,13 +298,13 @@ int32 CreatureAI::VisualizeBoundary(uint32 duration, Unit* owner, bool fill) con
|
||||
std::unordered_set<coordinate> outOfBounds;
|
||||
|
||||
Position startPosition = owner->GetPosition();
|
||||
if (!CheckBoundary(&startPosition)) // fall back to creature position
|
||||
{
|
||||
if (!CheckBoundary(&startPosition))
|
||||
{ // fall back to creature position
|
||||
startPosition = me->GetPosition();
|
||||
if (!CheckBoundary(&startPosition))
|
||||
{
|
||||
{ // fall back to creature home position
|
||||
startPosition = me->GetHomePosition();
|
||||
if (!CheckBoundary(&startPosition)) // fall back to creature home position
|
||||
if (!CheckBoundary(&startPosition))
|
||||
return LANG_CREATURE_NO_INTERIOR_POINT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ class CreatureAI : public UnitAI
|
||||
{
|
||||
EVADE_REASON_NO_HOSTILES, // the creature's threat list is empty
|
||||
EVADE_REASON_BOUNDARY, // the creature has moved outside its evade boundary
|
||||
EVADE_REASON_NO_PATH, // the creature was unable to reach its target for over 5 seconds
|
||||
EVADE_REASON_SEQUENCE_BREAK, // this is a boss and the pre-requisite encounters for engaging it are not defeated yet
|
||||
EVADE_REASON_OTHER
|
||||
};
|
||||
|
||||
@@ -190,15 +190,15 @@ SpellInfo const* ScriptedAI::SelectSpell(Unit* target, uint32 school, uint32 mec
|
||||
return NULL;
|
||||
|
||||
//Using the extended script system we first create a list of viable spells
|
||||
SpellInfo const* apSpell[CREATURE_MAX_SPELLS];
|
||||
memset(apSpell, 0, CREATURE_MAX_SPELLS * sizeof(SpellInfo*));
|
||||
SpellInfo const* apSpell[MAX_CREATURE_SPELLS];
|
||||
memset(apSpell, 0, MAX_CREATURE_SPELLS * sizeof(SpellInfo*));
|
||||
|
||||
uint32 spellCount = 0;
|
||||
|
||||
SpellInfo const* tempSpell = NULL;
|
||||
|
||||
//Check if each spell is viable(set it to null if not)
|
||||
for (uint32 i = 0; i < CREATURE_MAX_SPELLS; i++)
|
||||
for (uint32 i = 0; i < MAX_CREATURE_SPELLS; i++)
|
||||
{
|
||||
tempSpell = sSpellMgr->GetSpellInfo(me->m_spells[i]);
|
||||
|
||||
|
||||
@@ -416,12 +416,7 @@ void SmartAI::EnterEvadeMode(EvadeReason /*why*/)
|
||||
me->RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_CLONE_CASTER);
|
||||
|
||||
me->AddUnitState(UNIT_STATE_EVADE);
|
||||
me->DeleteThreatList();
|
||||
me->CombatStop(true);
|
||||
me->LoadCreaturesAddon();
|
||||
me->SetLootRecipient(NULL);
|
||||
me->ResetPlayerDamageReq();
|
||||
me->SetLastDamagedTime(0);
|
||||
_EnterEvadeMode();
|
||||
|
||||
GetScript()->ProcessEventsFor(SMART_EVENT_EVADE);//must be after aura clear so we can cast spells from db
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -395,7 +395,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;
|
||||
@@ -652,33 +652,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 <= diff)
|
||||
{*/
|
||||
if (!IsInEvadeMode() && (!bInCombat || IsPolymorphed())) // regenerate health if not in combat or if polymorphed
|
||||
RegenerateHealth();
|
||||
|
||||
if (HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER))
|
||||
if (m_regenTimer == 0)
|
||||
{
|
||||
if (getPowerType() == POWER_ENERGY)
|
||||
Regenerate(POWER_ENERGY);
|
||||
else
|
||||
RegenerateMana();
|
||||
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 (!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();
|
||||
}
|
||||
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:
|
||||
@@ -1837,7 +1836,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;
|
||||
@@ -1885,7 +1884,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;
|
||||
@@ -2325,10 +2324,10 @@ void Creature::SetInCombatWithZone()
|
||||
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
|
||||
|
||||
@@ -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 CreatureTemplate
|
||||
@@ -119,7 +120,7 @@ struct 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;
|
||||
@@ -484,6 +485,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
|
||||
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();
|
||||
@@ -565,7 +567,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
|
||||
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;
|
||||
@@ -630,6 +632,9 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
|
||||
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()); }
|
||||
|
||||
@@ -717,6 +722,8 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
|
||||
bool m_AlreadyCallAssistance;
|
||||
bool m_AlreadySearchedAssistance;
|
||||
bool m_regenHealth;
|
||||
bool m_cannotReachTarget;
|
||||
uint32 m_cannotReachTimer;
|
||||
bool m_AI_locked;
|
||||
|
||||
SpellSchoolMask m_meleeDamageSchoolMask;
|
||||
|
||||
@@ -20895,7 +20895,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);
|
||||
@@ -20919,7 +20919,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?
|
||||
|
||||
@@ -581,7 +581,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;
|
||||
@@ -1098,7 +1098,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);
|
||||
@@ -1309,7 +1309,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
|
||||
@@ -1945,7 +1945,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);
|
||||
@@ -2512,7 +2512,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
|
||||
@@ -7639,7 +7639,7 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (victim->ToCreature()->IsInEvadeMode())
|
||||
if (victim->ToCreature()->IsEvadingAttacks())
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -12339,7 +12339,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);
|
||||
|
||||
@@ -513,7 +513,7 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields)
|
||||
for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
|
||||
creatureTemplate.resistance[i] = fields[44 + i - 1].GetInt16();
|
||||
|
||||
for (uint8 i = 0; i < CREATURE_MAX_SPELLS; ++i)
|
||||
for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i)
|
||||
creatureTemplate.spells[i] = fields[50 + i].GetUInt32();
|
||||
|
||||
creatureTemplate.PetSpellDataId = fields[58].GetUInt32();
|
||||
@@ -854,7 +854,7 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
|
||||
if (!displayScaleEntry)
|
||||
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) does not have any existing display id in Modelid1/Modelid2/Modelid3/Modelid4.", cInfo->Entry);
|
||||
|
||||
for (int k = 0; k < MAX_KILL_CREDIT; ++k)
|
||||
for (uint8 k = 0; k < MAX_KILL_CREDIT; ++k)
|
||||
{
|
||||
if (cInfo->KillCredit[k])
|
||||
{
|
||||
@@ -941,7 +941,7 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
|
||||
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has non-existing PetSpellDataId (%u).", cInfo->Entry, cInfo->PetSpellDataId);
|
||||
}
|
||||
|
||||
for (uint8 j = 0; j < CREATURE_MAX_SPELLS; ++j)
|
||||
for (uint8 j = 0; j < MAX_CREATURE_SPELLS; ++j)
|
||||
{
|
||||
if (cInfo->spells[j] && !sSpellMgr->GetSpellInfo(cInfo->spells[j]))
|
||||
{
|
||||
|
||||
@@ -37,7 +37,10 @@ void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool up
|
||||
return;
|
||||
|
||||
if (owner->GetTypeId() == TYPEID_UNIT && !i_target->isInAccessiblePlaceFor(owner->ToCreature()))
|
||||
{
|
||||
owner->ToCreature()->SetCannotReachTarget(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsFocusing(nullptr, true))
|
||||
return;
|
||||
@@ -102,8 +105,10 @@ void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool up
|
||||
bool result = i_path->CalculatePath(x, y, z, forceDest);
|
||||
if (!result || (i_path->GetPathType() & PATHFIND_NOPATH))
|
||||
{
|
||||
// Cant reach target
|
||||
// can't reach target
|
||||
i_recalculateTravel = true;
|
||||
if (owner->GetTypeId() == TYPEID_UNIT)
|
||||
owner->ToCreature()->SetCannotReachTarget(true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -111,6 +116,8 @@ void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool up
|
||||
i_targetReached = false;
|
||||
i_recalculateTravel = false;
|
||||
owner->AddUnitState(UNIT_STATE_CHASE);
|
||||
if (owner->GetTypeId() == TYPEID_UNIT)
|
||||
owner->ToCreature()->SetCannotReachTarget(false);
|
||||
|
||||
Movement::MoveSplineInit init(owner);
|
||||
init.MovebyPath(i_path->GetPath());
|
||||
@@ -201,6 +208,8 @@ void ChaseMovementGenerator<T>::_reachTarget(T* owner)
|
||||
{
|
||||
if (owner->IsWithinMeleeRange(this->i_target.getTarget()))
|
||||
owner->Attack(this->i_target.getTarget(), true);
|
||||
if (owner->GetTypeId() == TYPEID_UNIT)
|
||||
owner->ToCreature()->SetCannotReachTarget(false);
|
||||
}
|
||||
|
||||
template<>
|
||||
|
||||
@@ -549,7 +549,7 @@ void SpellHistory::LockSpellSchool(SpellSchoolMask schoolMask, uint32 lockoutTim
|
||||
else
|
||||
{
|
||||
Creature* creatureOwner = _owner->ToCreature();
|
||||
for (uint8 i = 0; i < CREATURE_MAX_SPELLS; ++i)
|
||||
for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i)
|
||||
if (creatureOwner->m_spells[i])
|
||||
knownSpells.insert(creatureOwner->m_spells[i]);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user