diff options
author | Treeston <treeston.mmoc@gmail.com> | 2018-08-28 12:52:50 +0200 |
---|---|---|
committer | Treeston <treeston.mmoc@gmail.com> | 2018-08-28 12:53:13 +0200 |
commit | da21ca80fc35a325df0fb0ef2f687a91121d42de (patch) | |
tree | 5cb52972690d0f1aad69e7b9b085056e5ca96a50 | |
parent | bf8c6f220c07a3316fcf0b04ac6a9a77755b9b1d (diff) |
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
5 files changed, 39 insertions, 45 deletions
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 058652563c3..a831649589a 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -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); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 75a12d61b26..e08bbb5f027 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -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,25 +11515,26 @@ void Unit::RemoveCharmedBy(Unit* charmer) } } - if (GetTypeId() != TYPEID_PLAYER || charmer->GetTypeId() == TYPEID_UNIT) - { - if (UnitAI* charmedAI = GetAI()) - charmedAI->OnCharmed(false); // AI will potentially schedule a charm ai update - 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())) + + // 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()) + charmedAI->OnCharmed(false); // AI will potentially schedule a charm ai update + else + ScheduleAIChange(); + } } void Unit::RestoreFaction() diff --git a/src/server/game/Entities/Unit/UnitDefines.h b/src/server/game/Entities/Unit/UnitDefines.h index 8c43a314999..d3a1e07bee7 100644 --- a/src/server/game/Entities/Unit/UnitDefines.h +++ b/src/server/game/Entities/Unit/UnitDefines.h @@ -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"; diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp index 5648bcf9120..a1d9f564f46 100644 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp @@ -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(); diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp index aa81d6d0d92..5de1e7b9061 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp @@ -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(); |