diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp index b650b65fb..33cb56877 100644 --- a/src/game/CreatureAI.cpp +++ b/src/game/CreatureAI.cpp @@ -36,7 +36,7 @@ CanCastResult CreatureAI::CanCastSpell(Unit* pTarget, const SpellEntry *pSpell, if (!isTriggered) { // State does not allow - if (m_creature->hasUnitState(UNIT_STAT_CAN_NOT_REACT)) + if (m_creature->hasUnitState(UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL)) return CAST_FAIL_STATE; if (pSpell->PreventionType == SPELL_PREVENTION_TYPE_SILENCE && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp index bbb12c602..c79611c31 100644 --- a/src/game/CreatureEventAI.cpp +++ b/src/game/CreatureEventAI.cpp @@ -1319,7 +1319,7 @@ bool CreatureEventAI::CanCast(Unit* Target, SpellEntry const *Spell, bool Trigge return false; //Silenced so we can't cast - if (!Triggered && (m_creature->hasUnitState(UNIT_STAT_CAN_NOT_REACT) || + if (!Triggered && (m_creature->hasUnitState(UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL) || m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED))) return false; diff --git a/src/game/GridNotifiersImpl.h b/src/game/GridNotifiersImpl.h index c32073011..b1cda7ecf 100644 --- a/src/game/GridNotifiersImpl.h +++ b/src/game/GridNotifiersImpl.h @@ -67,7 +67,7 @@ inline void PlayerCreatureRelocationWorker(Player* pl, WorldObject const* viewPo pl->UpdateVisibilityOf(viewPoint,c); // Creature AI reaction - if (!c->hasUnitState(UNIT_STAT_FLEEING)) + if (!c->hasUnitState(UNIT_STAT_LOST_CONTROL)) { if (c->AI() && c->AI()->IsVisible(pl) && !c->IsInEvadeMode()) c->AI()->MoveInLineOfSight(pl); @@ -76,13 +76,13 @@ inline void PlayerCreatureRelocationWorker(Player* pl, WorldObject const* viewPo inline void CreatureCreatureRelocationWorker(Creature* c1, Creature* c2) { - if (!c1->hasUnitState(UNIT_STAT_FLEEING)) + if (!c1->hasUnitState(UNIT_STAT_LOST_CONTROL)) { if (c1->AI() && c1->AI()->IsVisible(c2) && !c1->IsInEvadeMode()) c1->AI()->MoveInLineOfSight(c2); } - if (!c2->hasUnitState(UNIT_STAT_FLEEING)) + if (!c2->hasUnitState(UNIT_STAT_LOST_CONTROL)) { if (c2->AI() && c2->AI()->IsVisible(c1) && !c2->IsInEvadeMode()) c2->AI()->MoveInLineOfSight(c1); diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp index c43ce0f4f..e09fc962a 100644 --- a/src/game/MotionMaster.cpp +++ b/src/game/MotionMaster.cpp @@ -41,10 +41,11 @@ void MotionMaster::Initialize() { // clear ALL movement generators (including default) + i_owner->StopMoving(); Clear(false,true); // set new default movement generator - if (i_owner->GetTypeId() == TYPEID_UNIT) + if (i_owner->GetTypeId() == TYPEID_UNIT && !i_owner->hasUnitState(UNIT_STAT_CONTROLED)) { MovementGenerator* movement = FactorySelector::selectMovementGenerator((Creature*)i_owner); push(movement == NULL ? &si_idleMovement : movement); @@ -226,7 +227,7 @@ void MotionMaster::MoveRandom() void MotionMaster::MoveTargetedHome() { - if(i_owner->hasUnitState(UNIT_STAT_FLEEING)) + if(i_owner->hasUnitState(UNIT_STAT_LOST_CONTROL)) return; Clear(false); @@ -281,6 +282,9 @@ MotionMaster::MoveChase(Unit* target, float dist, float angle) void MotionMaster::MoveFollow(Unit* target, float dist, float angle) { + if(i_owner->hasUnitState(UNIT_STAT_LOST_CONTROL)) + return; + Clear(); // ignore movement request if target not exist diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 39827a33a..0596f1891 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -2236,7 +2236,7 @@ Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask) return NULL; // not in interactive state - if (hasUnitState(UNIT_STAT_CAN_NOT_REACT)) + if (hasUnitState(UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL)) return NULL; // exist (we need look pets also for some interaction (quest/etc) @@ -2290,7 +2290,7 @@ GameObject* Player::GetGameObjectIfCanInteractWith(ObjectGuid guid, uint32 gameo return NULL; // not in interactive state - if (hasUnitState(UNIT_STAT_CAN_NOT_REACT)) + if (hasUnitState(UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL)) return NULL; if (GameObject *go = GetMap()->GetGameObject(guid)) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index c199196b9..027037a4e 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3619,6 +3619,8 @@ void Aura::HandleModPossess(bool apply, bool Real) if( apply ) { + target->addUnitState(UNIT_STAT_CONTROLED); + target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); target->SetCharmerGUID(p_caster->GetGUID()); @@ -3630,24 +3632,28 @@ void Aura::HandleModPossess(bool apply, bool Real) p_caster->SetClientControl(target, 1); p_caster->SetMover(target); - target->CombatStop(); + target->CombatStop(true); target->DeleteThreatList(); + target->getHostileRefManager().deleteReferences(); + + if(CharmInfo *charmInfo = target->InitCharmInfo(target)) + { + charmInfo->InitPossessCreateSpells(); + charmInfo->SetReactState(REACT_PASSIVE); + charmInfo->SetCommandState(COMMAND_STAY); + } + + p_caster->PossessSpellInitialize(); if(target->GetTypeId() == TYPEID_UNIT) { - target->StopMoving(); - target->GetMotionMaster()->Clear(); - target->GetMotionMaster()->MoveIdle(); + ((Creature*)target)->AIM_Initialize(); } else if(target->GetTypeId() == TYPEID_PLAYER) { ((Player*)target)->SetClientControl(target, 0); } - if(CharmInfo *charmInfo = target->InitCharmInfo(target)) - charmInfo->InitPossessCreateSpells(); - - p_caster->PossessSpellInitialize(); } else { @@ -3664,6 +3670,12 @@ void Aura::HandleModPossess(bool apply, bool Real) if(m_removeMode == AURA_REMOVE_BY_DELETE) return; + target->clearUnitState(UNIT_STAT_CONTROLED); + + target->CombatStop(true); + target->DeleteThreatList(); + target->getHostileRefManager().deleteReferences(); + target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); target->SetCharmerGUID(0); @@ -3772,8 +3784,9 @@ void Aura::HandleModCharm(bool apply, bool Real) target->CastStop(target == caster ? GetId() : 0); caster->SetCharm(target); - target->CombatStop(); + target->CombatStop(true); target->DeleteThreatList(); + target->getHostileRefManager().deleteReferences(); if(target->GetTypeId() == TYPEID_UNIT) { @@ -3848,6 +3861,10 @@ void Aura::HandleModCharm(bool apply, bool Real) if(caster->GetTypeId() == TYPEID_PLAYER) ((Player*)caster)->RemovePetActionBar(); + target->CombatStop(true); + target->DeleteThreatList(); + target->getHostileRefManager().deleteReferences(); + if(target->GetTypeId() == TYPEID_UNIT) { ((Creature*)target)->AIM_Initialize(); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index f6a2c5a03..d0c82d8f7 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -13736,4 +13736,4 @@ bool Unit::CheckAndIncreaseCastCounter() ++m_castCounter; return true; -} +} \ No newline at end of file diff --git a/src/game/Unit.h b/src/game/Unit.h index b4b407727..11090bf49 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -420,24 +420,25 @@ enum UnitState UNIT_STAT_STUNNED = 0x00000008, // Aura::HandleAuraModStun UNIT_STAT_ROOT = 0x00000010, // Aura::HandleAuraModRoot UNIT_STAT_ISOLATED = 0x00000020, // area auras do not affect other players, Aura::HandleAuraModSchoolImmunity + UNIT_STAT_CONTROLED = 0x00000040, // Aura::HandleAuraModPossess // persistent movement generator state (all time while movement generator applied to unit (independent from top state of movegen) - UNIT_STAT_IN_FLIGHT = 0x00000040, // player is in flight mode (in fact interrupted at far teleport until next map telport landing) - UNIT_STAT_DISTRACTED = 0x00000080, // DistractedMovementGenerator active + UNIT_STAT_IN_FLIGHT = 0x00000080, // player is in flight mode (in fact interrupted at far teleport until next map telport landing) + UNIT_STAT_DISTRACTED = 0x00000100, // DistractedMovementGenerator active // persistent movement generator state with non-persistent mirror states for stop support // (can be removed temporary by stop command or another movement generator apply) // not use _MOVE versions for generic movegen state, it can be removed temporary for unit stop and etc - UNIT_STAT_CONFUSED = 0x00000100, // ConfusedMovementGenerator active/onstack - UNIT_STAT_CONFUSED_MOVE = 0x00000200, - UNIT_STAT_ROAMING = 0x00000400, // RandomMovementGenerator/PointMovementGenerator/WaypointMovementGenerator active (now always set) - UNIT_STAT_ROAMING_MOVE = 0x00000800, - UNIT_STAT_CHASE = 0x00001000, // ChaseMovementGenerator active - UNIT_STAT_CHASE_MOVE = 0x00002000, - UNIT_STAT_FOLLOW = 0x00004000, // FollowMovementGenerator active - UNIT_STAT_FOLLOW_MOVE = 0x00008000, - UNIT_STAT_FLEEING = 0x00010000, // FleeMovementGenerator/TimedFleeingMovementGenerator active/onstack - UNIT_STAT_FLEEING_MOVE = 0x00020000, + UNIT_STAT_CONFUSED = 0x00000200, // ConfusedMovementGenerator active/onstack + UNIT_STAT_CONFUSED_MOVE = 0x00000400, + UNIT_STAT_ROAMING = 0x00000800, // RandomMovementGenerator/PointMovementGenerator/WaypointMovementGenerator active (now always set) + UNIT_STAT_ROAMING_MOVE = 0x00001000, + UNIT_STAT_CHASE = 0x00002000, // ChaseMovementGenerator active + UNIT_STAT_CHASE_MOVE = 0x00004000, + UNIT_STAT_FOLLOW = 0x00008000, // FollowMovementGenerator active + UNIT_STAT_FOLLOW_MOVE = 0x00010000, + UNIT_STAT_FLEEING = 0x00020000, // FleeMovementGenerator/TimedFleeingMovementGenerator active/onstack + UNIT_STAT_FLEEING_MOVE = 0x00040000, // masks (only for check) @@ -457,6 +458,12 @@ enum UnitState UNIT_STAT_CAN_NOT_REACT = UNIT_STAT_STUNNED | UNIT_STAT_DIED | UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING, + // AI disabled by some reason + UNIT_STAT_LOST_CONTROL = UNIT_STAT_FLEEING | UNIT_STAT_CONTROLED, + + // above 2 state cases + UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL = UNIT_STAT_CAN_NOT_REACT | UNIT_STAT_LOST_CONTROL, + // masks (for check or reset) // for real move using movegen check and stop (except unstoppable flight) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 926d2dd1d..247bcbbc9 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "10052" + #define REVISION_NR "10053" #endif // __REVISION_NR_H__