mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Unit: Some charm fixes:
* Properly restore react state after possession expires. Closes #20769. * Possessed creatures now don't override player control with random/waypoint motion * SmartAI creatures now properly re-aggress charmer after charm expires
This commit is contained in:
@@ -679,8 +679,13 @@ void SmartAI::OnCharmed(bool /*isNew*/)
|
||||
else
|
||||
me->SetWalk(!mRun);
|
||||
|
||||
if (Unit* charmer = me->GetCharmer())
|
||||
AttackStart(charmer);
|
||||
if (me->LastCharmerGUID)
|
||||
{
|
||||
if (!me->HasReactState(REACT_PASSIVE))
|
||||
if (Unit* lastCharmer = ObjectAccessor::GetUnit(*me, me->LastCharmerGUID))
|
||||
me->EngageWithTarget(lastCharmer);
|
||||
me->LastCharmerGUID.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
GetScript()->ProcessEventsFor(SMART_EVENT_CHARMED, nullptr, 0, 0, charmed);
|
||||
|
||||
@@ -9573,10 +9573,10 @@ CharmInfo::CharmInfo(Unit* unit)
|
||||
for (uint8 i = 0; i < MAX_SPELL_CHARM; ++i)
|
||||
_charmspells[i].SetActionAndType(0, ACT_DISABLED);
|
||||
|
||||
if (_unit->GetTypeId() == TYPEID_UNIT)
|
||||
if (Creature* creature = _unit->ToCreature())
|
||||
{
|
||||
_oldReactState = _unit->ToCreature()->GetReactState();
|
||||
_unit->ToCreature()->SetReactState(REACT_PASSIVE);
|
||||
_oldReactState = creature->GetReactState();
|
||||
creature->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11358,26 +11358,12 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
|
||||
GetMotionMaster()->Clear(MOTION_PRIORITY_NORMAL);
|
||||
|
||||
StopMoving();
|
||||
|
||||
// AI will schedule its own change if appropriate
|
||||
if (UnitAI* ai = GetAI())
|
||||
ai->OnCharmed(false);
|
||||
else
|
||||
ScheduleAIChange();
|
||||
}
|
||||
else if (Player* player = ToPlayer())
|
||||
{
|
||||
if (player->isAFK())
|
||||
player->ToggleAFK();
|
||||
|
||||
if (charmer->GetTypeId() == TYPEID_UNIT) // we are charmed by a creature
|
||||
{
|
||||
// change AI to charmed AI on next Update tick
|
||||
if (UnitAI* ai = GetAI())
|
||||
ai->OnCharmed(false);
|
||||
else
|
||||
player->ScheduleAIChange();
|
||||
}
|
||||
player->SetClientControl(this, false);
|
||||
}
|
||||
|
||||
@@ -11438,6 +11424,15 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
|
||||
}
|
||||
|
||||
AddUnitState(UNIT_STATE_CHARMED);
|
||||
|
||||
if ((GetTypeId() != TYPEID_PLAYER) || (charmer->GetTypeId() != TYPEID_PLAYER))
|
||||
{
|
||||
// AI will schedule its own change if appropriate
|
||||
if (UnitAI* ai = GetAI())
|
||||
ai->OnCharmed(false);
|
||||
else
|
||||
ScheduleAIChange();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -11446,15 +11441,12 @@ void Unit::RemoveCharmedBy(Unit* charmer)
|
||||
if (!IsCharmed())
|
||||
return;
|
||||
|
||||
if (!charmer)
|
||||
if (charmer)
|
||||
ASSERT(charmer == GetCharmer());
|
||||
else
|
||||
charmer = GetCharmer();
|
||||
if (charmer != GetCharmer()) // one aura overrides another?
|
||||
{
|
||||
// TC_LOG_FATAL("entities.unit", "Unit::RemoveCharmedBy: this: " UI64FMTD " true charmer: " UI64FMTD " false charmer: " UI64FMTD,
|
||||
// GetGUID(), GetCharmerGUID(), charmer->GetGUID());
|
||||
// ABORT();
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(charmer);
|
||||
|
||||
CharmType type;
|
||||
if (HasUnitState(UNIT_STATE_POSSESSED))
|
||||
@@ -11480,11 +11472,7 @@ void Unit::RemoveCharmedBy(Unit* charmer)
|
||||
|
||||
// Vehicle should not attack its passenger after he exists the seat
|
||||
if (type != CHARM_TYPE_VEHICLE)
|
||||
LastCharmerGUID = ASSERT_NOTNULL(charmer)->GetGUID();
|
||||
|
||||
// If charmer still exists
|
||||
if (!charmer)
|
||||
return;
|
||||
LastCharmerGUID = charmer->GetGUID();
|
||||
|
||||
ASSERT(type != CHARM_TYPE_POSSESS || charmer->GetTypeId() == TYPEID_PLAYER);
|
||||
ASSERT(type != CHARM_TYPE_VEHICLE || (GetTypeId() == TYPEID_UNIT && IsVehicle()));
|
||||
@@ -11527,6 +11515,19 @@ void Unit::RemoveCharmedBy(Unit* charmer)
|
||||
}
|
||||
}
|
||||
|
||||
if (Player* player = ToPlayer())
|
||||
player->SetClientControl(this, true);
|
||||
|
||||
if (playerCharmer && this != charmer->GetFirstControlled())
|
||||
playerCharmer->SendRemoveControlBar();
|
||||
|
||||
// a guardian should always have charminfo
|
||||
if (!IsGuardian())
|
||||
DeleteCharmInfo();
|
||||
|
||||
// reset confused movement for example
|
||||
ApplyControlStatesIfNeeded();
|
||||
|
||||
if (GetTypeId() != TYPEID_PLAYER || charmer->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
if (UnitAI* charmedAI = GetAI())
|
||||
@@ -11534,18 +11535,6 @@ void Unit::RemoveCharmedBy(Unit* charmer)
|
||||
else
|
||||
ScheduleAIChange();
|
||||
}
|
||||
|
||||
if (Player* player = ToPlayer())
|
||||
player->SetClientControl(this, true);
|
||||
|
||||
// a guardian should always have charminfo
|
||||
if (playerCharmer && this != charmer->GetFirstControlled())
|
||||
playerCharmer->SendRemoveControlBar();
|
||||
else if (GetTypeId() == TYPEID_PLAYER || (GetTypeId() == TYPEID_UNIT && !IsGuardian()))
|
||||
DeleteCharmInfo();
|
||||
|
||||
// reset confused movement for example
|
||||
ApplyControlStatesIfNeeded();
|
||||
}
|
||||
|
||||
void Unit::RestoreFaction()
|
||||
|
||||
@@ -340,7 +340,7 @@ enum ReactStates
|
||||
REACT_DEFENSIVE = 1,
|
||||
REACT_AGGRESSIVE = 2
|
||||
};
|
||||
static char const* DescribeReactState(ReactStates state) {
|
||||
static char const* TC_GAME_API DescribeReactState(ReactStates state) {
|
||||
switch (state)
|
||||
{
|
||||
case REACT_PASSIVE: return "PASSIVE";
|
||||
|
||||
@@ -86,7 +86,7 @@ void RandomMovementGenerator<Creature>::SetRandomLocation(Creature* owner)
|
||||
if (!owner)
|
||||
return;
|
||||
|
||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting())
|
||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE | UNIT_STATE_LOST_CONTROL) || owner->IsMovementPreventedByCasting())
|
||||
{
|
||||
AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED);
|
||||
owner->StopMoving();
|
||||
|
||||
@@ -139,7 +139,7 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* owner, uint32 diff)
|
||||
if (HasFlag(MOVEMENTGENERATOR_FLAG_FINALIZED | MOVEMENTGENERATOR_FLAG_PAUSED) || !_path || _path->nodes.empty())
|
||||
return true;
|
||||
|
||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting())
|
||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE | UNIT_STATE_LOST_CONTROL) || owner->IsMovementPreventedByCasting())
|
||||
{
|
||||
AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED);
|
||||
owner->StopMoving();
|
||||
|
||||
Reference in New Issue
Block a user