mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
Core/AreaTriggers: Handle exit areatrigger on player map change (#31077)
This commit is contained in:
@@ -867,53 +867,65 @@ void AreaTrigger::HandleUnitEnterExit(std::vector<Unit*> const& newTargetList)
|
||||
|
||||
// Handle after _insideUnits have been reinserted so we can use GetInsideUnits() in hooks
|
||||
for (Unit* unit : enteringUnits)
|
||||
{
|
||||
if (Player* player = unit->ToPlayer())
|
||||
{
|
||||
if (player->isDebugAreaTriggers)
|
||||
ChatHandler(player->GetSession()).PSendSysMessage(LANG_DEBUG_AREATRIGGER_ENTITY_ENTERED, GetEntry(), IsCustom(), IsStaticSpawn(), _spawnId);
|
||||
|
||||
player->UpdateQuestObjectiveProgress(QUEST_OBJECTIVE_AREA_TRIGGER_ENTER, GetEntry(), 1);
|
||||
|
||||
if (GetTemplate()->ActionSetId)
|
||||
player->UpdateCriteria(CriteriaType::EnterAreaTriggerWithActionSet, GetTemplate()->ActionSetId);
|
||||
}
|
||||
|
||||
DoActions(unit);
|
||||
|
||||
_ai->OnUnitEnter(unit);
|
||||
}
|
||||
HandleUnitEnter(unit);
|
||||
|
||||
for (ObjectGuid const& exitUnitGuid : exitUnits)
|
||||
{
|
||||
if (Unit* leavingUnit = ObjectAccessor::GetUnit(*this, exitUnitGuid))
|
||||
{
|
||||
if (Player* player = leavingUnit->ToPlayer())
|
||||
{
|
||||
if (player->isDebugAreaTriggers)
|
||||
ChatHandler(player->GetSession()).PSendSysMessage(LANG_DEBUG_AREATRIGGER_ENTITY_LEFT, GetEntry(), IsCustom(), IsStaticSpawn(), _spawnId);
|
||||
HandleUnitExitInternal(leavingUnit);
|
||||
|
||||
player->UpdateQuestObjectiveProgress(QUEST_OBJECTIVE_AREA_TRIGGER_EXIT, GetEntry(), 1);
|
||||
|
||||
if (GetTemplate()->ActionSetId)
|
||||
player->UpdateCriteria(CriteriaType::LeaveAreaTriggerWithActionSet, GetTemplate()->ActionSetId);
|
||||
}
|
||||
|
||||
UndoActions(leavingUnit);
|
||||
|
||||
_ai->OnUnitExit(leavingUnit);
|
||||
}
|
||||
}
|
||||
|
||||
if (std::ranges::any_of(_insideUnits, [](ObjectGuid const& guid) { return guid.IsPlayer(); }))
|
||||
SetAreaTriggerFlag(AreaTriggerFieldFlags::HasPlayers);
|
||||
else
|
||||
RemoveAreaTriggerFlag(AreaTriggerFieldFlags::HasPlayers);
|
||||
UpdateHasPlayersFlag();
|
||||
|
||||
if (IsStaticSpawn())
|
||||
setActive(!_insideUnits.empty());
|
||||
}
|
||||
|
||||
void AreaTrigger::HandleUnitEnter(Unit* unit)
|
||||
{
|
||||
if (Player* player = unit->ToPlayer())
|
||||
{
|
||||
if (player->isDebugAreaTriggers)
|
||||
ChatHandler(player->GetSession()).PSendSysMessage(LANG_DEBUG_AREATRIGGER_ENTITY_ENTERED, GetEntry(), IsCustom(), IsStaticSpawn(), _spawnId);
|
||||
|
||||
player->UpdateQuestObjectiveProgress(QUEST_OBJECTIVE_AREA_TRIGGER_ENTER, GetEntry(), 1);
|
||||
|
||||
if (GetTemplate()->ActionSetId)
|
||||
player->UpdateCriteria(CriteriaType::EnterAreaTriggerWithActionSet, GetTemplate()->ActionSetId);
|
||||
}
|
||||
|
||||
DoActions(unit);
|
||||
|
||||
_ai->OnUnitEnter(unit);
|
||||
unit->EnterAreaTrigger(this);
|
||||
}
|
||||
|
||||
void AreaTrigger::HandleUnitExitInternal(Unit* unit)
|
||||
{
|
||||
if (Player* player = unit->ToPlayer())
|
||||
{
|
||||
if (player->isDebugAreaTriggers)
|
||||
ChatHandler(player->GetSession()).PSendSysMessage(LANG_DEBUG_AREATRIGGER_ENTITY_LEFT, GetEntry(), IsCustom(), IsStaticSpawn(), _spawnId);
|
||||
|
||||
player->UpdateQuestObjectiveProgress(QUEST_OBJECTIVE_AREA_TRIGGER_EXIT, GetEntry(), 1);
|
||||
|
||||
if (GetTemplate()->ActionSetId)
|
||||
player->UpdateCriteria(CriteriaType::LeaveAreaTriggerWithActionSet, GetTemplate()->ActionSetId);
|
||||
}
|
||||
|
||||
UndoActions(unit);
|
||||
|
||||
_ai->OnUnitExit(unit);
|
||||
unit->ExitAreaTrigger(this);
|
||||
}
|
||||
|
||||
void AreaTrigger::HandleUnitExit(Unit* unit)
|
||||
{
|
||||
_insideUnits.erase(unit->GetGUID());
|
||||
|
||||
HandleUnitExitInternal(unit);
|
||||
|
||||
UpdateHasPlayersFlag();
|
||||
}
|
||||
|
||||
uint32 AreaTrigger::GetScriptId() const
|
||||
{
|
||||
if (_spawnId)
|
||||
@@ -1177,7 +1189,7 @@ void AreaTrigger::UndoActions(Unit* unit)
|
||||
case AREATRIGGER_ACTION_CAST:
|
||||
[[fallthrough]];
|
||||
case AREATRIGGER_ACTION_ADDAURA:
|
||||
unit->RemoveAurasDueToSpell(action.Param, GetCasterGuid());
|
||||
unit->RemoveAurasDueToSpell(action.Param, GetCasterGuid());
|
||||
break;
|
||||
case AREATRIGGER_ACTION_TAVERN:
|
||||
if (Player* player = unit->ToPlayer())
|
||||
@@ -1185,7 +1197,7 @@ void AreaTrigger::UndoActions(Unit* unit)
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1442,6 +1454,14 @@ void AreaTrigger::UpdateOverridePosition()
|
||||
GetMap()->AreaTriggerRelocation(this, x, y, z, orientation);
|
||||
}
|
||||
|
||||
void AreaTrigger::UpdateHasPlayersFlag()
|
||||
{
|
||||
if (std::ranges::any_of(_insideUnits, [](ObjectGuid const& guid) { return guid.IsPlayer(); }))
|
||||
SetAreaTriggerFlag(AreaTriggerFieldFlags::HasPlayers);
|
||||
else
|
||||
RemoveAreaTriggerFlag(AreaTriggerFieldFlags::HasPlayers);
|
||||
}
|
||||
|
||||
void AreaTrigger::DebugVisualizePosition()
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
|
||||
@@ -193,6 +193,8 @@ class TC_GAME_API AreaTrigger final : public WorldObject, public GridObject<Area
|
||||
|
||||
void UpdateShape();
|
||||
|
||||
void HandleUnitExit(Unit* unit);
|
||||
|
||||
UF::UpdateField<UF::AreaTriggerData, int32(WowCS::EntityFragment::CGObject), TYPEID_AREATRIGGER> m_areaTriggerData;
|
||||
|
||||
protected:
|
||||
@@ -219,6 +221,8 @@ class TC_GAME_API AreaTrigger final : public WorldObject, public GridObject<Area
|
||||
void SearchUnitInDisk(UF::AreaTriggerDisk const& disk, std::vector<Unit*>& targetList);
|
||||
void SearchUnitInBoundedPlane(UF::AreaTriggerBoundedPlane const& boundedPlane, std::vector<Unit*>& targetList);
|
||||
void HandleUnitEnterExit(std::vector<Unit*> const& targetList);
|
||||
void HandleUnitEnter(Unit* unit);
|
||||
void HandleUnitExitInternal(Unit* unit);
|
||||
|
||||
void DoActions(Unit* unit);
|
||||
void UndoActions(Unit* unit);
|
||||
@@ -231,6 +235,8 @@ class TC_GAME_API AreaTrigger final : public WorldObject, public GridObject<Area
|
||||
Position const* GetOrbitCenterPosition() const;
|
||||
Position CalculateOrbitPosition() const;
|
||||
|
||||
void UpdateHasPlayersFlag();
|
||||
|
||||
void DebugVisualizePosition(); // Debug purpose only
|
||||
|
||||
ObjectGuid::LowType _spawnId;
|
||||
|
||||
@@ -21839,6 +21839,9 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent)
|
||||
|
||||
pet->CombatStop();
|
||||
|
||||
// exit areatriggers before saving to remove auras applied by them
|
||||
pet->ExitAllAreaTriggers();
|
||||
|
||||
// only if current pet in slot
|
||||
pet->SavePetToDB(mode);
|
||||
|
||||
|
||||
@@ -5499,6 +5499,23 @@ void Unit::RemoveAllAreaTriggers(AreaTriggerRemoveReason reason /*= AreaTriggerR
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::EnterAreaTrigger(AreaTrigger* areaTrigger)
|
||||
{
|
||||
m_insideAreaTriggers.push_back(areaTrigger);
|
||||
}
|
||||
|
||||
void Unit::ExitAreaTrigger(AreaTrigger* areaTrigger)
|
||||
{
|
||||
std::erase(m_insideAreaTriggers, areaTrigger);
|
||||
}
|
||||
|
||||
void Unit::ExitAllAreaTriggers()
|
||||
{
|
||||
AreaTriggerList atList = std::move(m_insideAreaTriggers);
|
||||
for (AreaTrigger* at : atList)
|
||||
at->HandleUnitExit(this);
|
||||
}
|
||||
|
||||
void Unit::SendSpellNonMeleeDamageLog(SpellNonMeleeDamage const* log)
|
||||
{
|
||||
WorldPackets::CombatLog::SpellNonMeleeDamageLog packet;
|
||||
@@ -10083,6 +10100,7 @@ void Unit::RemoveFromWorld()
|
||||
RemoveAllGameObjects();
|
||||
RemoveAllDynObjects();
|
||||
RemoveAllAreaTriggers(AreaTriggerRemoveReason::UnitDespawn);
|
||||
ExitAllAreaTriggers(); // exit all areatriggers the unit is in
|
||||
|
||||
ExitVehicle(); // Remove applied auras with SPELL_AURA_CONTROL_VEHICLE
|
||||
UnsummonAllTotems();
|
||||
|
||||
@@ -1639,6 +1639,12 @@ class TC_GAME_API Unit : public WorldObject
|
||||
void RemoveAreaTrigger(AuraEffect const* aurEff);
|
||||
void RemoveAllAreaTriggers(AreaTriggerRemoveReason reason = AreaTriggerRemoveReason::Default);
|
||||
|
||||
void EnterAreaTrigger(AreaTrigger* areaTrigger);
|
||||
void ExitAreaTrigger(AreaTrigger* areaTrigger);
|
||||
|
||||
std::vector<AreaTrigger*> const& GetInsideAreaTriggers() const { return m_insideAreaTriggers; }
|
||||
void ExitAllAreaTriggers();
|
||||
|
||||
void ModifyAuraState(AuraStateType flag, bool apply);
|
||||
uint32 BuildAuraStateUpdateForTarget(Unit const* target) const;
|
||||
bool HasAuraState(AuraStateType flag, SpellInfo const* spellProto = nullptr, Unit const* Caster = nullptr) const;
|
||||
@@ -1896,6 +1902,7 @@ class TC_GAME_API Unit : public WorldObject
|
||||
|
||||
typedef std::vector<AreaTrigger*> AreaTriggerList;
|
||||
AreaTriggerList m_areaTrigger;
|
||||
AreaTriggerList m_insideAreaTriggers;
|
||||
|
||||
uint32 m_transformSpell;
|
||||
|
||||
|
||||
@@ -632,6 +632,9 @@ void WorldSession::LogoutPlayer(bool save)
|
||||
|
||||
_player->FailQuestsWithFlag(QUEST_FLAGS_FAIL_ON_LOGOUT);
|
||||
|
||||
// exit areatriggers before saving to remove auras applied by them
|
||||
_player->ExitAllAreaTriggers();
|
||||
|
||||
///- empty buyback items and save the player in the database
|
||||
// some save parts only correctly work in case player present in map/player_lists (pets, etc)
|
||||
if (save)
|
||||
|
||||
Reference in New Issue
Block a user