*Update charm and possess code.

--HG--
branch : trunk
This commit is contained in:
megamage
2009-01-08 21:48:38 -06:00
parent b57516e170
commit 2377f49ea8
13 changed files with 363 additions and 363 deletions
+2 -4
View File
@@ -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);
}
+38
View File
@@ -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);
}
}
+16 -1
View File
@@ -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:
+3 -2
View File
@@ -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
+2 -6
View File
@@ -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;
}
+4 -145
View File
@@ -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;
if(Unit *u = GetCharm())
u->RemoveCharmedOrPossessedBy(this);
// 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);
// 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)
+9 -2
View File
@@ -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);
+28 -128
View File
@@ -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)
return;
if( apply )
if(caster && caster->GetTypeId() == TYPEID_UNIT)
{
if (caster->GetTypeId() == TYPEID_PLAYER)
((Player*)caster)->Possess(m_target);
HandleModCharm(apply, Real);
return;
}
if(apply)
{
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)
+1 -1
View File
@@ -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)
+2 -2
View File
@@ -172,9 +172,9 @@ void TemporarySummon::Summon(TempSummonType type, uint32 lifetime)
void TemporarySummon::UnSummon()
{
CombatStop();
RemoveCharmedOrPossessedBy(NULL);
UnpossessSelf(false);
CombatStop();
CleanupsBeforeDelete();
AddObjectToRemoveList();
+226 -27
View File
@@ -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;
}
+26 -38
View File
@@ -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;
+6 -7
View File
@@ -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