aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTrigger.cpp88
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTrigger.h6
-rw-r--r--src/server/game/Entities/Player/Player.cpp3
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp18
-rw-r--r--src/server/game/Entities/Unit/Unit.h7
-rw-r--r--src/server/game/Server/WorldSession.cpp3
6 files changed, 91 insertions, 34 deletions
diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
index b58668e7836..f4a556df130 100644
--- a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
+++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
@@ -867,51 +867,63 @@ 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);
+ HandleUnitEnter(unit);
- player->UpdateQuestObjectiveProgress(QUEST_OBJECTIVE_AREA_TRIGGER_ENTER, GetEntry(), 1);
+ for (ObjectGuid const& exitUnitGuid : exitUnits)
+ if (Unit* leavingUnit = ObjectAccessor::GetUnit(*this, exitUnitGuid))
+ HandleUnitExitInternal(leavingUnit);
- if (GetTemplate()->ActionSetId)
- player->UpdateCriteria(CriteriaType::EnterAreaTriggerWithActionSet, GetTemplate()->ActionSetId);
- }
+ 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);
- DoActions(unit);
+ player->UpdateQuestObjectiveProgress(QUEST_OBJECTIVE_AREA_TRIGGER_ENTER, GetEntry(), 1);
- _ai->OnUnitEnter(unit);
+ if (GetTemplate()->ActionSetId)
+ player->UpdateCriteria(CriteriaType::EnterAreaTriggerWithActionSet, GetTemplate()->ActionSetId);
}
- 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);
+ DoActions(unit);
- player->UpdateQuestObjectiveProgress(QUEST_OBJECTIVE_AREA_TRIGGER_EXIT, GetEntry(), 1);
+ _ai->OnUnitEnter(unit);
+ unit->EnterAreaTrigger(this);
+}
- if (GetTemplate()->ActionSetId)
- player->UpdateCriteria(CriteriaType::LeaveAreaTriggerWithActionSet, GetTemplate()->ActionSetId);
- }
+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);
- UndoActions(leavingUnit);
+ player->UpdateQuestObjectiveProgress(QUEST_OBJECTIVE_AREA_TRIGGER_EXIT, GetEntry(), 1);
- _ai->OnUnitExit(leavingUnit);
- }
+ if (GetTemplate()->ActionSetId)
+ player->UpdateCriteria(CriteriaType::LeaveAreaTriggerWithActionSet, GetTemplate()->ActionSetId);
}
- if (std::ranges::any_of(_insideUnits, [](ObjectGuid const& guid) { return guid.IsPlayer(); }))
- SetAreaTriggerFlag(AreaTriggerFieldFlags::HasPlayers);
- else
- RemoveAreaTriggerFlag(AreaTriggerFieldFlags::HasPlayers);
+ UndoActions(unit);
- if (IsStaticSpawn())
- setActive(!_insideUnits.empty());
+ _ai->OnUnitExit(unit);
+ unit->ExitAreaTrigger(this);
+}
+
+void AreaTrigger::HandleUnitExit(Unit* unit)
+{
+ _insideUnits.erase(unit->GetGUID());
+
+ HandleUnitExitInternal(unit);
+
+ UpdateHasPlayersFlag();
}
uint32 AreaTrigger::GetScriptId() const
@@ -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())
diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.h b/src/server/game/Entities/AreaTrigger/AreaTrigger.h
index 6d10f853063..24312586042 100644
--- a/src/server/game/Entities/AreaTrigger/AreaTrigger.h
+++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.h
@@ -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;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 6bd0b7c320b..4d828fbebc8 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -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);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index fe31ff4b40b..9925f04084b 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -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();
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index ab91bf1f62b..8d5502ff16b 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -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;
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index b62697bce23..e0daa6751d5 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -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)