13 cmangos commits implemented

commits:

432bd63 Commit Ported  Core Implement TakePossessOf to generalize the
code.
0b663eb Commit Ported  Core Implement a possibility to summon manualy a

temporary creature.
b6a9ead Commit Imported  Core Little rewrite of resurect code to prepare
ability
ro resurrect a player to a ghoul form.
e98b42c Commit Imported  Core Implement TemporarySummon Linked aura to
owner.
ab139ff Commit Imported  Core Do not force the creature to attack
summoner in all
case
555f055 Commit Imported  Core Avoid possibility to charm more than one
new
creature for an unit.
fd78c4a Commit Imported  Core Fix problem that occur when the charm unit
field is
updated after the possess bar.
e9821e2 Commit Imported  Core fix lightwell gameobject not appearing
after spell
is cast
17d0e93 Commit Imported  Core Implement logic for Target 95 as
TARGET_VEHICLE_DRIVER
42b3545 Commit Imported  Core Now npc/gameobject interaction will remove

unauthorized aura
1195398 Commit Imported  Core Improve functionality for eventAI action
26 -
ACTION_T_QUEST_EVENT_ALL
72b7a48 Commit Ported  Core fix pet stay
245f068 Commit Imported  Warlock [Charm] prevent charming multiple
demons also remove
pet temporarily when casting specific channels that summon other charmed
creatures
This commit is contained in:
Charles A Edwards 2016-09-13 10:37:38 +01:00 committed by Antz
parent 18dd18780d
commit df3ab5df8e
25 changed files with 508 additions and 313 deletions

View file

@ -2241,8 +2241,9 @@ bool Creature::IsOutOfThreatArea(Unit* pVictim) const
CreatureDataAddon const* Creature::GetCreatureAddon() const
{
if (CreatureDataAddon const* addon = ObjectMgr::GetCreatureAddon(GetGUIDLow()))
return addon;
if (!(GetObjectGuid().GetHigh() == HIGHGUID_PET)) // pets have guidlow that is conflicting with normal guidlows hence GetGUIDLow() gives wrong info
if (CreatureDataAddon const* addon = ObjectMgr::GetCreatureAddon(GetGUIDLow()))
return addon;
// dependent from difficulty mode entry
if (GetEntry() != GetCreatureInfo()->Entry)

View file

@ -832,7 +832,14 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
m_creature->DoFleeToGetAssistance();
break;
case ACTION_T_QUEST_EVENT_ALL:
if (pActionInvoker && pActionInvoker->GetTypeId() == TYPEID_PLAYER)
if (action.quest_event_all.useThreatList)
{
ThreatList const& threatList = m_creature->GetThreatManager().getThreatList();
for (ThreatList::const_iterator i = threatList.begin(); i != threatList.end(); ++i)
if (Player* temp = m_creature->GetMap()->GetPlayer((*i)->getUnitGuid()))
temp->GroupEventHappens(action.quest_event_all.questId, m_creature);
}
else if (pActionInvoker && pActionInvoker->GetTypeId() == TYPEID_PLAYER)
((Player*)pActionInvoker)->GroupEventHappens(action.quest_event_all.questId, m_creature);
break;
case ACTION_T_CAST_EVENT_ALL:

View file

@ -103,7 +103,7 @@ enum EventAI_ActionType
ACTION_T_INC_PHASE = 23, // Value (may be negative to decrement phase, should not be 0)
ACTION_T_EVADE = 24, // No Params
ACTION_T_FLEE_FOR_ASSIST = 25, // No Params
ACTION_T_QUEST_EVENT_ALL = 26, // QuestID
ACTION_T_QUEST_EVENT_ALL = 26, // QuestID, UseThreatList (1 = true, 0 = false)
ACTION_T_CAST_EVENT_ALL = 27, // CreatureId, SpellId
ACTION_T_REMOVEAURASFROMSPELL = 28, // Target, Spellid
ACTION_T_RANGED_MOVEMENT = 29, // Distance, Angle
@ -297,6 +297,7 @@ struct CreatureEventAI_Action
struct
{
uint32 questId;
uint32 useThreatList; // bool: 1 = true; 0 = false
} quest_event_all;
// ACTION_T_CAST_EVENT_ALL = 27
struct

View file

@ -65,6 +65,12 @@ enum TempSummonType
TEMPSUMMON_TIMED_OOC_OR_CORPSE_DESPAWN = 9, // despawns after a specified time (OOC) OR when the creature dies
};
enum TempSummonLinkedAura
{
TEMPSUMMON_LINKED_AURA_OWNER_CHECK = 0x00000001,
TEMPSUMMON_LINKED_AURA_REMOVE_OWNER = 0x00000002
};
enum PhaseMasks
{
PHASEMASK_NORMAL = 0x00000001,

View file

@ -39,7 +39,9 @@ Pet::Pet(PetType type) :
m_resetTalentsCost(0), m_resetTalentsTime(0), m_usedTalentCount(0),
m_removed(false), m_petType(type), m_duration(0),
m_bonusdamage(0), m_auraUpdateMask(0), m_loading(false),
m_declinedname(NULL), m_petModeFlags(PET_MODE_DEFAULT)
m_declinedname(nullptr), m_petModeFlags(PET_MODE_DEFAULT), m_retreating(false),
m_stayPosSet(false), m_stayPosX(0), m_stayPosY(0), m_stayPosZ(0), m_stayPosO(0),
m_opener(0), m_openerMinRange(0), m_openerMaxRange(0)
{
m_name = "Pet";
m_regenTimer = 4000;

View file

@ -254,6 +254,21 @@ class Pet : public Creature
PetSpellMap m_spells;
AutoSpellList m_autospells;
uint32 m_opener;
uint32 m_openerMinRange;
uint32 m_openerMaxRange;
uint32 GetSpellOpener() { return m_opener; }
uint32 GetSpellOpenerMinRange() { return m_openerMinRange; }
uint32 GetSpellOpenerMaxRange() { return m_openerMaxRange; }
void SetSpellOpener(uint32 spellId = 0, uint32 minRange = 0, uint32 maxRange = 0)
{
m_opener = spellId;
m_openerMinRange = minRange;
m_openerMaxRange = maxRange;
}
void InitPetCreateSpells();
bool resetTalents(bool no_cost = false);

View file

@ -2298,6 +2298,9 @@ Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint32 NpcFlagsmask)
if (!guid || !IsInWorld() || IsTaxiFlying())
return NULL;
// set player as interacting
DoInteraction(guid);
// not in interactive state
if (hasUnitState(UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL))
return NULL;
@ -2339,12 +2342,15 @@ Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint32 NpcFlagsmask)
return unit;
}
GameObject* Player::GetGameObjectIfCanInteractWith(ObjectGuid guid, uint32 gameobject_type) const
GameObject* Player::GetGameObjectIfCanInteractWith(ObjectGuid guid, uint32 gameobject_type)
{
// some basic checks
if (!guid || !IsInWorld() || IsTaxiFlying())
return NULL;
// set player as interacting
DoInteraction(guid);
// not in interactive state
if (hasUnitState(UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL))
return NULL;
@ -21270,6 +21276,24 @@ void Player::SetClientControl(Unit* target, uint8 allowMove)
GetSession()->SendPacket(&data);
}
void Player::Uncharm()
{
if (Unit* charm = GetCharm())
{
charm->RemoveSpellsCausingAura(SPELL_AURA_MOD_CHARM);
charm->RemoveSpellsCausingAura(SPELL_AURA_MOD_POSSESS);
charm->RemoveSpellsCausingAura(SPELL_AURA_MOD_POSSESS_PET);
if (charm == GetMover())
{
SetMover(nullptr);
GetCamera().ResetView();
RemoveSpellsCausingAura(SPELL_AURA_MOD_INVISIBILITY);
SetCharm(nullptr);
SetClientControl(this, 1);
}
}
}
void Player::UpdateZoneDependentAuras()
{
// Some spells applied at enter into zone (with subzones), aura removed in UpdateAreaDependentAuras that called always at zone->area update
@ -22699,6 +22723,15 @@ void Player::UnsummonPetTemporaryIfAny()
pet->Unsummon(PET_SAVE_AS_CURRENT, this);
}
void Player::UnsummonPetIfAny()
{
Pet* pet = GetPet();
if (!pet)
return;
pet->Unsummon(PET_SAVE_NOT_IN_SLOT, this);
}
void Player::ResummonPetTemporaryUnSummonedIfAny()
{
if (!m_temporaryUnsummonedPetNumber)
@ -24307,6 +24340,41 @@ float Player::GetCollisionHeight(bool mounted) const
}
}
// set data to accept next resurrect response and process it with required data
void Player::setResurrectRequestData(Unit* caster, uint32 health, uint32 mana)
{
m_resurrectGuid = caster->GetObjectGuid();
m_resurrectMap = caster->GetMapId();
caster->GetPosition(m_resurrectX, m_resurrectY, m_resurrectZ);
m_resurrectHealth = health;
m_resurrectMana = mana;
m_resurrectToGhoul = false;
}
// we can use this to prepare data in case we have to resurrect player in ghoul form
void Player::setResurrectRequestDataToGhoul(Unit* caster)
{
setResurrectRequestData(caster, 0, 0);
m_resurrectToGhoul = true;
}
// player is interacting so we have to remove non authorized aura
void Player::DoInteraction(ObjectGuid const& interactObjGuid)
{
if (interactObjGuid.IsUnit())
{
// remove some aura like stealth aura
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK);
}
else if (interactObjGuid.IsGameObject())
{
// remove some aura like stealth aura
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_USE);
}
SendForcedObjectUpdate();
}
void Player::SendPetitionSignResult(ObjectGuid petitionGuid, Player* player, uint32 result)
{
WorldPacket data(SMSG_PETITION_SIGN_RESULTS, 8 + 8 + 4);

View file

@ -1128,7 +1128,7 @@ class Player : public Unit
void SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time);
Creature* GetNPCIfCanInteractWith(ObjectGuid guid, uint32 NpcFlagsmask);
GameObject* GetGameObjectIfCanInteractWith(ObjectGuid guid, uint32 gameobject_type = MAX_GAMEOBJECT_TYPE) const;
GameObject* GetGameObjectIfCanInteractWith(ObjectGuid guid, uint32 gameobject_type = MAX_GAMEOBJECT_TYPE);
void ToggleAFK();
void ToggleDND();
@ -1214,7 +1214,13 @@ class Player : public Unit
* \param: bool inRestPlace > if it was offline, is the player was in city/tavern/inn?
* \returns: float
**/
float ComputeRest(time_t timePassed, bool offline = false, bool inRestPlace = false);
float ComputeRest(time_t timePassed, bool offline = false, bool inRestPlace = false);
/**
* \brief: player is interacting with something.
* \param: ObjectGuid interactObj > object that interact with this player
**/
void DoInteraction(ObjectGuid const& interactObjGuid);
RestType GetRestType() const
{
@ -1817,6 +1823,8 @@ class Player : public Unit
uint32 GetLastPotionId() { return m_lastPotionId; }
void UpdatePotionCooldown(Spell* spell = NULL);
void setResurrectRequestData(Unit* caster, uint32 health, uint32 mana);
void setResurrectRequestDataToGhoul(Unit* caster);
void setResurrectRequestData(ObjectGuid guid, uint32 mapId, float X, float Y, float Z, uint32 health, uint32 mana)
{
m_resurrectGuid = guid;
@ -2413,6 +2421,7 @@ class Player : public Unit
void SetMover(Unit* target) { m_mover = target ? target : this; }
Unit* GetMover() const { return m_mover; }
bool IsSelfMover() const { return m_mover == this; }// normal case for player not controlling other unit
void Uncharm() override;
ObjectGuid const& GetFarSightGuid() const { return GetGuidValue(PLAYER_FARSIGHT); }
@ -2472,6 +2481,7 @@ class Player : public Unit
uint32 GetTemporaryUnsummonedPetNumber() const { return m_temporaryUnsummonedPetNumber; }
void SetTemporaryUnsummonedPetNumber(uint32 petnumber) { m_temporaryUnsummonedPetNumber = petnumber; }
void UnsummonPetTemporaryIfAny();
void UnsummonPetIfAny();
void ResummonPetTemporaryUnSummonedIfAny();
bool IsPetNeedBeTemporaryUnsummoned() const { return !IsInWorld() || !IsAlive() || IsMounted() /*+in flight*/; }
@ -2745,6 +2755,7 @@ class Player : public Unit
uint32 m_resurrectMap;
float m_resurrectX, m_resurrectY, m_resurrectZ;
uint32 m_resurrectHealth, m_resurrectMana;
bool m_resurrectToGhoul;
WorldSession* m_session;

View file

@ -27,7 +27,7 @@
#include "CreatureAI.h"
TemporarySummon::TemporarySummon(ObjectGuid summoner) :
Creature(CREATURE_SUBTYPE_TEMPORARY_SUMMON), m_type(TEMPSUMMON_TIMED_OOC_OR_CORPSE_DESPAWN), m_timer(0), m_lifetime(0), m_summoner(summoner)
Creature(CREATURE_SUBTYPE_TEMPORARY_SUMMON), m_type(TEMPSUMMON_TIMED_OOC_OR_CORPSE_DESPAWN), m_timer(0), m_lifetime(0), m_summoner(summoner), m_linkedToOwnerAura(0)
{
}
@ -189,31 +189,93 @@ void TemporarySummon::Update(uint32 update_diff, uint32 diff)
break;
}
switch (m_deathState)
{
case ALIVE:
if (m_linkedToOwnerAura & TEMPSUMMON_LINKED_AURA_OWNER_CHECK)
{
// we have to check if owner still have the required aura
Unit* owner = GetCharmerOrOwner();
uint32 const& spellId = GetUInt32Value(UNIT_CREATED_BY_SPELL);
if (!owner || !spellId || !owner->HasAura(spellId))
UnSummon();
}
break;
case DEAD:
case CORPSE:
if (m_linkedToOwnerAura & TEMPSUMMON_LINKED_AURA_REMOVE_OWNER)
{
RemoveAuraFromOwner();
m_linkedToOwnerAura = 0; // we dont need to recheck
}
default:
break;
}
Creature::Update(update_diff, diff);
}
void TemporarySummon::Summon(TempSummonType type, uint32 lifetime)
void TemporarySummon::SetSummonProperties(TempSummonType type, uint32 lifetime)
{
m_type = type;
m_timer = lifetime;
m_lifetime = lifetime;
}
void TemporarySummon::Summon(TempSummonType type, uint32 lifetime)
{
SetSummonProperties(type, lifetime);
GetMap()->Add((Creature*)this);
AIM_Initialize();
GetMap()->Add((Creature*)this);
}
void TemporarySummon::UnSummon()
{
CombatStop();
if (m_linkedToOwnerAura & TEMPSUMMON_LINKED_AURA_REMOVE_OWNER)
RemoveAuraFromOwner();
if (GetSummonerGuid().IsCreatureOrVehicle())
{
if (Creature* sum = GetMap()->GetCreature(GetSummonerGuid()))
if (sum->AI())
sum->AI()->SummonedCreatureDespawn(this);
}
else if (GetSummonerGuid().IsPlayer()) // if player that summoned this creature was MCing it, uncharm
if (Player* player = GetMap()->GetPlayer(GetSummonerGuid()))
if (player->GetMover() == this)
player->Uncharm();
if (AI())
AI()->SummonedCreatureDespawn(this);
AddObjectToRemoveList();
}
void TemporarySummon::RemoveAuraFromOwner()
{
// creature is dead and we have to remove the charmer aura if exist
uint32 const& spellId = GetUInt32Value(UNIT_CREATED_BY_SPELL);
if (spellId)
{
if (Unit* charmer = GetCharmer())
{
charmer->RemoveAurasDueToSpell(spellId);
charmer->ResetControlState(false);
}
else if (Unit* owner = GetOwner())
{
owner->RemoveAurasDueToSpell(spellId);
}
}
}
void TemporarySummon::SaveToDB()
{
}

View file

@ -35,12 +35,15 @@ class TemporarySummon : public Creature
virtual ~TemporarySummon() {};
void Update(uint32 update_diff, uint32 time) override;
void SetSummonProperties(TempSummonType type, uint32 lifetime);
void Summon(TempSummonType type, uint32 lifetime);
void UnSummon();
void MANGOS_DLL_SPEC UnSummon();
void SaveToDB();
ObjectGuid const& GetSummonerGuid() const { return m_summoner ; }
Unit* GetSummoner() const { return ObjectAccessor::GetUnit(*this, m_summoner); }
void SetLinkedToOwnerAura(uint32 flags) { m_linkedToOwnerAura |= flags; };
private:
void RemoveAuraFromOwner();
void SaveToDB(uint32, uint8, uint32) override // overwrited of Creature::SaveToDB - don't must be called
{
MANGOS_ASSERT(false);
@ -54,6 +57,7 @@ class TemporarySummon : public Creature
uint32 m_timer;
uint32 m_lifetime;
ObjectGuid m_summoner;
uint32 m_linkedToOwnerAura;
};
class TemporarySummonWaypoint : public TemporarySummon

View file

@ -12298,3 +12298,225 @@ void Unit::SendCollisionHeightUpdate(float height)
}
}
// This will create a new creature and set the current unit as the controller of that new creature
Unit* Unit::TakePossessOf(SpellEntry const* spellEntry, SummonPropertiesEntry const* summonProp, SpellEffectEntry const* spellEffect, float x, float y, float z, float ang)
{
int32 const& creatureEntry = spellEffect->EffectMiscValue;
CreatureInfo const* cinfo = ObjectMgr::GetCreatureTemplate(creatureEntry);
if (!cinfo)
{
sLog.outErrorDb("WorldObject::SummonCreature: Creature (Entry: %u) not existed for summoner: %s. ", creatureEntry, GetGuidStr().c_str());
return nullptr;
}
if (GetCharm())
{
sLog.outError("Unit::TakePossessOf> There is already a charmed creature for %s its : %s. ", GetGuidStr().c_str(), GetCharm()->GetGuidStr().c_str());
return nullptr;
}
TemporarySummon* pCreature = new TemporarySummon(GetObjectGuid());
CreatureCreatePos pos(GetMap(), x, y, z, ang, GetPhaseMask());
if (x == 0.0f && y == 0.0f && z == 0.0f)
pos = CreatureCreatePos(this, GetOrientation(), CONTACT_DISTANCE, ang);
if (!pCreature->Create(GetMap()->GenerateLocalLowGuid(cinfo->GetHighGuid()), pos, cinfo))
{
delete pCreature;
return nullptr;
}
Player* player = GetTypeId() == TYPEID_PLAYER ? static_cast<Player*>(this): nullptr;
pCreature->setFaction(getFaction()); // set same faction than player
pCreature->SetRespawnCoord(pos); // set spawn coord
pCreature->SetCharmerGuid(GetObjectGuid()); // save guid of the charmer
pCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, spellEntry->Id); // set the spell id used to create this (may be used for removing corresponding aura
pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); // set flag for client that mean this unit is controlled by a player
pCreature->addUnitState(UNIT_STAT_CONTROLLED); // also set internal unit state flag
pCreature->SelectLevel(getLevel()); // set level to same level than summoner TODO:: not sure its always the case...
pCreature->SetLinkedToOwnerAura(TEMPSUMMON_LINKED_AURA_OWNER_CHECK | TEMPSUMMON_LINKED_AURA_REMOVE_OWNER); // set what to do if linked aura is removed or the creature is dead.
pCreature->SetWalk(IsWalking(), true); // sync the walking state with the summoner
// important before adding to the map!
SetCharmGuid(pCreature->GetObjectGuid()); // save guid of charmed creature
pCreature->SetSummonProperties(TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); // set 5s corpse decay
GetMap()->Add(static_cast<Creature*>(pCreature)); // create the creature in the client
// Give the control to the player
if (player)
{
player->GetCamera().SetView(pCreature); // modify camera view to the creature view
player->SetClientControl(pCreature, 1); // transfer client control to the creature
player->SetMover(pCreature); // set mover so now we know that creature is "moved" by this unit
player->SendForcedObjectUpdate(); // we have to update client data here to avoid problem with the "release spirit" windows reappear.
}
// initialize AI
pCreature->AIM_Initialize();
if (player)
{
// Initialize pet bar
if (CharmInfo* charmInfo = pCreature->InitCharmInfo(pCreature))
charmInfo->InitPossessCreateSpells();
player->PossessSpellInitialize();
}
else
{
// fire just summoned hook
if (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->AI())
((Creature*)this)->AI()->JustSummoned(pCreature);
}
// Creature Linking, Initial load is handled like respawn
if (pCreature->IsLinkingEventTrigger())
GetMap()->GetCreatureLinkingHolder()->DoCreatureLinkingEvent(LINKING_EVENT_RESPAWN, pCreature);
// return the creature therewith the summoner has access to it
return pCreature;
}
bool Unit::TakePossessOf(Unit* possessed)
{
Player* player = nullptr;
if (GetTypeId() == TYPEID_PLAYER)
player = static_cast<Player *>(this);
possessed->addUnitState(UNIT_STAT_CONTROLLED);
possessed->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
possessed->SetCharmerGuid(GetObjectGuid());
possessed->setFaction(getFaction());
SetCharm(possessed);
Creature* possessedCreature = nullptr;
if (possessed->GetTypeId() == TYPEID_UNIT)
possessedCreature = static_cast<Creature *>(possessed);
if (player)
{
player->GetCamera().SetView(possessed);
player->SetClientControl(possessed, 1);
player->SetMover(possessed);
player->SendForcedObjectUpdate();
if (possessedCreature && possessedCreature->IsPet() && possessedCreature->GetObjectGuid() == GetPetGuid())
{
possessed->StopMoving();
possessed->GetMotionMaster()->Clear(false);
possessed->GetMotionMaster()->MoveIdle();
return true;
}
else if (CharmInfo* charmInfo = possessed->InitCharmInfo(possessed))
{
charmInfo->InitPossessCreateSpells();
charmInfo->SetReactState(REACT_PASSIVE);
charmInfo->SetCommandState(COMMAND_STAY);
}
player->PossessSpellInitialize();
}
possessed->CombatStop(true);
possessed->DeleteThreatList();
possessed->getHostileRefManager().deleteReferences();
if (possessedCreature)
{
possessedCreature->AIM_Initialize();
}
else if (possessed->GetTypeId() == TYPEID_PLAYER)
{
static_cast<Player*>(possessed)->SetClientControl(possessed, 0);
}
return true;
}
void Unit::ResetControlState(bool attackCharmer /*= true*/)
{
Player* player = nullptr;
if (GetTypeId() == TYPEID_PLAYER)
player = static_cast<Player *>(this);
Unit* possessed = GetCharm();
if (!possessed)
{
if (player)
{
player->GetCamera().ResetView();
player->SetClientControl(player, 1);
player->SetMover(nullptr);
}
return;
}
Creature* possessedCreature = static_cast<Creature *>(possessed);
possessed->clearUnitState(UNIT_STAT_CONTROLLED);
possessed->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
possessed->SetCharmerGuid(ObjectGuid());
SetCharmGuid(ObjectGuid());
if (player)
{
player->SetClientControl(possessed, 0);
player->SetMover(nullptr);
player->GetCamera().ResetView();
if (possessedCreature->IsPet() && possessedCreature->GetObjectGuid() == GetPetGuid())
{
// out of range pet dismissed
if (!possessedCreature->IsWithinDistInMap(this, possessedCreature->GetMap()->GetVisibilityDistance()))
{
player->RemovePet(PET_SAVE_REAGENTS);
}
else
{
possessedCreature->GetMotionMaster()->MoveFollow(this, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
}
return;
}
else
player->RemovePetActionBar();
}
possessed->CombatStop(true);
possessed->DeleteThreatList();
possessed->getHostileRefManager().deleteReferences();
if (possessed->GetTypeId() == TYPEID_PLAYER)
{
Player* possessedPlayer = static_cast<Player *>(possessed);
possessedPlayer->setFactionForRace(possessedPlayer->getRace());
possessedPlayer->SetClientControl(possessedPlayer, 1);
}
else if (possessedCreature)
{
if (possessedCreature->IsPet() && possessedCreature->GetObjectGuid() == GetPetGuid())
{
// out of range pet dismissed
if (!possessedCreature->IsWithinDistInMap(this, possessedCreature->GetMap()->GetVisibilityDistance()))
{
player->RemovePet(PET_SAVE_REAGENTS);
}
else
{
possessedCreature->GetMotionMaster()->MoveFollow(this, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
}
}
else if (attackCharmer)
{
CreatureInfo const* cinfo = possessedCreature->GetCreatureInfo();
possessedCreature->setFaction(cinfo->FactionAlliance);
possessedCreature->AIM_Initialize();
possessedCreature->AttackedBy(this);
}
}
}

View file

@ -2826,7 +2826,7 @@ class Unit : public WorldObject
* - \ref AuraType::SPELL_AURA_MOD_POSSESS
* - \ref AuraType::SPELL_AURA_MOD_POSSESS_PET
*/
void Uncharm();
virtual void Uncharm();
/**
* Does the same as \ref Unit::GetCharmerOrOwnerGuid but returns the \ref Unit for that instead
* @return the \ref Unit that's charming this one or owning it, NULL if there is none
@ -3530,6 +3530,15 @@ class Unit : public WorldObject
void BuildMoveHoverPacket(WorldPacket* data, bool apply, uint32 value);
void BuildMoveLevitatePacket(WorldPacket* data, bool apply, uint32 value);
// Take possession of an unit (pet, creature, ...)
bool TakePossessOf(Unit* possessed);
// Take possession of a new spawned unit
Unit* TakePossessOf(SpellEntry const* spellEntry, SummonPropertiesEntry const* summonProp, SpellEffectEntry const* spellEffect, float x, float y, float z, float ang);
// Reset control to player
void ResetControlState(bool attackCharmer = true);
protected:
explicit Unit();