mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
Core/GameObject: Implement GAMEOBJECT_TYPE_NEW_FLAG_DROP (#28021)
This commit is contained in:
@@ -503,6 +503,51 @@ void SetTransportAutoCycleBetweenStopFrames::Execute(GameObjectTypeBase& type) c
|
||||
if (Transport* transport = dynamic_cast<Transport*>(&type))
|
||||
transport->SetAutoCycleBetweenStopFrames(_on);
|
||||
}
|
||||
|
||||
class NewFlag : public GameObjectTypeBase
|
||||
{
|
||||
public:
|
||||
explicit NewFlag(GameObject& owner) : GameObjectTypeBase(owner), _state(FlagState::InBase), _respawnTime(0) { }
|
||||
|
||||
void SetState(FlagState newState, Player* player)
|
||||
{
|
||||
FlagState oldState = _state;
|
||||
_state = newState;
|
||||
_owner.UpdateObjectVisibility();
|
||||
if (ZoneScript* zoneScript = _owner.GetZoneScript())
|
||||
zoneScript->OnFlagStateChange(&_owner, oldState, _state, player);
|
||||
|
||||
if (newState == FlagState::Respawning)
|
||||
_respawnTime = GameTime::GetGameTimeMS() + _owner.GetGOInfo()->newflag.RespawnTime;
|
||||
else
|
||||
_respawnTime = 0;
|
||||
}
|
||||
|
||||
void Update([[maybe_unused]] uint32 diff) override
|
||||
{
|
||||
if (_state == FlagState::Respawning && GameTime::GetGameTimeMS() >= _respawnTime)
|
||||
SetState(FlagState::InBase, nullptr);
|
||||
}
|
||||
|
||||
bool IsNeverVisibleFor([[maybe_unused]] WorldObject const* seer, [[maybe_unused]] bool allowServersideObjects) const override
|
||||
{
|
||||
return _state != FlagState::InBase;
|
||||
}
|
||||
|
||||
private:
|
||||
FlagState _state;
|
||||
time_t _respawnTime;
|
||||
};
|
||||
|
||||
SetNewFlagState::SetNewFlagState(FlagState state, Player* player) : _state(state), _player(player)
|
||||
{
|
||||
}
|
||||
|
||||
void SetNewFlagState::Execute(GameObjectTypeBase& type) const
|
||||
{
|
||||
if (NewFlag* newFlag = dynamic_cast<NewFlag*>(&type))
|
||||
newFlag->SetState(_state, _player);
|
||||
}
|
||||
}
|
||||
|
||||
GameObject::GameObject() : WorldObject(false), MapObject(),
|
||||
@@ -797,6 +842,9 @@ bool GameObject::Create(uint32 entry, Map* map, Position const& pos, QuaternionD
|
||||
m_invisibility.AddValue(INVISIBILITY_TRAP, 300);
|
||||
}
|
||||
break;
|
||||
case GAMEOBJECT_TYPE_NEW_FLAG:
|
||||
m_goTypeImpl = std::make_unique<GameObjectType::NewFlag>(*this);
|
||||
break;
|
||||
case GAMEOBJECT_TYPE_PHASEABLE_MO:
|
||||
RemoveFlag(GameObjectFlags(0xF00));
|
||||
SetFlag(GameObjectFlags((m_goInfo->phaseableMO.AreaNameSet & 0xF) << 8));
|
||||
@@ -1317,6 +1365,13 @@ void GameObject::Update(uint32 diff)
|
||||
else if (!GetOwnerGUID().IsEmpty() || GetSpellId())
|
||||
{
|
||||
SetRespawnTime(0);
|
||||
|
||||
if (GetGoType() == GAMEOBJECT_TYPE_NEW_FLAG_DROP)
|
||||
{
|
||||
if (GameObject* go = GetMap()->GetGameObject(GetOwnerGUID()))
|
||||
go->HandleCustomTypeCommand(GameObjectType::SetNewFlagState(FlagState::InBase, nullptr));
|
||||
}
|
||||
|
||||
Delete();
|
||||
return;
|
||||
}
|
||||
@@ -1807,6 +1862,9 @@ bool GameObject::IsNeverVisibleFor(WorldObject const* seer, bool allowServerside
|
||||
if (!GetDisplayId() && GetGOInfo()->IsDisplayMandatory())
|
||||
return true;
|
||||
|
||||
if (m_goTypeImpl)
|
||||
return m_goTypeImpl->IsNeverVisibleFor(seer, allowServersideObjects);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2892,8 +2950,48 @@ void GameObject::Use(Unit* user)
|
||||
return;
|
||||
|
||||
spellId = info->newflag.pickupSpell;
|
||||
spellCaster = nullptr;
|
||||
break;
|
||||
}
|
||||
case GAMEOBJECT_TYPE_NEW_FLAG_DROP:
|
||||
{
|
||||
GameObjectTemplate const* info = GetGOInfo();
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
if (user->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
if (GameObject* owner = GetMap()->GetGameObject(GetOwnerGUID()))
|
||||
{
|
||||
if (owner->GetGoType() == GAMEOBJECT_TYPE_NEW_FLAG)
|
||||
{
|
||||
// friendly with enemy flag means you're taking it
|
||||
bool defenderInteract = !owner->IsFriendlyTo(user);
|
||||
if (defenderInteract && owner->GetGOInfo()->newflag.ReturnonDefenderInteract)
|
||||
{
|
||||
Delete();
|
||||
owner->HandleCustomTypeCommand(GameObjectType::SetNewFlagState(FlagState::InBase, user->ToPlayer()));
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we let the owner cast the spell for now
|
||||
// so that caster guid is set correctly
|
||||
SpellCastResult result = owner->CastSpell(user, owner->GetGOInfo()->newflag.pickupSpell, CastSpellExtraArgs(TRIGGERED_FULL_MASK));
|
||||
if (result == SPELL_CAST_OK)
|
||||
{
|
||||
Delete();
|
||||
owner->HandleCustomTypeCommand(GameObjectType::SetNewFlagState(FlagState::Taken, user->ToPlayer()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Delete();
|
||||
return;
|
||||
}
|
||||
case GAMEOBJECT_TYPE_ITEM_FORGE:
|
||||
{
|
||||
GameObjectTemplate const* info = GetGOInfo();
|
||||
@@ -3047,7 +3145,14 @@ void GameObject::Use(Unit* user)
|
||||
if (spellCaster)
|
||||
spellCaster->CastSpell(user, spellId, triggered);
|
||||
else
|
||||
CastSpell(user, spellId);
|
||||
{
|
||||
SpellCastResult castResult = CastSpell(user, spellId);
|
||||
if (castResult == SPELL_FAILED_SUCCESS)
|
||||
{
|
||||
if (GetGoType() == GAMEOBJECT_TYPE_NEW_FLAG)
|
||||
HandleCustomTypeCommand(GameObjectType::SetNewFlagState(FlagState::Taken, user->ToPlayer()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameObject::SendCustomAnim(uint32 anim)
|
||||
|
||||
@@ -35,6 +35,16 @@ struct Loot;
|
||||
struct TransportAnimation;
|
||||
enum TriggerCastFlags : uint32;
|
||||
|
||||
// enum for GAMEOBJECT_TYPE_NEW_FLAG
|
||||
// values taken from world state
|
||||
enum class FlagState : uint8
|
||||
{
|
||||
InBase = 1,
|
||||
Taken,
|
||||
Dropped,
|
||||
Respawning
|
||||
};
|
||||
|
||||
namespace WorldPackets
|
||||
{
|
||||
namespace Battleground
|
||||
@@ -60,6 +70,7 @@ public:
|
||||
virtual void Update([[maybe_unused]] uint32 diff) { }
|
||||
virtual void OnStateChanged([[maybe_unused]] GOState oldState, [[maybe_unused]] GOState newState) { }
|
||||
virtual void OnRelocated() { }
|
||||
virtual bool IsNeverVisibleFor([[maybe_unused]] WorldObject const* seer, [[maybe_unused]] bool allowServersideObjects) const { return false; }
|
||||
|
||||
protected:
|
||||
GameObject& _owner;
|
||||
@@ -77,6 +88,18 @@ public:
|
||||
private:
|
||||
bool _on;
|
||||
};
|
||||
|
||||
class TC_GAME_API SetNewFlagState : public GameObjectTypeBase::CustomCommand
|
||||
{
|
||||
public:
|
||||
explicit SetNewFlagState(FlagState state, Player* player);
|
||||
|
||||
void Execute(GameObjectTypeBase& type) const override;
|
||||
|
||||
private:
|
||||
FlagState _state;
|
||||
Player* _player;
|
||||
};
|
||||
}
|
||||
|
||||
union GameObjectValue
|
||||
|
||||
@@ -23,10 +23,13 @@
|
||||
|
||||
class Creature;
|
||||
class GameObject;
|
||||
class Player;
|
||||
class Unit;
|
||||
class WorldObject;
|
||||
struct CreatureData;
|
||||
|
||||
enum class FlagState : uint8;
|
||||
|
||||
class TC_GAME_API ZoneScript
|
||||
{
|
||||
public:
|
||||
@@ -62,6 +65,8 @@ class TC_GAME_API ZoneScript
|
||||
|
||||
virtual void TriggerGameEvent(uint32 gameEventId, WorldObject* source = nullptr, WorldObject* target = nullptr);
|
||||
virtual void ProcessEvent(WorldObject* /*obj*/, uint32 /*eventId*/, WorldObject* /*invoker*/) { }
|
||||
|
||||
virtual void OnFlagStateChange([[maybe_unused]] GameObject* flagInBase, [[maybe_unused]] FlagState oldValue, [[maybe_unused]] FlagState newValue, [[maybe_unused]] Player* player) { }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6209,6 +6209,19 @@ void AuraEffect::HandleBattlegroundPlayerPosition(AuraApplication const* aurApp,
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
if (!apply)
|
||||
{
|
||||
if (GameObject* gameObjectCaster = target->GetMap()->GetGameObject(GetCasterGUID()))
|
||||
{
|
||||
if (gameObjectCaster->GetGoType() == GAMEOBJECT_TYPE_NEW_FLAG)
|
||||
{
|
||||
gameObjectCaster->HandleCustomTypeCommand(GameObjectType::SetNewFlagState(FlagState::Dropped, target));
|
||||
if (GameObject* droppedFlag = gameObjectCaster->SummonGameObject(gameObjectCaster->GetGOInfo()->newflag.FlagDrop, target->GetPosition(), QuaternionData::fromEulerAnglesZYX(target->GetOrientation(), 0.f, 0.f), Seconds(gameObjectCaster->GetGOInfo()->newflag.ExpireDuration / 1000), GO_SUMMON_TIMED_DESPAWN))
|
||||
droppedFlag->SetOwnerGUID(gameObjectCaster->GetGUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BattlegroundMap* battlegroundMap = target->GetMap()->ToBattlegroundMap();
|
||||
if (!battlegroundMap)
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user