Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2024-09-04 23:45:48 +08:00
282 changed files with 1861 additions and 1430 deletions

View File

@@ -220,9 +220,6 @@ bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
{
if (Unit* victim = ObjectAccessor::GetUnit(*m_owner, m_victim))
{
// Initialize last damage timer if it doesn't exist
m_owner->SetLastDamagedTime(GameTime::GetGameTime().count() + MAX_AGGRO_RESET_TIME);
while (!m_assistants.empty())
{
Creature* assistant = ObjectAccessor::GetCreature(*m_owner, *m_assistants.begin());
@@ -233,9 +230,14 @@ bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
assistant->SetNoCallAssistance(true);
assistant->CombatStart(victim);
if (assistant->IsAIEnabled)
{
assistant->AI()->AttackStart(victim);
assistant->SetLastDamagedTimePtr(m_owner->GetLastDamagedTimePtr());
// When nearby mobs aggro from another mob's initial call for assistance
// their leash timers become linked and attacking one will keep the rest from evading.
if (assistant->GetVictim())
assistant->SetLastLeashExtensionTimePtr(m_owner->GetLastLeashExtensionTimePtr());
}
}
}
}
@@ -272,7 +274,7 @@ Creature::Creature(bool isWorldObject): Unit(isWorldObject), MovableMapObject(),
m_transportCheckTimer(1000), lootPickPocketRestoreTime(0), 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_regenPower(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_moveInLineOfSightDisabled(false), m_moveInLineOfSightStrictlyDisabled(false),
m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_detectionDistance(20.0f), m_waypointID(0), m_path_id(0), m_formation(nullptr), _lastDamagedTime(nullptr), m_cannotReachTimer(0),
m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_detectionDistance(20.0f), m_waypointID(0), m_path_id(0), m_formation(nullptr), m_lastLeashExtensionTime(nullptr), m_cannotReachTimer(0),
_isMissingSwimmingFlagOutOfCombat(false), m_assistanceTimer(0), _playerDamageReq(0), _damagedByPlayer(false), _isCombatMovementAllowed(true)
{
m_regenTimer = CREATURE_REGEN_INTERVAL;
@@ -1905,7 +1907,7 @@ bool Creature::CanStartAttack(Unit const* who) const
return false;
// This set of checks is should be done only for creatures
if ((IsImmuneToNPC() && who->GetTypeId() != TYPEID_PLAYER) || // flag is valid only for non player characters
if ((IsImmuneToNPC() && !who->IsPlayer()) || // flag is valid only for non player characters
(IsImmuneToPC() && who->IsPlayer())) // immune to PC and target is a player, return false
{
return false;
@@ -1916,7 +1918,7 @@ bool Creature::CanStartAttack(Unit const* who) const
return false;
// Do not attack non-combat pets
if (who->GetTypeId() == TYPEID_UNIT && who->GetCreatureType() == CREATURE_TYPE_NON_COMBAT_PET)
if (who->IsCreature() && who->GetCreatureType() == CREATURE_TYPE_NON_COMBAT_PET)
return false;
if (!CanFly() && (GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE + m_CombatDistance)) // too much Z difference, skip very costy vmap calculations here
@@ -1962,8 +1964,6 @@ void Creature::setDeathState(DeathState state, bool despawn)
if (state == DeathState::JustDied)
{
_lastDamagedTime.reset();
m_corpseRemoveTime = GameTime::GetGameTime().count() + m_corpseDelay;
m_respawnTime = GameTime::GetGameTime().count() + m_respawnDelay + m_corpseDelay;
@@ -2499,7 +2499,7 @@ bool Creature::CanAssistTo(Unit const* u, Unit const* enemy, bool checkfaction /
return false;
// pussywizard: or if enemy is in evade mode
if (enemy && enemy->GetTypeId() == TYPEID_UNIT && enemy->ToCreature()->IsInEvadeMode())
if (enemy && enemy->IsCreature() && enemy->ToCreature()->IsInEvadeMode())
return false;
// we don't need help from non-combatant ;)
@@ -2637,11 +2637,11 @@ bool Creature::CanCreatureAttack(Unit const* victim, bool skipDistCheck) const
return false;
// pussywizard: or if enemy is in evade mode
if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode())
if (victim->IsCreature() && victim->ToCreature()->IsInEvadeMode())
return false;
// cannot attack if is during 5 second grace period, unless being attacked
if (m_respawnedTime && (GameTime::GetGameTime().count() - m_respawnedTime) < 5 && !GetLastDamagedTime())
if (m_respawnedTime && (GameTime::GetGameTime().count() - m_respawnedTime) < 5 && !IsEngagedBy(victim))
{
return false;
}
@@ -2657,9 +2657,15 @@ bool Creature::CanCreatureAttack(Unit const* victim, bool skipDistCheck) const
if (GetMap()->IsDungeon())
return true;
float visibility = std::max<float>(GetVisibilityRange(), victim->GetVisibilityRange());
// if outside visibility
if (!IsWithinDist(victim, visibility))
return false;
// pussywizard: don't check distance to home position if recently damaged (allow kiting away from spawnpoint!)
// xinef: this should include taunt auras
if (!isWorldBoss() && (GetLastDamagedTime() > GameTime::GetGameTime().count() || HasAuraType(SPELL_AURA_MOD_TAUNT)))
if (!isWorldBoss() && (GetLastLeashExtensionTime() + 12 > GameTime::GetGameTime().count() || HasAuraType(SPELL_AURA_MOD_TAUNT)))
return true;
}
@@ -2667,10 +2673,13 @@ bool Creature::CanCreatureAttack(Unit const* victim, bool skipDistCheck) const
return true;
// xinef: added size factor for huge npcs
float dist = std::min<float>(GetMap()->GetVisibilityRange() + GetObjectSize() * 2, 150.0f);
float dist = std::min<float>(GetDetectionRange() + GetObjectSize() * 2, 150.0f);
if (Unit* unit = GetCharmerOrOwner())
{
dist = std::min<float>(GetMap()->GetVisibilityRange() + GetObjectSize() * 2, 150.0f);
return victim->IsWithinDist(unit, dist);
}
else
{
// to prevent creatures in air ignore attacks because distance is already too high...
@@ -3030,8 +3039,11 @@ std::string Creature::GetScriptName() const
uint32 Creature::GetScriptId() const
{
if (CreatureData const* creatureData = GetCreatureData())
if (uint32 scriptId = creatureData->ScriptId)
{
uint32 scriptId = creatureData->ScriptId;
if (scriptId && GetEntry() == creatureData->id1)
return scriptId;
}
return sObjectMgr->GetCreatureTemplate(GetEntry())->ScriptID;
}
@@ -3664,35 +3676,31 @@ bool Creature::IsNotReachableAndNeedRegen() const
return false;
}
time_t Creature::GetLastDamagedTime() const
std::shared_ptr<time_t> const& Creature::GetLastLeashExtensionTimePtr() const
{
if (!_lastDamagedTime)
return time_t(0);
return *_lastDamagedTime;
if (m_lastLeashExtensionTime == nullptr)
m_lastLeashExtensionTime = std::make_shared<time_t>(time(nullptr));
return m_lastLeashExtensionTime;
}
std::shared_ptr<time_t> const& Creature::GetLastDamagedTimePtr() const
void Creature::SetLastLeashExtensionTimePtr(std::shared_ptr<time_t> const& timer)
{
return _lastDamagedTime;
m_lastLeashExtensionTime = timer;
}
void Creature::SetLastDamagedTime(time_t val)
void Creature::ClearLastLeashExtensionTimePtr()
{
if (val > 0)
{
if (_lastDamagedTime)
*_lastDamagedTime = val;
else
_lastDamagedTime = std::make_shared<time_t>(val);
}
else
_lastDamagedTime.reset();
m_lastLeashExtensionTime.reset();
}
void Creature::SetLastDamagedTimePtr(std::shared_ptr<time_t> const& val)
time_t Creature::GetLastLeashExtensionTime() const
{
_lastDamagedTime = val;
return *GetLastLeashExtensionTimePtr();
}
void Creature::UpdateLeashExtensionTime()
{
(*GetLastLeashExtensionTimePtr()) = time(nullptr);
}
bool Creature::CanPeriodicallyCallForAssistance() const