Merge pull request #16644 from Treeston/3.3.5-customcharmai
Core/UnitAI: Rework creature-controlled player behavior.
This commit is contained in:
commit
4e4b2b9a13
13 files changed
+304
-102
No files matched your search
@@ -259,36 +259,6 @@ void UnitAI::FillAISpellInfo()
|
||||
}
|
||||
}
|
||||
|
||||
//Enable PlayerAI when charmed
|
||||
void PlayerAI::OnCharmed(bool apply)
|
||||
{
|
||||
me->IsAIEnabled = apply;
|
||||
}
|
||||
|
||||
void SimpleCharmedAI::UpdateAI(const uint32 /*diff*/)
|
||||
{
|
||||
Creature* charmer = me->GetCharmer()->ToCreature();
|
||||
|
||||
//kill self if charm aura has infinite duration
|
||||
if (charmer->IsInEvadeMode())
|
||||
{
|
||||
Unit::AuraEffectList const& auras = me->GetAuraEffectsByType(SPELL_AURA_MOD_CHARM);
|
||||
for (Unit::AuraEffectList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter)
|
||||
if ((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->GetBase()->IsPermanent())
|
||||
{
|
||||
charmer->Kill(me);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!charmer->IsInCombat())
|
||||
me->GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, me->GetFollowAngle());
|
||||
|
||||
Unit* target = me->GetVictim();
|
||||
if (!target || !charmer->IsValidAttackTarget(target))
|
||||
AttackStart(charmer->SelectNearestTargetInAttackDistance());
|
||||
}
|
||||
|
||||
SpellTargetSelector::SpellTargetSelector(Unit* caster, uint32 spellId) :
|
||||
_caster(caster), _spellInfo(sSpellMgr->GetSpellForDifficultyFromSpell(sSpellMgr->GetSpellInfo(spellId), caster))
|
||||
{
|
||||
|
||||
@@ -268,21 +268,4 @@ class UnitAI
|
||||
UnitAI& operator=(UnitAI const& right) = delete;
|
||||
};
|
||||
|
||||
class PlayerAI : public UnitAI
|
||||
{
|
||||
protected:
|
||||
Player* const me;
|
||||
public:
|
||||
explicit PlayerAI(Player* player) : UnitAI((Unit*)player), me(player) { }
|
||||
|
||||
void OnCharmed(bool apply) override;
|
||||
};
|
||||
|
||||
class SimpleCharmedAI : public PlayerAI
|
||||
{
|
||||
public:
|
||||
void UpdateAI(uint32 diff) override;
|
||||
SimpleCharmedAI(Player* player): PlayerAI(player) { }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -28,6 +28,7 @@ class WorldObject;
|
||||
class Unit;
|
||||
class Creature;
|
||||
class Player;
|
||||
class PlayerAI;
|
||||
class SpellInfo;
|
||||
|
||||
#define TIME_INTERVAL_LOOK 5000
|
||||
@@ -186,6 +187,11 @@ class CreatureAI : public UnitAI
|
||||
|
||||
virtual bool CanSeeAlways(WorldObject const* /*obj*/) { return false; }
|
||||
|
||||
// Called when a player is charmed by the creature
|
||||
// If a PlayerAI* is returned, that AI is placed on the player instead of the default charm AI
|
||||
// Object destruction is handled by Unit::RemoveCharmedBy
|
||||
virtual PlayerAI* GetAIForCharmedPlayer(Player* /*who*/) { return nullptr; }
|
||||
|
||||
// intended for encounter design/debugging. do not use for other purposes. expensive.
|
||||
int32 VisualizeBoundary(uint32 duration, Unit* owner=nullptr, bool fill=false) const;
|
||||
virtual bool CheckInRoom();
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2016 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PlayerAI.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
/* Generic */
|
||||
SPELL_AUTO_SHOT = 75,
|
||||
SPELL_SHOOT = 3018,
|
||||
SPELL_THROW = 2764,
|
||||
SPELL_SHOOT_WAND = 5019,
|
||||
|
||||
/* Priest */
|
||||
SPELL_SHADOWFORM = 15473,
|
||||
|
||||
/* Shaman */
|
||||
SPELL_STORMSTRIKE = 17364,
|
||||
|
||||
/* Druid */
|
||||
SPELL_MOONKIN_FORM = 24858
|
||||
};
|
||||
PlayerAI::PlayerAI(Player* player) : UnitAI(static_cast<Unit*>(player)), me(player), _isRangedAttacker(false)
|
||||
{
|
||||
switch (me->getClass())
|
||||
{
|
||||
case CLASS_WARRIOR:
|
||||
_isRangedAttacker = false;
|
||||
break;
|
||||
case CLASS_PALADIN:
|
||||
_isRangedAttacker = false;
|
||||
break;
|
||||
case CLASS_HUNTER:
|
||||
{
|
||||
// check if we have a ranged weapon equipped
|
||||
Item const* rangedSlot = me->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED);
|
||||
if (ItemTemplate const* rangedTemplate = rangedSlot ? rangedSlot->GetTemplate() : nullptr)
|
||||
if ((1 << rangedTemplate->SubClass) & ITEM_SUBCLASS_MASK_WEAPON_RANGED)
|
||||
{
|
||||
_isRangedAttacker = true;
|
||||
break;
|
||||
}
|
||||
_isRangedAttacker = false;
|
||||
break;
|
||||
}
|
||||
case CLASS_ROGUE:
|
||||
_isRangedAttacker = false;
|
||||
break;
|
||||
case CLASS_PRIEST:
|
||||
_isRangedAttacker = me->HasSpell(SPELL_SHADOWFORM);
|
||||
break;
|
||||
case CLASS_DEATH_KNIGHT:
|
||||
_isRangedAttacker = false;
|
||||
break;
|
||||
case CLASS_SHAMAN:
|
||||
_isRangedAttacker = !me->HasSpell(SPELL_STORMSTRIKE);
|
||||
break;
|
||||
case CLASS_MAGE:
|
||||
_isRangedAttacker = true;
|
||||
break;
|
||||
case CLASS_WARLOCK:
|
||||
_isRangedAttacker = true;
|
||||
break;
|
||||
case CLASS_DRUID:
|
||||
_isRangedAttacker = me->HasAura(SPELL_MOONKIN_FORM);
|
||||
break;
|
||||
default:
|
||||
TC_LOG_WARN("entities.unit", "Possessed player %s (possessed by %s) does not have any recognized class (class = %u).", me->GetGUID().ToString().c_str(), me->GetCharmerGUID().ToString().c_str(), me->getClass());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerAI::DoRangedAttackIfReady()
|
||||
{
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
if (!me->isAttackReady(RANGED_ATTACK))
|
||||
return;
|
||||
|
||||
Unit* victim = me->GetVictim();
|
||||
if (!victim)
|
||||
return;
|
||||
|
||||
uint32 rangedAttackSpell = 0;
|
||||
|
||||
Item const* rangedItem = me->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED);
|
||||
if (ItemTemplate const* rangedTemplate = rangedItem ? rangedItem->GetTemplate() : nullptr)
|
||||
{
|
||||
switch (rangedTemplate->SubClass)
|
||||
{
|
||||
case ITEM_SUBCLASS_WEAPON_BOW:
|
||||
case ITEM_SUBCLASS_WEAPON_GUN:
|
||||
case ITEM_SUBCLASS_WEAPON_CROSSBOW:
|
||||
rangedAttackSpell = SPELL_SHOOT;
|
||||
break;
|
||||
case ITEM_SUBCLASS_WEAPON_THROWN:
|
||||
rangedAttackSpell = SPELL_THROW;
|
||||
break;
|
||||
case ITEM_SUBCLASS_WEAPON_WAND:
|
||||
rangedAttackSpell = SPELL_SHOOT_WAND;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Selected " << rangedAttackSpell << std::endl;
|
||||
|
||||
if (!rangedAttackSpell)
|
||||
return;
|
||||
|
||||
me->CastSpell(victim, rangedAttackSpell, TRIGGERED_CAST_DIRECTLY);
|
||||
me->resetAttackTimer(RANGED_ATTACK);
|
||||
}
|
||||
|
||||
void PlayerAI::DoAutoAttackIfReady()
|
||||
{
|
||||
if (IsRangedAttacker())
|
||||
DoRangedAttackIfReady();
|
||||
else
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void SimpleCharmedPlayerAI::UpdateAI(const uint32 /*diff*/)
|
||||
{
|
||||
Creature* charmer = me->GetCharmer()->ToCreature();
|
||||
|
||||
//kill self if charm aura has infinite duration
|
||||
if (charmer->IsInEvadeMode())
|
||||
{
|
||||
Player::AuraEffectList const& auras = me->GetAuraEffectsByType(SPELL_AURA_MOD_CHARM);
|
||||
for (Player::AuraEffectList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter)
|
||||
if ((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->GetBase()->IsPermanent())
|
||||
{
|
||||
me->Kill(me);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (charmer->IsInCombat())
|
||||
{
|
||||
Unit* target = me->GetVictim();
|
||||
if (!target || !charmer->IsValidAttackTarget(target))
|
||||
{
|
||||
target = charmer->SelectNearestTarget();
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
if (IsRangedAttacker())
|
||||
AttackStartCaster(target, 28.0f);
|
||||
else
|
||||
AttackStart(target);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
me->AttackStop();
|
||||
me->CastStop();
|
||||
me->GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
|
||||
}
|
||||
|
||||
DoAutoAttackIfReady();
|
||||
}
|
||||
|
||||
void SimpleCharmedPlayerAI::OnCharmed(bool apply)
|
||||
{
|
||||
if (apply)
|
||||
{
|
||||
me->CastStop();
|
||||
me->AttackStop();
|
||||
}
|
||||
else
|
||||
{
|
||||
me->CastStop();
|
||||
me->AttackStop();
|
||||
// @todo only voluntary movement (don't cancel stuff like death grip or charge mid-animation)
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->StopMoving();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2016 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TRINITY_PLAYERAI_H
|
||||
#define TRINITY_PLAYERAI_H
|
||||
|
||||
#include "UnitAI.h"
|
||||
#include "Player.h"
|
||||
#include "Creature.h"
|
||||
|
||||
class PlayerAI : public UnitAI
|
||||
{
|
||||
public:
|
||||
explicit PlayerAI(Player* player);
|
||||
|
||||
void OnCharmed(bool /*apply*/) override { } // charm AI application for players is handled by Unit::SetCharmedBy / Unit::RemoveCharmedBy
|
||||
|
||||
protected:
|
||||
Player* const me;
|
||||
void SetIsRangedAttacker(bool state) { _isRangedAttacker = state; }
|
||||
bool IsRangedAttacker() const { return _isRangedAttacker; }
|
||||
|
||||
void DoRangedAttackIfReady();
|
||||
void DoAutoAttackIfReady();
|
||||
|
||||
private:
|
||||
bool _isRangedAttacker;
|
||||
};
|
||||
|
||||
class SimpleCharmedPlayerAI : public PlayerAI
|
||||
{
|
||||
public:
|
||||
SimpleCharmedPlayerAI(Player* player) : PlayerAI(player) { }
|
||||
void UpdateAI(uint32 diff) override;
|
||||
void OnCharmed(bool apply) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -108,6 +108,7 @@ include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Addons
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/AI
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/AI/CoreAI
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/AI/PlayerAI
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/AI/ScriptedAI
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/AI/SmartScripts
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/AuctionHouse
|
||||
|
||||
@@ -479,7 +479,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
|
||||
bool AIM_Initialize(CreatureAI* ai = NULL);
|
||||
void Motion_Initialize();
|
||||
|
||||
CreatureAI* AI() const { return (CreatureAI*)i_AI; }
|
||||
CreatureAI* AI() const { return reinterpret_cast<CreatureAI*>(i_AI); }
|
||||
|
||||
bool SetWalk(bool enable) override;
|
||||
bool SetDisableGravity(bool disable, bool packetOnly = false) override;
|
||||
|
||||
@@ -1237,12 +1237,7 @@ void Player::Update(uint32 p_time)
|
||||
|
||||
UpdateAfkReport(now);
|
||||
|
||||
if (IsCharmed())
|
||||
if (Unit* charmer = GetCharmer())
|
||||
if (charmer->GetTypeId() == TYPEID_UNIT && charmer->IsAlive())
|
||||
UpdateCharmedAI();
|
||||
|
||||
if (GetAI() && IsAIEnabled)
|
||||
if (IsAIEnabled && GetAI())
|
||||
GetAI()->UpdateAI(p_time);
|
||||
|
||||
// Update items that have just a limited lifetime
|
||||
@@ -24129,38 +24124,6 @@ bool Player::isTotalImmunity()
|
||||
return false;
|
||||
}
|
||||
|
||||
void Player::UpdateCharmedAI()
|
||||
{
|
||||
//This should only called in Player::Update
|
||||
Creature* charmer = GetCharmer()->ToCreature();
|
||||
|
||||
//kill self if charm aura has infinite duration
|
||||
if (charmer->IsInEvadeMode())
|
||||
{
|
||||
AuraEffectList const& auras = GetAuraEffectsByType(SPELL_AURA_MOD_CHARM);
|
||||
for (AuraEffectList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter)
|
||||
if ((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->GetBase()->IsPermanent())
|
||||
{
|
||||
charmer->DealDamage(this, GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!charmer->IsInCombat())
|
||||
GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
|
||||
|
||||
Unit* target = GetVictim();
|
||||
if (!target || !charmer->IsValidAttackTarget(target))
|
||||
{
|
||||
target = charmer->SelectNearestTarget();
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
GetMotionMaster()->MoveChase(target);
|
||||
Attack(target, true);
|
||||
}
|
||||
}
|
||||
|
||||
uint32 Player::GetRuneBaseCooldown(uint8 index)
|
||||
{
|
||||
uint8 rune = GetBaseRune(index);
|
||||
|
||||
@@ -54,6 +54,7 @@ class PlayerMenu;
|
||||
class PlayerSocial;
|
||||
class SpellCastTargets;
|
||||
class UpdateMask;
|
||||
class PlayerAI;
|
||||
|
||||
struct CharacterCustomizeInfo;
|
||||
|
||||
@@ -1022,6 +1023,8 @@ class Player : public Unit, public GridObject<Player>
|
||||
explicit Player(WorldSession* session);
|
||||
~Player();
|
||||
|
||||
PlayerAI* AI() const { return reinterpret_cast<PlayerAI*>(i_AI); }
|
||||
|
||||
void CleanupsBeforeDelete(bool finalCleanup = true) override;
|
||||
|
||||
void AddToWorld() override;
|
||||
@@ -2533,8 +2536,6 @@ class Player : public Unit, public GridObject<Player>
|
||||
|
||||
MapReference m_mapRef;
|
||||
|
||||
void UpdateCharmedAI();
|
||||
|
||||
uint32 m_lastFallTime;
|
||||
float m_lastFallZ;
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "PetAI.h"
|
||||
#include "Pet.h"
|
||||
#include "Player.h"
|
||||
#include "PlayerAI.h"
|
||||
#include "QuestDef.h"
|
||||
#include "ReputationMgr.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
@@ -15902,11 +15903,21 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
|
||||
ToCreature()->AI()->OnCharmed(true);
|
||||
GetMotionMaster()->MoveIdle();
|
||||
}
|
||||
else
|
||||
else if (Player* player = ToPlayer())
|
||||
{
|
||||
Player* player = ToPlayer();
|
||||
if (player->isAFK())
|
||||
player->ToggleAFK();
|
||||
|
||||
if (Creature* creatureCharmer = charmer->ToCreature()) // we are charmed by a creature
|
||||
{
|
||||
IsAIEnabled = true;
|
||||
i_disabledAI = i_AI;
|
||||
// set our AI to the charmer's custom charm AI if applicable
|
||||
if (PlayerAI* charmAI = creatureCharmer->AI()->GetAIForCharmedPlayer(player))
|
||||
i_AI = charmAI;
|
||||
else // otherwise use the default charmed player AI
|
||||
i_AI = new SimpleCharmedPlayerAI(player);
|
||||
}
|
||||
player->SetClientControl(this, false);
|
||||
}
|
||||
|
||||
@@ -16064,7 +16075,24 @@ void Unit::RemoveCharmedBy(Unit* charmer)
|
||||
}
|
||||
|
||||
if (Player* player = ToPlayer())
|
||||
{
|
||||
if (charmer->GetTypeId() == TYPEID_UNIT) // charmed by a creature, this means we had PlayerAI
|
||||
{
|
||||
if (i_AI)
|
||||
{
|
||||
// allow charmed player AI to clean up
|
||||
i_AI->OnCharmed(false);
|
||||
// then delete it
|
||||
delete i_AI;
|
||||
// and restore our previous playerAI (if we had one)
|
||||
if ((i_AI = i_disabledAI))
|
||||
i_disabledAI = nullptr;
|
||||
else
|
||||
IsAIEnabled = false;
|
||||
}
|
||||
}
|
||||
player->SetClientControl(this, true);
|
||||
}
|
||||
|
||||
// a guardian should always have charminfo
|
||||
if (playerCharmer && this != charmer->GetFirstControlled())
|
||||
|
||||
@@ -73,6 +73,7 @@ include_directories(
|
||||
${CMAKE_SOURCE_DIR}/src/server/game/Addons
|
||||
${CMAKE_SOURCE_DIR}/src/server/game/AI
|
||||
${CMAKE_SOURCE_DIR}/src/server/game/AI/CoreAI
|
||||
${CMAKE_SOURCE_DIR}/src/server/game/AI/PlayerAI
|
||||
${CMAKE_SOURCE_DIR}/src/server/game/AI/ScriptedAI
|
||||
${CMAKE_SOURCE_DIR}/src/server/game/AI/SmartScripts
|
||||
${CMAKE_SOURCE_DIR}/src/server/game/AuctionHouse
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "pit_of_saron.h"
|
||||
#include "Vehicle.h"
|
||||
#include "Player.h"
|
||||
#include "PlayerAI.h"
|
||||
|
||||
enum Yells
|
||||
{
|
||||
@@ -438,9 +439,10 @@ class spell_tyrannus_overlord_brand : public SpellScriptLoader
|
||||
if (GetTarget()->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
oldAI = GetTarget()->GetAI();
|
||||
oldAIState = GetTarget()->IsAIEnabled;
|
||||
GetTarget()->SetAI(new player_overlord_brandAI(GetTarget()->ToPlayer(), GetCasterGUID()));
|
||||
Player* pTarget = GetTarget()->ToPlayer();
|
||||
oldAI = pTarget->AI();
|
||||
oldAIState = pTarget->IsAIEnabled;
|
||||
GetTarget()->SetAI(static_cast<UnitAI*>(new player_overlord_brandAI(pTarget, GetCasterGUID())));
|
||||
GetTarget()->IsAIEnabled = true;
|
||||
}
|
||||
|
||||
@@ -450,8 +452,8 @@ class spell_tyrannus_overlord_brand : public SpellScriptLoader
|
||||
return;
|
||||
|
||||
GetTarget()->IsAIEnabled = oldAIState;
|
||||
UnitAI* thisAI = GetTarget()->GetAI();
|
||||
GetTarget()->SetAI(oldAI);
|
||||
PlayerAI* thisAI = GetTarget()->ToPlayer()->AI();
|
||||
GetTarget()->SetAI(static_cast<UnitAI*>(oldAI));
|
||||
delete thisAI;
|
||||
}
|
||||
|
||||
@@ -461,7 +463,7 @@ class spell_tyrannus_overlord_brand : public SpellScriptLoader
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_tyrannus_overlord_brand_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
|
||||
UnitAI* oldAI;
|
||||
PlayerAI* oldAI;
|
||||
bool oldAIState;
|
||||
};
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
#include "Player.h"
|
||||
#include "UnitAI.h"
|
||||
#include "PlayerAI.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
@@ -1909,9 +1909,9 @@ public:
|
||||
if (!player || player->GetGhoulResurrectGhoulGUID().IsEmpty())
|
||||
return;
|
||||
|
||||
oldAI = player->GetAI();
|
||||
oldAI = player->AI();
|
||||
oldAIState = player->IsAIEnabled;
|
||||
player->SetAI(new player_ghoulAI(player, player->GetGhoulResurrectGhoulGUID()));
|
||||
player->SetAI(static_cast<UnitAI*>(new player_ghoulAI(player, player->GetGhoulResurrectGhoulGUID())));
|
||||
player->IsAIEnabled = true;
|
||||
}
|
||||
|
||||
@@ -1922,8 +1922,8 @@ public:
|
||||
return;
|
||||
|
||||
player->IsAIEnabled = oldAIState;
|
||||
UnitAI* thisAI = player->GetAI();
|
||||
player->SetAI(oldAI);
|
||||
PlayerAI* thisAI = player->AI();
|
||||
player->SetAI(static_cast<UnitAI*>(oldAI));
|
||||
delete thisAI;
|
||||
|
||||
// Dismiss ghoul if necessary
|
||||
@@ -1943,7 +1943,7 @@ public:
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_dk_raise_ally_AuraScript::OnRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
|
||||
UnitAI* oldAI;
|
||||
PlayerAI* oldAI;
|
||||
bool oldAIState;
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user