Core/Spells: rework part 5: GameObject casting

Closes #21330
Closes #18885
Ref #18752

(cherry picked from commit 45c5e1b9d63796d168339a44f63418f220cf2403)
This commit is contained in:
ariel-
2021-08-28 15:59:11 +02:00
committed by Shauren
parent 65dca120d3
commit 962f6d7988
46 changed files with 2775 additions and 2419 deletions
@@ -517,6 +517,8 @@ GameObject* GameObject::CreateGameObjectFromDB(ObjectGuid::LowType spawnId, Map*
void GameObject::Update(uint32 diff)
{
m_Events.Update(diff);
if (AI())
AI()->UpdateAI(diff);
else if (!AIM_Initialize())
@@ -825,8 +827,10 @@ void GameObject::Update(uint32 diff)
else if (Unit* target = ObjectAccessor::GetUnit(*this, m_lootStateUnitGUID))
{
// Some traps do not have a spell but should be triggered
CastSpellExtraArgs args;
args.SetOriginalCaster(GetOwnerGUID());
if (goInfo->trap.spell)
CastSpell(target, goInfo->trap.spell);
CastSpell(target, goInfo->trap.spell, args);
// Template value or 4 seconds
m_cooldownTime = GameTime::GetGameTimeMS() + (goInfo->trap.cooldown ? goInfo->trap.cooldown : uint32(4)) * IN_MILLISECONDS;
@@ -1307,11 +1311,6 @@ bool GameObject::IsDestructibleBuilding() const
return gInfo->type == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING;
}
Unit* GameObject::GetOwner() const
{
return ObjectAccessor::GetUnit(*this, GetOwnerGUID());
}
void GameObject::SaveRespawnTime(uint32 forceDelay, bool savetodb)
{
if (m_goData && (forceDelay || m_respawnTime > GameTime::GetGameTime()) && m_spawnedByDefault)
@@ -2211,68 +2210,6 @@ void GameObject::Use(Unit* user)
CastSpell(user, spellId);
}
void GameObject::CastSpell(Unit* target, uint32 spellId, bool triggered /* = true*/)
{
CastSpell(target, spellId, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE);
}
void GameObject::CastSpell(Unit* target, uint32 spellId, TriggerCastFlags triggered)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID());
if (!spellInfo)
return;
bool self = false;
for (SpellEffectInfo const* effect : spellInfo->GetEffects())
{
if (effect && effect->TargetA.GetTarget() == TARGET_UNIT_CASTER)
{
self = true;
break;
}
}
if (self)
{
if (target)
target->CastSpell(target, spellInfo->Id, triggered);
return;
}
//summon world trigger
Creature* trigger = SummonTrigger(GetPositionX(), GetPositionY(), GetPositionZ(), 0, spellInfo->CalcCastTime() + 100);
if (!trigger)
return;
// remove immunity flags, to allow spell to target anything
trigger->SetImmuneToAll(false);
PhasingHandler::InheritPhaseShift(trigger, this);
CastSpellExtraArgs args;
args.TriggerFlags = triggered;
if (Unit* owner = GetOwner())
{
trigger->SetFaction(owner->GetFaction());
if (owner->HasUnitFlag(UNIT_FLAG_PVP_ATTACKABLE))
trigger->AddUnitFlag(UNIT_FLAG_PVP_ATTACKABLE);
// copy pvp state flags from owner
trigger->SetPvpFlags(owner->GetPvpFlags());
// needed for GO casts for proper target validation checks
trigger->SetOwnerGUID(owner->GetGUID());
args.OriginalCaster = owner->GetGUID();
trigger->CastSpell(target ? target : trigger, spellInfo->Id, args);
}
else
{
trigger->SetFaction(spellInfo->IsPositive() ? FACTION_FRIENDLY : FACTION_MONSTER);
// Set owner guid for target if no owner available - needed by trigger auras
// - trigger gets despawned and there's no caster avalible (see AuraEffect::TriggerSpell())
args.OriginalCaster = target ? target->GetGUID() : ObjectGuid::Empty;
trigger->CastSpell(target ? target : trigger, spellInfo->Id, args);
}
}
void GameObject::SendCustomAnim(uint32 anim)
{
WorldPackets::GameObject::GameObjectCustomAnim customAnim;
@@ -2380,7 +2317,7 @@ void GameObject::SetWorldRotationAngles(float z_rot, float y_rot, float x_rot)
SetWorldRotation(quat.x, quat.y, quat.z, quat.w);
}
void GameObject::ModifyHealth(int32 change, Unit* attackerOrHealer /*= nullptr*/, uint32 spellId /*= 0*/)
void GameObject::ModifyHealth(int32 change, WorldObject* attackerOrHealer /*= nullptr*/, uint32 spellId /*= 0*/)
{
if (!m_goValue.Building.MaxHealth || !change)
return;
@@ -2399,10 +2336,8 @@ void GameObject::ModifyHealth(int32 change, Unit* attackerOrHealer /*= nullptr*/
// Set the health bar, value = 255 * healthPct;
SetGoAnimProgress(m_goValue.Building.Health * 255 / m_goValue.Building.MaxHealth);
Player* player = attackerOrHealer ? attackerOrHealer->GetCharmerOrOwnerPlayerOrPlayerItself() : nullptr;
// dealing damage, send packet
if (player)
if (Player* player = attackerOrHealer ? attackerOrHealer->GetCharmerOrOwnerPlayerOrPlayerItself() : nullptr)
{
WorldPackets::GameObject::DestructibleBuildingDamage packet;
packet.Caster = attackerOrHealer->GetGUID(); // todo: this can be a GameObject
@@ -2425,11 +2360,10 @@ void GameObject::ModifyHealth(int32 change, Unit* attackerOrHealer /*= nullptr*/
if (newState == GetDestructibleState())
return;
/// @todo: pass attackerOrHealer instead of player
SetDestructibleState(newState, player, false);
SetDestructibleState(newState, attackerOrHealer, false);
}
void GameObject::SetDestructibleState(GameObjectDestructibleState state, Player* eventInvoker /*= nullptr*/, bool setHealth /*= false*/)
void GameObject::SetDestructibleState(GameObjectDestructibleState state, WorldObject* attackerOrHealer /*= nullptr*/, bool setHealth /*= false*/)
{
// the user calling this must know he is already operating on destructible gameobject
ASSERT(GetGoType() == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING);
@@ -2448,8 +2382,8 @@ void GameObject::SetDestructibleState(GameObjectDestructibleState state, Player*
break;
case GO_DESTRUCTIBLE_DAMAGED:
{
EventInform(m_goInfo->destructibleBuilding.DamagedEvent, eventInvoker);
AI()->Damaged(eventInvoker, m_goInfo->destructibleBuilding.DamagedEvent);
EventInform(m_goInfo->destructibleBuilding.DamagedEvent, attackerOrHealer);
AI()->Damaged(attackerOrHealer, m_goInfo->destructibleBuilding.DamagedEvent);
RemoveFlag(GO_FLAG_DESTROYED);
AddFlag(GO_FLAG_DAMAGED);
@@ -2473,11 +2407,12 @@ void GameObject::SetDestructibleState(GameObjectDestructibleState state, Player*
}
case GO_DESTRUCTIBLE_DESTROYED:
{
EventInform(m_goInfo->destructibleBuilding.DestroyedEvent, eventInvoker);
AI()->Destroyed(eventInvoker, m_goInfo->destructibleBuilding.DestroyedEvent);
if (eventInvoker)
if (Battleground* bg = eventInvoker->GetBattleground())
bg->DestroyGate(eventInvoker, this);
EventInform(m_goInfo->destructibleBuilding.DestroyedEvent, attackerOrHealer);
AI()->Destroyed(attackerOrHealer, m_goInfo->destructibleBuilding.DestroyedEvent);
if (attackerOrHealer && attackerOrHealer->GetTypeId() == TYPEID_PLAYER)
if (Battleground* bg = attackerOrHealer->ToPlayer()->GetBattleground())
bg->DestroyGate(attackerOrHealer->ToPlayer(), this);
RemoveFlag(GO_FLAG_DAMAGED);
AddFlag(GO_FLAG_DESTROYED);
@@ -2498,7 +2433,7 @@ void GameObject::SetDestructibleState(GameObjectDestructibleState state, Player*
}
case GO_DESTRUCTIBLE_REBUILDING:
{
EventInform(m_goInfo->destructibleBuilding.RebuildingEvent, eventInvoker);
EventInform(m_goInfo->destructibleBuilding.RebuildingEvent, attackerOrHealer);
RemoveFlag(GameObjectFlags(GO_FLAG_DAMAGED | GO_FLAG_DESTROYED));
uint32 modelId = m_goInfo->displayId;