*Update charm and possess code.
--HG-- branch : trunk
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -172,9 +172,9 @@ void TemporarySummon::Summon(TempSummonType type, uint32 lifetime)
|
||||
|
||||
void TemporarySummon::UnSummon()
|
||||
{
|
||||
CombatStop();
|
||||
RemoveCharmedOrPossessedBy(NULL);
|
||||
|
||||
UnpossessSelf(false);
|
||||
CombatStop();
|
||||
|
||||
CleanupsBeforeDelete();
|
||||
AddObjectToRemoveList();
|
||||
|
||||
+226
-27
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user