aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/game/Creature.cpp6
-rw-r--r--src/game/CreatureAI.cpp38
-rw-r--r--src/game/CreatureAI.h17
-rw-r--r--src/game/CreatureAISelector.cpp5
-rw-r--r--src/game/Level3.cpp8
-rw-r--r--src/game/Player.cpp149
-rw-r--r--src/game/Player.h11
-rw-r--r--src/game/SpellAuras.cpp152
-rw-r--r--src/game/SpellEffects.cpp2
-rw-r--r--src/game/TemporarySummon.cpp4
-rw-r--r--src/game/Unit.cpp253
-rw-r--r--src/game/Unit.h64
-rw-r--r--src/game/WorldSession.cpp13
13 files changed, 361 insertions, 361 deletions
diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp
index 081f1160b1a..03eeecb3e10 100644
--- a/src/game/Creature.cpp
+++ b/src/game/Creature.cpp
@@ -594,10 +594,6 @@ bool Creature::AIM_Initialize(CreatureAI* ai)
return false;
}
- // don't allow AI switch when possessed
- if (isPossessed())
- return false;
-
CreatureAI * oldAI = i_AI;
i_motionMaster.Initialize();
i_AI = ai ? ai : FactorySelector::selectAI(this);
@@ -621,6 +617,8 @@ void Creature::DisablePossessedAI()
{
if (!i_AI_possessed) return;
+ delete i_AI_possessed;
+
// Signal the old AI that it's been re-enabled
i_AI->OnPossess(false);
}
diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp
index ad663d13b38..71046e2f154 100644
--- a/src/game/CreatureAI.cpp
+++ b/src/game/CreatureAI.cpp
@@ -19,7 +19,45 @@
*/
#include "CreatureAI.h"
+#include "Creature.h"
+#include "Pet.h"
+#include "SpellAuras.h"
CreatureAI::~CreatureAI()
{
}
+
+SimpleCharmedAI::SimpleCharmedAI(Unit &u) : me(u)
+{
+}
+
+void SimpleCharmedAI::UpdateAI(const uint32 /*diff*/)
+{
+ Creature *charmer = (Creature*)me.GetCharmer();
+
+ //kill self if charm aura has infinite duration
+ if(charmer->IsInEvadeMode())
+ {
+ Unit::AuraList const& auras = me.GetAurasByType(SPELL_AURA_MOD_CHARM);
+ for(Unit::AuraList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter)
+ if((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->IsPermanent())
+ {
+ charmer->Kill(&me);
+ return;
+ }
+ }
+
+ if(!charmer->isInCombat())
+ me.GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
+
+ Unit *target = me.getVictim();
+ if(!target || !charmer->canAttack(target))
+ {
+ target = charmer->SelectNearestTarget();
+ if(!target)
+ return;
+
+ me.GetMotionMaster()->MoveChase(target);
+ me.Attack(target, true);
+ }
+}
diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h
index a1f78be1e86..b5fda95ef85 100644
--- a/src/game/CreatureAI.h
+++ b/src/game/CreatureAI.h
@@ -69,7 +69,22 @@ enum SelectAggroTarget
SELECT_TARGET_FARTHEST,
};
-class TRINITY_DLL_SPEC CreatureAI
+class TRINITY_DLL_SPEC UnitAI
+{
+ public:
+ virtual void UpdateAI(const uint32 diff) = 0;
+};
+
+class TRINITY_DLL_SPEC SimpleCharmedAI
+{
+ public:
+ SimpleCharmedAI(Unit &u);
+ virtual void UpdateAI(const uint32 diff);
+ private:
+ Unit &me;
+};
+
+class TRINITY_DLL_SPEC CreatureAI : public UnitAI
{
public:
diff --git a/src/game/CreatureAISelector.cpp b/src/game/CreatureAISelector.cpp
index 5e15efafe6f..9927ff34df3 100644
--- a/src/game/CreatureAISelector.cpp
+++ b/src/game/CreatureAISelector.cpp
@@ -34,6 +34,9 @@ namespace FactorySelector
{
CreatureAI* selectAI(Creature *creature)
{
+ //if(creature->isPossessed())
+ // creature->InitPossessedAI();
+
// Allow scripting AI for normal creatures and not controlled pets (guardians and mini-pets)
if((!creature->isPet() || !((Pet*)creature)->isControlled()) && !creature->isCharmed())
if(CreatureAI* scriptedAI = Script->GetAI(creature))
@@ -62,8 +65,6 @@ namespace FactorySelector
ai_factory = ai_registry.GetRegistryItem("TotemAI");
else if(creature->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER)
ai_factory = ai_registry.GetRegistryItem("NullCreatureAI");
- else if(creature->isPossessed())
- creature->InitPossessedAI();
}
// select by permit check
diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp
index 6a05a81fbae..a825743481a 100644
--- a/src/game/Level3.cpp
+++ b/src/game/Level3.cpp
@@ -6915,7 +6915,7 @@ bool ChatHandler::HandlePossessCommand(const char* args)
if (pUnit->GetTypeId() == TYPEID_PLAYER)
return false;
- m_session->GetPlayer()->Possess(pUnit);
+ pUnit->SetCharmedOrPossessedBy(m_session->GetPlayer(), true);
return true;
}
@@ -6923,11 +6923,7 @@ bool ChatHandler::HandlePossessCommand(const char* args)
bool ChatHandler::HandleUnPossessCommand(const char* args)
{
// Use this command to also unpossess ourselves
- if (m_session->GetPlayer()->isPossessed())
- m_session->GetPlayer()->UnpossessSelf(false);
- else
- m_session->GetPlayer()->RemovePossess(false);
-
+ m_session->GetPlayer()->RemoveCharmedOrPossessedBy(NULL);
return true;
}
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 81ebb45a92e..5dfc9a412b1 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -19039,150 +19039,12 @@ void Player::HandleFallUnderMap()
}
}
-void Player::Possess(Unit *target)
-{
- if(!target || target == this)
- return;
-
- // Don't allow possession of someone else's pet
- if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isPet() && target != GetPet())
- return;
-
- // Don't allow possession on transports or when in flight; also remove possession from the now-to-be-possessed
- if (target->GetTypeId() == TYPEID_PLAYER)
- {
- if (((Player*)target)->m_transport || ((Player*)target)->isInFlight())
- return;
- if (target->isPossessing())
- ((Player*)target)->RemovePossess(true);
- }
-
- // Remove any previous possession from the target
- if (target->isPossessedByPlayer())
- ((Player*)target->GetCharmer())->RemovePossess(false);
- else if (target->isCharmed())
- target->UncharmSelf(); // Target isn't possessed, but charmed; uncharm before possessing
-
- // Remove our previous possession
- if (isPossessing())
- RemovePossess(true);
- else if (GetCharm()) // We are charming a creature, not possessing it; uncharm ourself first
- Uncharm();
-
- // Interrupt any current casting of the target
- if(target->IsNonMeleeSpellCasted(true))
- target->InterruptNonMeleeSpells(true);
-
- // Update the proper unit fields
- SetPossessedTarget(target);
-
- // Start channeling packets to possessor
- target->AddPlayerToVision(this);
-
- target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, getFaction());
- target->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
- target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
- target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
- SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
-
- if(target->GetTypeId() == TYPEID_UNIT)
- {
- ((Creature*)target)->InitPossessedAI(); // Initialize the possessed AI
- target->StopMoving();
- target->GetMotionMaster()->Clear(false);
- target->GetMotionMaster()->MoveIdle();
- }
-
- target->CombatStop();
- target->DeleteThreatList();
-
- // Pets already have a properly initialized CharmInfo, don't overwrite it.
- if(target->GetTypeId() == TYPEID_PLAYER || (target->GetTypeId() == TYPEID_UNIT && !((Creature*)target)->isPet()))
- {
- CharmInfo* charmInfo = target->InitCharmInfo(target);
- charmInfo->InitPossessCreateSpells();
- }
-
- // Disable control for target player and remove AFK
- if(target->GetTypeId() == TYPEID_PLAYER)
- {
- if(((Player*)target)->isAFK())
- ((Player*)target)->ToggleAFK();
- ((Player*)target)->SetViewport(target->GetGUID(), false);
- }
-
- // Set current viewport to target unit, controllable
- SetViewport(target->GetGUID(), true);
-
- PossessSpellInitialize();
-}
-
void Player::RemovePossess(bool attack)
{
- Unit* target = GetCharm();
- if(!target || !target->isPossessed())
- return;
-
- // Remove area auras from possessed
- Unit::AuraMap& tAuras = target->GetAuras();
- for(Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
- {
- if(itr->second && itr->second->IsAreaAura())
- target->RemoveAura(itr);
- else
- ++itr;
- }
-
- // Interrupt any current casting of the target
- if(target->IsNonMeleeSpellCasted(true))
- target->InterruptNonMeleeSpells(true);
-
- RemovePossessedTarget();
-
- // Stop channeling packets back to possessor
- target->RemovePlayerFromVision(this);
-
- if(target->GetTypeId() == TYPEID_PLAYER)
- ((Player*)target)->setFactionForRace(target->getRace());
- else if(target->GetTypeId() == TYPEID_UNIT)
- {
- if(((Creature*)target)->isPet())
- {
- if(Unit* owner = target->GetOwner())
- target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, owner->getFaction());
- } else
- {
- if(CreatureInfo const* cInfo = ((Creature*)target)->GetCreatureInfo())
- target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, cInfo->faction_A);
- }
- }
-
- target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
- RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
+ if(Unit *u = GetCharm())
+ u->RemoveCharmedOrPossessedBy(this);
- // Remove pet spell action bar
- WorldPacket data(SMSG_PET_SPELLS, 8);
- data << uint64(0);
- m_session->SendPacket(&data);
-
- // Restore original view
- SetViewport(GetGUID(), true);
- if(target->GetTypeId() == TYPEID_PLAYER)
- ((Player*)target)->SetViewport(target->GetGUID(), true);
- else
- {
- target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
- // Reinitialize the pet bar and make the pet come back to the owner
- if(((Creature*)target)->isPet())
- {
- PetSpellInitialize();
- if (!target->getVictim())
- {
- target->GetMotionMaster()->MoveFollow(this, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
- target->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW);
- }
- }
- else if (target->isAlive())
+ /*else if (target->isAlive())
{
// If we're still hostile to our target, continue attacking otherwise reset threat and go home
if (Unit* victim = target->getVictim())
@@ -19209,10 +19071,7 @@ void Player::RemovePossess(bool attack)
// Add high amount of threat on the player
if(attack)
target->AddThreat(this, 1000000.0f);
- }
- // Disable the assigned possessed AI
- ((Creature*)target)->DisablePossessedAI();
- }
+ }*/
}
void Player::SetViewport(uint64 guid, bool moveable)
diff --git a/src/game/Player.h b/src/game/Player.h
index 3dc1a691e44..cdf2005f111 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -899,8 +899,14 @@ class TRINITY_DLL_SPEC Player : public Unit
void RemoveFromWorld();
void SetViewport(uint64 guid, bool movable);
- void Possess(Unit *target);
- void RemovePossess(bool attack = true);
+ void RemovePossess(bool attack = true);
+ void StopCharmOrPossess()
+ {
+ if(isPossessing())
+ RemovePossess(true);
+ else if(GetCharm())
+ Uncharm();
+ }
WorldObject* GetFarsightTarget() const;
void ClearFarsight();
void RemoveFarsightTarget();
@@ -2325,6 +2331,7 @@ class TRINITY_DLL_SPEC Player : public Unit
MapReference m_mapRef;
void UpdateCharmedAI();
+ UnitAI *i_AI;
};
void AddItemsSetItem(Player*player,Item *item);
diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp
index ebee1e4c22b..0c9f8d54e4a 100644
--- a/src/game/SpellAuras.cpp
+++ b/src/game/SpellAuras.cpp
@@ -687,21 +687,8 @@ void AreaAura::Update(uint32 diff)
}
else if( m_areaAuraType == AREA_AURA_PARTY) // check if in same sub group
{
- // not check group if target == owner or target == pet
- if (caster->GetCharmerOrOwnerGUID() != tmp_target->GetGUID() && caster->GetGUID() != tmp_target->GetCharmerOrOwnerGUID())
- {
- Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself();
-
- Group *pGroup = check ? check->GetGroup() : NULL;
- if( pGroup )
- {
- Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself();
- if(!checkTarget || !pGroup->SameSubGroup(check, checkTarget))
- tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
- }
- else
- tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
- }
+ if(!tmp_target->IsInPartyWith(caster))
+ tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
}
else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER )
{
@@ -2866,24 +2853,22 @@ void Aura::HandleModPossess(bool apply, bool Real)
if(!Real)
return;
- if(m_target->getLevel() > m_modifier.m_amount)
- return;
-
- // not possess yourself
- if(GetCasterGUID() == m_target->GetGUID())
- return;
-
Unit* caster = GetCaster();
- if(!caster)
+ if(caster && caster->GetTypeId() == TYPEID_UNIT)
+ {
+ HandleModCharm(apply, Real);
return;
+ }
- if( apply )
+ if(apply)
{
- if (caster->GetTypeId() == TYPEID_PLAYER)
- ((Player*)caster)->Possess(m_target);
+ if(m_target->getLevel() > m_modifier.m_amount)
+ return;
+
+ m_target->SetCharmedOrPossessedBy(caster, true);
}
else
- m_target->UnpossessSelf(true);
+ m_target->RemoveCharmedOrPossessedBy(caster);
}
void Aura::HandleModPossessPet(bool apply, bool Real)
@@ -2898,12 +2883,18 @@ void Aura::HandleModPossessPet(bool apply, bool Real)
return;
if(apply)
- {
- ((Player*)caster)->Possess(m_target);
- }
+ m_target->SetCharmedOrPossessedBy(caster, true);
else
{
- ((Player*)caster)->RemovePossess(false);
+ m_target->RemoveCharmedOrPossessedBy(caster);
+
+ // Reinitialize the pet bar and make the pet come back to the owner
+ ((Player*)caster)->PetSpellInitialize();
+ if(!m_target->getVictim())
+ {
+ m_target->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
+ m_target->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW);
+ }
}
}
@@ -2912,108 +2903,17 @@ void Aura::HandleModCharm(bool apply, bool Real)
if(!Real)
return;
- // not charm yourself
- if(GetCasterGUID() == m_target->GetGUID())
- return;
-
Unit* caster = GetCaster();
- if( apply )
+ if(apply)
{
- if(!caster)
- return;
-
if(int32(m_target->getLevel()) > m_modifier.m_amount)
return;
-
- m_target->SetCharmerGUID(GetCasterGUID());
- m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
- m_target->CastStop(m_target==caster ? GetId() : 0);
- caster->SetCharm(m_target);
-
- m_target->CombatStop();
- m_target->DeleteThreatList();
-
- if(m_target->GetTypeId() == TYPEID_UNIT)
- {
- ((Creature*)m_target)->AIM_Initialize();
- CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
- charmInfo->InitCharmCreateSpells();
- charmInfo->SetReactState( REACT_DEFENSIVE );
-
- if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK)
- {
- CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
- if(cinfo && cinfo->type == CREATURE_TYPE_DEMON)
- {
- //to prevent client crash
- m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048);
- //just to enable stat window
- charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true);
- //if charmed two demons the same session, the 2nd gets the 1st one's name
- m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
- }
- }
- }
-
- if(caster->GetTypeId() == TYPEID_PLAYER)
- {
- ((Player*)caster)->CharmSpellInitialize();
- }
+
+ m_target->SetCharmedOrPossessedBy(caster, false);
}
else
- {
- m_target->SetCharmerGUID(0);
-
- if(m_target->GetTypeId() == TYPEID_PLAYER)
- ((Player*)m_target)->setFactionForRace(m_target->getRace());
- else
- {
- CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
-
- // restore faction
- if(((Creature*)m_target)->isPet())
- {
- if(Unit* owner = m_target->GetOwner())
- m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction());
- else if(cinfo)
- m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
- }
- else if(cinfo) // normal creature
- m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
-
- // restore UNIT_FIELD_BYTES_0
- if(caster && cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON)
- {
- CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon();
- if(cainfo && cainfo->bytes0 != 0)
- m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0);
- else
- m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);
-
- if(m_target->GetCharmInfo())
- m_target->GetCharmInfo()->SetPetNumber(0, true);
- else
- sLog.outError("Aura::HandleModCharm: target="I64FMTD" with typeid=%d has a charm aura but no charm info!", m_target->GetGUID(), m_target->GetTypeId());
- }
-
- ((Creature*)m_target)->AIM_Initialize();
- if(((Creature*)m_target)->AI() && caster)
- ((Creature*)m_target)->AI()->AttackStart(caster);
- }
-
- if(caster)
- {
- caster->SetCharm(0);
-
- if(caster->GetTypeId() == TYPEID_PLAYER)
- {
- WorldPacket data(SMSG_PET_SPELLS, 8);
- data << uint64(0);
- ((Player*)caster)->GetSession()->SendPacket(&data);
- }
- }
- }
+ m_target->RemoveCharmedOrPossessedBy(caster);
}
void Aura::HandleModConfuse(bool apply, bool Real)
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
index fc9f132e23d..4c2c28e64e4 100644
--- a/src/game/SpellEffects.cpp
+++ b/src/game/SpellEffects.cpp
@@ -3704,7 +3704,7 @@ void Spell::EffectSummonPossessed(uint32 i)
TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
Creature* c = m_caster->SummonCreature(creatureEntry, px, py, pz, m_caster->GetOrientation(), summonType, duration);
- ((Player*)m_caster)->Possess(c);
+ if(c) c->SetCharmedOrPossessedBy(m_caster, true);
}
void Spell::EffectTeleUnitsFaceCaster(uint32 i)
diff --git a/src/game/TemporarySummon.cpp b/src/game/TemporarySummon.cpp
index 357a32b4ecb..553f7644b64 100644
--- a/src/game/TemporarySummon.cpp
+++ b/src/game/TemporarySummon.cpp
@@ -172,9 +172,9 @@ void TemporarySummon::Summon(TempSummonType type, uint32 lifetime)
void TemporarySummon::UnSummon()
{
- CombatStop();
+ RemoveCharmedOrPossessedBy(NULL);
- UnpossessSelf(false);
+ CombatStop();
CleanupsBeforeDelete();
AddObjectToRemoveList();
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index 85f13097a14..0bf8faa5bb2 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -233,7 +233,6 @@ Unit::Unit()
m_removedAuras = 0;
m_charmInfo = NULL;
m_unit_movement_flags = 0;
- m_isPossessed = false;
m_reducedThreatPercent = 0;
m_misdirectionTargetGUID = 0;
@@ -8380,7 +8379,8 @@ void Unit::SetPet(Pet* pet)
void Unit::SetCharm(Unit* pet)
{
- SetUInt64Value(UNIT_FIELD_CHARM, pet ? pet->GetGUID() : 0);
+ if(GetTypeId() == TYPEID_PLAYER)
+ SetUInt64Value(UNIT_FIELD_CHARM, pet ? pet->GetGUID() : 0);
}
void Unit::AddPlayerToVision(Player* plr)
@@ -8423,21 +8423,6 @@ void Unit::UncharmSelf()
RemoveSpellsCausingAura(SPELL_AURA_MOD_CHARM);
}
-void Unit::UnpossessSelf(bool attack)
-{
- if (!isPossessed() || !GetCharmer())
- return;
-
- if (GetCharmer()->GetTypeId() == TYPEID_PLAYER)
- ((Player*)GetCharmer())->RemovePossess(attack);
- else
- {
- GetCharmer()->SetCharm(0);
- SetCharmerGUID(0);
- m_isPossessed = false;
- }
-}
-
void Unit::UnsummonAllTotems()
{
for (int8 i = 0; i < MAX_TOTEM; ++i)
@@ -10239,7 +10224,7 @@ void Unit::setDeathState(DeathState s)
UnsummonAllTotems();
// Possessed unit died, restore control to possessor
- UnpossessSelf(false);
+ RemoveCharmedOrPossessedBy(NULL);
RemoveAllFromVision();
ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false);
@@ -11098,7 +11083,7 @@ void Unit::CleanupsBeforeDelete()
{
if(m_uint32Values) // only for fully created object
{
- UnpossessSelf(false);
+ RemoveCharmedOrPossessedBy(NULL);
RemoveAllFromVision();
InterruptNonMeleeSpells(true);
m_Events.KillAllEvents(false); // non-delatable (currently casted spells) will not deleted now but it will deleted at call in Map::RemoveAllObjectsInRemoveList
@@ -12929,22 +12914,236 @@ void Unit::SetConfused(bool apply)
((Player*)this)->SetClientControl(this, !apply);
}
+void Unit::SetCharmedOrPossessedBy(Unit* charmer, bool possess)
+{
+ if(!charmer)
+ return;
+
+ assert(!possess || charmer->GetTypeId() == TYPEID_PLAYER);
+
+ if(this == charmer)
+ return;
+
+ if(isInFlight())
+ return;
+
+ if(GetTypeId() == TYPEID_PLAYER && ((Player*)this)->GetTransport())
+ return;
+
+ RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
+ CastStop();
+ CombatStop(); //TODO: CombatStop(true) may cause crash (interrupt spells)
+ DeleteThreatList();
+
+ // Charmer stop charming
+ if(charmer->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)charmer)->StopCharmOrPossess();
+
+ // Charmed stop charming
+ if(GetTypeId() == TYPEID_PLAYER)
+ ((Player*)this)->StopCharmOrPossess();
+
+ // Charmed stop being charmed
+ RemoveCharmedOrPossessedBy(NULL);
+
+ // Set charmed
+ charmer->SetCharm(this);
+ SetCharmerGUID(charmer->GetGUID());
+ setFaction(charmer->getFaction());
+ SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
+
+ if(GetTypeId() == TYPEID_UNIT)
+ {
+ ((Creature*)this)->InitPossessedAI();
+ StopMoving();
+ GetMotionMaster()->Clear(false);
+ GetMotionMaster()->MoveIdle();
+ }
+ else
+ {
+ if(((Player*)this)->isAFK())
+ ((Player*)this)->ToggleAFK();
+ ((Player*)this)->SetViewport(GetGUID(), false);
+ }
+
+ // Pets already have a properly initialized CharmInfo, don't overwrite it.
+ if(GetTypeId() == TYPEID_PLAYER || GetTypeId() == TYPEID_UNIT && !((Creature*)this)->isPet())
+ {
+ CharmInfo *charmInfo = InitCharmInfo(this);
+ charmInfo->SetReactState(REACT_DEFENSIVE);
+ if(possess)
+ charmInfo->InitPossessCreateSpells();
+ else
+ charmInfo->InitCharmCreateSpells();
+ }
+
+ //Set possessed
+ if(possess)
+ {
+ addUnitState(UNIT_STAT_POSSESSED);
+ SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
+ AddPlayerToVision((Player*)charmer);
+ ((Player*)charmer)->SetViewport(GetGUID(), true);
+ charmer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
+ }
+ // Charm demon
+ else if(GetTypeId() == TYPEID_UNIT && charmer->GetTypeId() == TYPEID_PLAYER && charmer->getClass() == CLASS_WARLOCK)
+ {
+ CreatureInfo const *cinfo = ((Creature*)this)->GetCreatureInfo();
+ if(cinfo && cinfo->type == CREATURE_TYPE_DEMON)
+ {
+ //to prevent client crash
+ SetFlag(UNIT_FIELD_BYTES_0, 2048);
+
+ //just to enable stat window
+ if(GetCharmInfo())
+ GetCharmInfo()->SetPetNumber(objmgr.GeneratePetNumber(), true);
+
+ //if charmed two demons the same session, the 2nd gets the 1st one's name
+ SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
+ }
+ }
+
+ if(possess)
+ ((Player*)charmer)->PossessSpellInitialize();
+ else if(charmer->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)charmer)->CharmSpellInitialize();
+}
+
+void Unit::RemoveCharmedOrPossessedBy(Unit *charmer)
+{
+ if(!isCharmed())
+ return;
+
+ if(!charmer)
+ charmer = GetCharmer();
+ else if(charmer != GetCharmer()) // one aura overrides another?
+ return;
+
+ bool possess = hasUnitState(UNIT_STAT_POSSESSED);
+
+ CastStop();
+ CombatStop(); //TODO: CombatStop(true) may cause crash (interrupt spells)
+ getHostilRefManager().deleteReferences();
+ DeleteThreatList();
+ SetCharmerGUID(0);
+ RestoreFaction();
+
+ if(possess)
+ {
+ clearUnitState(UNIT_STAT_POSSESSED);
+ RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
+ }
+
+ if(GetTypeId() == TYPEID_UNIT)
+ {
+ if(!((Creature*)this)->isPet())
+ RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
+
+ ((Creature*)this)->DisablePossessedAI();
+ if(isAlive() && ((Creature*)this)->AI())
+ {
+ if(charmer && !IsFriendlyTo(charmer))
+ {
+ ((Creature*)this)->AddThreat(charmer, 10000.0f);
+ ((Creature*)this)->AI()->AttackStart(charmer);
+ }
+ else
+ ((Creature*)this)->AI()->EnterEvadeMode();
+ }
+ }
+ else
+ ((Player*)this)->SetViewport(GetGUID(), true);
+
+ // If charmer still exists
+ if(!charmer)
+ return;
+
+ assert(!possess || charmer->GetTypeId() == TYPEID_PLAYER);
+
+ charmer->SetCharm(0);
+ if(possess)
+ {
+ RemovePlayerFromVision((Player*)charmer);
+ ((Player*)charmer)->SetViewport(charmer->GetGUID(), true);
+ charmer->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
+ }
+ // restore UNIT_FIELD_BYTES_0
+ else if(GetTypeId() == TYPEID_UNIT && charmer->GetTypeId() == TYPEID_PLAYER && charmer->getClass() == CLASS_WARLOCK)
+ {
+ CreatureInfo const *cinfo = ((Creature*)this)->GetCreatureInfo();
+ if(cinfo && cinfo->type == CREATURE_TYPE_DEMON)
+ {
+ CreatureDataAddon const *cainfo = ((Creature*)this)->GetCreatureAddon();
+ if(cainfo && cainfo->bytes0 != 0)
+ SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0);
+ else
+ RemoveFlag(UNIT_FIELD_BYTES_0, 2048);
+
+ if(GetCharmInfo())
+ GetCharmInfo()->SetPetNumber(0, true);
+ else
+ sLog.outError("Aura::HandleModCharm: target="I64FMTD" with typeid=%d has a charm aura but no charm info!", GetGUID(), GetTypeId());
+ }
+ }
+
+ if(possess || charmer->GetTypeId() == TYPEID_PLAYER)
+ {
+ // Remove pet spell action bar
+ WorldPacket data(SMSG_PET_SPELLS, 8);
+ data << uint64(0);
+ ((Player*)charmer)->GetSession()->SendPacket(&data);
+ }
+}
+
+void Unit::RestoreFaction()
+{
+ if(GetTypeId() == TYPEID_PLAYER)
+ ((Player*)this)->setFactionForRace(getRace());
+ else
+ {
+ CreatureInfo const *cinfo = ((Creature*)this)->GetCreatureInfo();
+
+ if(((Creature*)this)->isPet())
+ {
+ if(Unit* owner = GetOwner())
+ setFaction(owner->getFaction());
+ else if(cinfo)
+ setFaction(cinfo->faction_A);
+ }
+ else if(cinfo) // normal creature
+ setFaction(cinfo->faction_A);
+ }
+}
+
bool Unit::IsInPartyWith(Unit const *unit) const
{
- const Player *p1 = GetCharmerOrOwnerPlayerOrPlayerItself();
- const Player *p2 = unit->GetCharmerOrOwnerPlayerOrPlayerItself();
- if(p1 && p2)
- return p1->IsInSameGroupWith(p2);
+ if(this == unit)
+ return true;
+
+ const Unit *u1 = GetCharmerOrOwnerOrSelf();
+ const Unit *u2 = unit->GetCharmerOrOwnerOrSelf();
+ if(u1 == u2)
+ return true;
+
+ if(u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_PLAYER)
+ return ((Player*)u1)->IsInSameGroupWith((Player*)u2);
else
return false;
}
bool Unit::IsInRaidWith(Unit const *unit) const
{
- const Player *p1 = GetCharmerOrOwnerPlayerOrPlayerItself();
- const Player *p2 = unit->GetCharmerOrOwnerPlayerOrPlayerItself();
- if(p1 && p2)
- return p1->IsInSameRaidWith(p2);
+ if(this == unit)
+ return true;
+
+ const Unit *u1 = GetCharmerOrOwnerOrSelf();
+ const Unit *u2 = unit->GetCharmerOrOwnerOrSelf();
+ if(u1 == u2)
+ return true;
+
+ if(u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_PLAYER)
+ return ((Player*)u1)->IsInSameRaidWith((Player*)u2);
else
return false;
}
diff --git a/src/game/Unit.h b/src/game/Unit.h
index 3cba888eb01..da85bd53d1a 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -350,27 +350,28 @@ enum DeathState
enum UnitState
{
- UNIT_STAT_DIED = 0x0001,
- UNIT_STAT_MELEE_ATTACKING = 0x0002, // player is melee attacking someone
- //UNIT_STAT_MELEE_ATTACK_BY = 0x0004, // player is melee attack by someone
- UNIT_STAT_STUNNED = 0x0008,
- UNIT_STAT_ROAMING = 0x0010,
- UNIT_STAT_CHASE = 0x0020,
- UNIT_STAT_SEARCHING = 0x0040,
- UNIT_STAT_FLEEING = 0x0080,
+ UNIT_STAT_DIED = 0x00000001,
+ UNIT_STAT_MELEE_ATTACKING = 0x00000002, // player is melee attacking someone
+ //UNIT_STAT_MELEE_ATTACK_BY = 0x00000004, // player is melee attack by someone
+ UNIT_STAT_STUNNED = 0x00000008,
+ UNIT_STAT_ROAMING = 0x00000010,
+ UNIT_STAT_CHASE = 0x00000020,
+ UNIT_STAT_SEARCHING = 0x00000040,
+ UNIT_STAT_FLEEING = 0x00000080,
+ UNIT_STAT_IN_FLIGHT = 0x00000100, // player is in flight mode
+ UNIT_STAT_FOLLOW = 0x00000200,
+ UNIT_STAT_ROOT = 0x00000400,
+ UNIT_STAT_CONFUSED = 0x00000800,
+ UNIT_STAT_DISTRACTED = 0x00001000,
+ UNIT_STAT_ISOLATED = 0x00002000, // area auras do not affect other players
+ UNIT_STAT_ATTACK_PLAYER = 0x00004000,
+ UNIT_STAT_CASTING = 0x00008000,
+ UNIT_STAT_POSSESSED = 0x00010000,
UNIT_STAT_MOVING = (UNIT_STAT_ROAMING | UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING),
- UNIT_STAT_IN_FLIGHT = 0x0100, // player is in flight mode
- UNIT_STAT_FOLLOW = 0x0200,
- UNIT_STAT_ROOT = 0x0400,
- UNIT_STAT_CONFUSED = 0x0800,
- UNIT_STAT_DISTRACTED = 0x1000,
- UNIT_STAT_ISOLATED = 0x2000, // area auras do not affect other players
- UNIT_STAT_ATTACK_PLAYER = 0x4000,
- UNIT_STAT_CASTING = 0x8000,
UNIT_STAT_LOST_CONTROL = (UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING),
UNIT_STAT_SIGHTLESS = (UNIT_STAT_LOST_CONTROL | UNIT_STAT_CHASE | UNIT_STAT_SEARCHING),
UNIT_STAT_CANNOT_AUTOATTACK = (UNIT_STAT_LOST_CONTROL | UNIT_STAT_CASTING),
- UNIT_STAT_ALL_STATE = 0xffff //(UNIT_STAT_STOPPED | UNIT_STAT_MOVING | UNIT_STAT_IN_COMBAT | UNIT_STAT_IN_FLIGHT)
+ UNIT_STAT_ALL_STATE = 0xffffffff //(UNIT_STAT_STOPPED | UNIT_STAT_MOVING | UNIT_STAT_IN_COMBAT | UNIT_STAT_IN_FLIGHT)
};
enum UnitMoveType
@@ -1058,35 +1059,24 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
Unit* GetCharmer() const;
Unit* GetCharm() const;
Unit* GetCharmerOrOwner() const { return GetCharmerGUID() ? GetCharmer() : GetOwner(); }
- Unit* GetCharmerOrOwnerOrSelf()
+ Unit* GetCharmerOrOwnerOrSelf() const
{
- if(Unit* u = GetCharmerOrOwner())
+ if(Unit *u = GetCharmerOrOwner())
return u;
- return this;
+ return (Unit*)this;
}
Player* GetCharmerOrOwnerPlayerOrPlayerItself() const;
void SetPet(Pet* pet);
void SetCharm(Unit* pet);
- void SetPossessedTarget(Unit* target)
- {
- if (!target) return;
- SetCharm(target);
- target->SetCharmerGUID(GetGUID());
- target->m_isPossessed = true;
- }
- void RemovePossessedTarget()
- {
- if (!GetCharm()) return;
- GetCharm()->SetCharmerGUID(0);
- GetCharm()->m_isPossessed = false;
- SetCharm(0);
- }
+ void SetCharmedOrPossessedBy(Unit* charmer, bool possess);
+ void RemoveCharmedOrPossessedBy(Unit* charmer);
+ void RestoreFaction();
bool isCharmed() const { return GetCharmerGUID() != 0; }
- bool isPossessed() const { return m_isPossessed; }
- bool isPossessedByPlayer() const { return m_isPossessed && IS_PLAYER_GUID(GetCharmerGUID()); }
+ bool isPossessed() const { return hasUnitState(UNIT_STAT_POSSESSED); }
+ bool isPossessedByPlayer() const { return hasUnitState(UNIT_STAT_POSSESSED) && IS_PLAYER_GUID(GetCharmerGUID()); }
bool isPossessing() const
{
if(Unit *u = GetCharm())
@@ -1104,7 +1094,6 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
void RemovePlayerFromVision(Player* plr);
void RemoveAllFromVision();
void UncharmSelf();
- void UnpossessSelf(bool attack);
Pet* CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id = 0);
@@ -1450,7 +1439,6 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
float m_speed_rate[MAX_MOVE_TYPE];
CharmInfo *m_charmInfo;
- bool m_isPossessed;
SharedVisionList m_sharedVision;
virtual SpellSchoolMask GetMeleeDamageSchoolMask() const;
diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp
index f2e08969a96..eb2612a1543 100644
--- a/src/game/WorldSession.cpp
+++ b/src/game/WorldSession.cpp
@@ -249,6 +249,12 @@ void WorldSession::LogoutPlayer(bool Save)
if (_player)
{
+ // Unpossess the current possessed unit of player
+ _player->StopCharmOrPossess();
+
+ // Remove any possession of this player on logout
+ _player->RemoveCharmedOrPossessedBy(NULL);
+
if (uint64 lguid = GetPlayer()->GetLootGUID())
DoLootRelease(lguid);
@@ -370,13 +376,6 @@ void WorldSession::LogoutPlayer(bool Save)
if(_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && m_Socket)
_player->RemoveFromGroup();
- // Unpossess the current possessed unit of player
- if (_player->isPossessing())
- _player->RemovePossess(false);
-
- // Remove any possession of this player on logout
- _player->UnpossessSelf(false);
-
///- Remove the player from the world
// the player may not be in the world when logging out
// e.g if he got disconnected during a transfer to another map