Skip to content

Commit

Permalink
[Core/Unit] Fix a crash by taken damage. (#379)
Browse files Browse the repository at this point in the history
  • Loading branch information
leelf00 authored Nov 24, 2024
1 parent 427a4c6 commit 7cfa358
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 12 deletions.
16 changes: 13 additions & 3 deletions src/server/game/AI/CreatureAI.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* This file is part of the Pandaria 5.4.8 Project. See THANKS file for Copyright information
* This file is part of the Legends of Azeroth Pandaria Project. See THANKS file for Copyright information
*
* 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
Expand Down Expand Up @@ -80,13 +80,23 @@ class TC_GAME_API CreatureAI : public UnitAI
Creature* DoSummonFlyer(uint32 entry, WorldObject* obj, float flightZ, float radius = 5.0f, uint32 despawnTime = 30000, TempSummonType summonType = TEMPSUMMON_CORPSE_TIMED_DESPAWN);

public:
void Talk(uint8 id, WorldObject const* whisperTarget = nullptr);
void TalkToMap(uint8 id, WorldObject const* whisperTarget = nullptr);
// EnumUtils: DESCRIBE THIS (in CreatureAI::)
enum EvadeReason
{
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, // anything else
};

explicit CreatureAI(Creature* creature);

virtual ~CreatureAI();

void Talk(uint8 id, WorldObject const* whisperTarget = nullptr);
void TalkToMap(uint8 id, WorldObject const* whisperTarget = nullptr);

/// == Reactions At =================================

// Called if IsVisible(Unit* who) is true at each who move, reaction at visibility zone enter
Expand Down
23 changes: 22 additions & 1 deletion src/server/game/Entities/Creature/Creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGrou
m_PlayerDamageReq(0), m_lootRecipient(), m_lootRecipientGroup(0), m_corpseRemoveTime(0), m_respawnTime(0),
m_respawnDelay(300), m_corpseDelay(60), m_wanderDistance(0.0f), m_WalkMode(0.0f), 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_cannotReachTarget(false), m_cannotReachTimer(0), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),
m_creatureInfo(nullptr), m_creatureData(nullptr), m_path_id(0), m_formation(nullptr), m_triggerJustAppeared(false), m_respawnDelayMax(0), dynamicHealthPlayersCount(0)
{
m_regenTimer = 0;
Expand Down Expand Up @@ -682,6 +682,15 @@ void Creature::Update(uint32 diff)
m_regenTimer += diff;

Regenerate();

if (CanNotReachTarget() && !IsInEvadeMode() && !GetMap()->IsRaid())
{
m_cannotReachTimer += diff;
if (m_cannotReachTimer >= CREATURE_NOPATH_EVADE_TIME)
if (CreatureAI* ai = AI())
ai->EnterEvadeMode(); // TODO missing EVADE_REASON
// ai->EnterEvadeMode(CreatureAI::EVADE_REASON_NO_PATH);
}
break;
}
default:
Expand Down Expand Up @@ -2737,6 +2746,18 @@ uint32 Creature::GetPetAutoSpellOnPos(uint8 pos) const
return m_charmInfo->GetCharmSpell(pos)->GetAction();
}

void Creature::SetCannotReachTarget(bool cannotReach)
{
if (cannotReach == m_cannotReachTarget)
return;
m_cannotReachTarget = cannotReach;
m_cannotReachTimer = 0;

if (cannotReach)
TC_LOG_DEBUG("entities.unit.chase", "Creature::SetCannotReachTarget() called with true");
// TC_LOG_DEBUG("entities.unit.chase", "Creature::SetCannotReachTarget() called with true. Details: s%", GetDebugInfo()); // TODO GetDebugInfo missing
}

void Creature::SetPosition(float x, float y, float z, float o)
{
// prevent crash when a bad coord is sent by the client
Expand Down
7 changes: 7 additions & 0 deletions src/server/game/Entities/Creature/Creature.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,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();
Expand Down Expand Up @@ -493,6 +494,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);
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()); }

Expand Down Expand Up @@ -592,6 +596,9 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma

bool m_AlreadyCallAssistance;
bool m_AlreadySearchedAssistance;
bool m_cannotReachTarget;
uint32 m_cannotReachTimer;

bool m_regenHealth;
bool m_regenMana = true;
bool m_AI_locked;
Expand Down
12 changes: 8 additions & 4 deletions src/server/game/Entities/Creature/CreatureData.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,14 @@ struct TC_GAME_API CreatureMovementData
std::string ToString() const;
};

static uint8 const MAX_KILL_CREDIT = 2;
static uint32 const MAX_CREATURE_MODELS = 4;
static uint32 const MAX_CREATURE_QUEST_ITEMS = 6;
static uint32 const MAX_CREATURE_SPELLS = 8;
static const uint32 CREATURE_REGEN_INTERVAL = 2 * IN_MILLISECONDS;
static const uint32 PET_FOCUS_REGEN_INTERVAL = 4 * IN_MILLISECONDS;
static const uint32 CREATURE_NOPATH_EVADE_TIME = 5 * IN_MILLISECONDS;

static const uint8 MAX_KILL_CREDIT = 2;
static const uint32 MAX_CREATURE_MODELS = 4;
static const uint32 MAX_CREATURE_QUEST_ITEMS = 6;
static const uint32 MAX_CREATURE_SPELLS = 8;

struct CreatureModel
{
Expand Down
21 changes: 17 additions & 4 deletions src/server/game/Entities/Unit/Unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1638,7 +1638,12 @@ 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()))
auto canTakeMeleeDamage = [&]()
{
return victim->IsAlive() && !victim->HasUnitState(UNIT_STATE_IN_FLIGHT) && (victim->GetTypeId() != TYPEID_UNIT || !victim->ToCreature()->IsEvadingAttacks());
};

if (!canTakeMeleeDamage())
return;

// Hmmmm dont like this emotes client must by self do all animations
Expand Down Expand Up @@ -1679,9 +1684,17 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
}
}

// Call default DealDamage
CleanDamage cleanDamage(damageInfo->cleanDamage, damageInfo->absorb, damageInfo->attackType, damageInfo->hitOutCome);
DealDamage(victim, damageInfo->damage, &cleanDamage, DIRECT_DAMAGE, SpellSchoolMask(damageInfo->damageSchoolMask), NULL, durabilityLoss);
// TODO multi damageschool
if (!canTakeMeleeDamage() || (!damageInfo->damage && !damageInfo->absorb && !damageInfo->resist))
{

}
else
{
// Call default DealDamage
CleanDamage cleanDamage(damageInfo->cleanDamage, damageInfo->absorb, damageInfo->attackType, damageInfo->hitOutCome);
DealDamage(victim, damageInfo->damage, &cleanDamage, DIRECT_DAMAGE, SpellSchoolMask(damageInfo->damageSchoolMask), nullptr, durabilityLoss);
}

// If this is a creature and it attacks from behind it has a probability to daze it's victim
if ((damageInfo->hitOutCome == MELEE_HIT_CRIT || damageInfo->hitOutCome == MELEE_HIT_CRUSHING || damageInfo->hitOutCome == MELEE_HIT_NORMAL || damageInfo->hitOutCome == MELEE_HIT_GLANCING) &&
Expand Down

0 comments on commit 7cfa358

Please sign in to comment.