*Implement Aura Type 247 (SPELL_AURA_CLONE_CASTER) and 279 (SPELL_AURA_INITIALIZE_IMAGES)
*Handle CMSG_GET_MIRRORIMAGE_DATA opcode. *Save Minions follow angle to allow themmoving in a formation *Improvements in SpellAI: correctly evade and select attack target for creatures without threat list *Use SpellAI instead of PetAI for not controllable guardians *Only guardians with SUMMON_TYPE_PET are controllable now *Add script and template data for Mirror Image. *Thanks to Drahy for help. --HG-- branch : trunk
This commit is contained in:
@@ -1092,6 +1092,7 @@ UPDATE `creature_template` SET `ScriptName`='mob_spawn_of_marli' WHERE `entry`=1
|
|||||||
UPDATE `creature_template` SET `ScriptName`='mob_batrider' WHERE `entry`=14965;
|
UPDATE `creature_template` SET `ScriptName`='mob_batrider' WHERE `entry`=14965;
|
||||||
UPDATE `creature_template` SET `ScriptName`='mob_shade_of_jindo' WHERE `entry`=14986;
|
UPDATE `creature_template` SET `ScriptName`='mob_shade_of_jindo' WHERE `entry`=14986;
|
||||||
UPDATE `creature_template` SET `ScriptName`='mob_ohgan' WHERE `entry`=14988;
|
UPDATE `creature_template` SET `ScriptName`='mob_ohgan' WHERE `entry`=14988;
|
||||||
|
UPDATE `creature_template` SET `ScriptName`='npc_mirror_image' WHERE `entry`=31216;
|
||||||
|
|
||||||
UPDATE `creature_template` SET `ScriptName`='EventAI', `modelid_A` = 16925,`modelid_H` = 16925, `minmana` = 1000000,`maxmana` = 1000000, `unit_flags` = 33554434 WHERE `entry` IN(29998, 33753, 33752, 33751, 33750);
|
UPDATE `creature_template` SET `ScriptName`='EventAI', `modelid_A` = 16925,`modelid_H` = 16925, `minmana` = 1000000,`maxmana` = 1000000, `unit_flags` = 33554434 WHERE `entry` IN(29998, 33753, 33752, 33751, 33750);
|
||||||
DELETE FROM `creature_ai_scripts` WHERE `creature_id` IN (29998, 33753, 33752, 33751, 33750);
|
DELETE FROM `creature_ai_scripts` WHERE `creature_id` IN (29998, 33753, 33752, 33751, 33750);
|
||||||
|
|||||||
@@ -140,7 +140,9 @@ INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comm
|
|||||||
-- --------
|
-- --------
|
||||||
-- TARGET
|
-- TARGET
|
||||||
-- --------
|
-- --------
|
||||||
|
-- Mirror Image
|
||||||
|
DELETE FROM `spell_script_target` WHERE `entry` IN (58836);
|
||||||
|
INSERT INTO `spell_script_target` VALUES (58836, 1, 31216);
|
||||||
-- zulaman
|
-- zulaman
|
||||||
DELETE FROM `spell_script_target` WHERE `entry` IN
|
DELETE FROM `spell_script_target` WHERE `entry` IN
|
||||||
(42577,42471,43734,42631);
|
(42577,42471,43734,42631);
|
||||||
|
|||||||
@@ -179,6 +179,8 @@ spell6 = VALUES(spell6),
|
|||||||
spell7 = VALUES(spell7),
|
spell7 = VALUES(spell7),
|
||||||
spell8 = VALUES(spell8);
|
spell8 = VALUES(spell8);
|
||||||
|
|
||||||
|
UPDATE `creature_template` SET `spell1`=59638, `spell2` = 59637 WHERE `entry`=31216; # Mirror Image
|
||||||
|
|
||||||
# Spore
|
# Spore
|
||||||
UPDATE `creature_template` SET `minlevel`='80',`maxlevel`='80',`faction_A`='21',`faction_H`='21' WHERE entry IN (16286,30068);
|
UPDATE `creature_template` SET `minlevel`='80',`maxlevel`='80',`faction_A`='21',`faction_H`='21' WHERE entry IN (16286,30068);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
DELETE FROM `spell_script_target` WHERE `entry` IN (58836);
|
||||||
|
INSERT INTO `spell_script_target` VALUES (58836, 1, 31216);
|
||||||
|
UPDATE `creature_template` SET `ScriptName`='npc_mirror_image' WHERE `entry`=31216;
|
||||||
|
UPDATE `creature_template` SET `spell1`=59638, `spell2` = 59637 WHERE `entry`=31216;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="windows-1250"?>
|
<?xml version="1.0" encoding="windows-1250"?>
|
||||||
<VisualStudioProject
|
<VisualStudioProject
|
||||||
ProjectType="Visual C++"
|
ProjectType="Visual C++"
|
||||||
Version="9.00"
|
Version="9,00"
|
||||||
Name="TrinityScript"
|
Name="TrinityScript"
|
||||||
ProjectGUID="{4295C8A9-79B7-4354-8064-F05FB9CA0C96}"
|
ProjectGUID="{4295C8A9-79B7-4354-8064-F05FB9CA0C96}"
|
||||||
RootNamespace="ScriptDev2"
|
RootNamespace="ScriptDev2"
|
||||||
@@ -556,11 +556,11 @@
|
|||||||
Name="Blackfathom Depths"
|
Name="Blackfathom Depths"
|
||||||
>
|
>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\scripts\zone\blackfathom_depths\instance_blackfathom_deeps.cpp"
|
RelativePath="..\scripts\zone\blackfathom_depths\def_blackfathom_deeps.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\scripts\zone\blackfathom_depths\def_blackfathom_deeps.h"
|
RelativePath="..\scripts\zone\blackfathom_depths\instance_blackfathom_deeps.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
@@ -725,9 +725,11 @@
|
|||||||
>
|
>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Desolace">
|
Name="Desolace"
|
||||||
|
>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\scripts\zone\desolace\desolace.cpp">
|
RelativePath="..\scripts\zone\desolace\desolace.cpp"
|
||||||
|
>
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
@@ -838,7 +840,7 @@
|
|||||||
Name="Razorfen Kraul"
|
Name="Razorfen Kraul"
|
||||||
>
|
>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\scripts\zone\razorfen_kraul\razorfen_kraul.cpp"
|
RelativePath="..\scripts\zone\razorfen_kraul\def_razorfen_kraul.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
@@ -846,7 +848,7 @@
|
|||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\scripts\zone\razorfen_kraul\def_razorfen_kraul.h"
|
RelativePath="..\scripts\zone\razorfen_kraul\razorfen_kraul.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
|||||||
@@ -1636,6 +1636,32 @@ CreatureAI* GetAI_mob_mojo(Creature *_Creature)
|
|||||||
return new mob_mojoAI (_Creature);
|
return new mob_mojoAI (_Creature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct TRINITY_DLL_DECL npc_mirror_image : public SpellAI
|
||||||
|
{
|
||||||
|
npc_mirror_image(Creature *c) : SpellAI(c) {}
|
||||||
|
Unit * owner;
|
||||||
|
void Reset()
|
||||||
|
{
|
||||||
|
if (m_creature->isSummon())
|
||||||
|
owner = ((TempSummon*)me)->GetOwner();
|
||||||
|
if (!owner)
|
||||||
|
return;
|
||||||
|
me->SetDisplayId(owner->GetDisplayId());
|
||||||
|
owner->SetLevel(owner->getLevel());
|
||||||
|
// Inherit Master's Threat List (not yet implemented)
|
||||||
|
owner->CastSpell((Unit*)NULL, 58838, true);
|
||||||
|
// here mirror image casts on summoner spell (not present in client dbc) 49866
|
||||||
|
// here should be auras (not present in client dbc): 35657, 35658, 35659, 35660 selfcasted by mirror images (stats related?)
|
||||||
|
// Clone Me!
|
||||||
|
owner->CastSpell(me, 45204, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CreatureAI* GetAI_npc_mirror_image(Creature *_Creature)
|
||||||
|
{
|
||||||
|
return new npc_mirror_image (_Creature);
|
||||||
|
}
|
||||||
|
|
||||||
void AddSC_npcs_special()
|
void AddSC_npcs_special()
|
||||||
{
|
{
|
||||||
Script *newscript;
|
Script *newscript;
|
||||||
@@ -1727,6 +1753,11 @@ void AddSC_npcs_special()
|
|||||||
newscript->GetAI = &GetAI_npc_snake_trap_serpents;
|
newscript->GetAI = &GetAI_npc_snake_trap_serpents;
|
||||||
newscript->RegisterSelf();
|
newscript->RegisterSelf();
|
||||||
|
|
||||||
|
newscript = new Script;
|
||||||
|
newscript->Name="npc_mirror_image";
|
||||||
|
newscript->GetAI = &GetAI_npc_mirror_image;
|
||||||
|
newscript->RegisterSelf();
|
||||||
|
|
||||||
newscript = new Script;
|
newscript = new Script;
|
||||||
newscript->Name="mob_mojo";
|
newscript->Name="mob_mojo";
|
||||||
newscript->GetAI = &GetAI_mob_mojo;
|
newscript->GetAI = &GetAI_mob_mojo;
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ struct TRINITY_DLL_DECL npc_threshwackonatorAI : public ScriptedAI
|
|||||||
if(me->isAlive())
|
if(me->isAlive())
|
||||||
{
|
{
|
||||||
if(Player* pPlayer = Unit::GetPlayer(PlayerGUID))
|
if(Player* pPlayer = Unit::GetPlayer(PlayerGUID))
|
||||||
me->GetMotionMaster()->MoveFollow(pPlayer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
|
me->GetMotionMaster()->MoveFollow(pPlayer, PET_FOLLOW_DIST, m_creature->GetFollowAngle());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
me->GetMotionMaster()->MovementExpired();
|
me->GetMotionMaster()->MovementExpired();
|
||||||
@@ -246,7 +246,7 @@ struct TRINITY_DLL_DECL npc_threshwackonatorAI : public ScriptedAI
|
|||||||
me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
|
me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
|
||||||
|
|
||||||
if(Player* pPlayer = Unit::GetPlayer(PlayerGUID))
|
if(Player* pPlayer = Unit::GetPlayer(PlayerGUID))
|
||||||
me->GetMotionMaster()->MoveFollow(pPlayer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
|
me->GetMotionMaster()->MoveFollow(pPlayer, PET_FOLLOW_DIST, m_creature->GetFollowAngle());
|
||||||
|
|
||||||
DoScriptText(EMOTE_START, me);
|
DoScriptText(EMOTE_START, me);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ bool EffectDummyCreature_npc_aged_dying_ancient_kodo(Unit *pCaster, uint32 spell
|
|||||||
if (pCreatureTarget->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
|
if (pCreatureTarget->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
|
||||||
pCreatureTarget->GetMotionMaster()->MoveIdle();
|
pCreatureTarget->GetMotionMaster()->MoveIdle();
|
||||||
|
|
||||||
pCreatureTarget->GetMotionMaster()->MoveFollow(pCaster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
|
pCreatureTarget->GetMotionMaster()->MoveFollow(pCaster, PET_FOLLOW_DIST, pCreatureTarget->GetFollowAngle());
|
||||||
}
|
}
|
||||||
|
|
||||||
//always return true when we are handling this spell and effect
|
//always return true when we are handling this spell and effect
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ struct TRINITY_DLL_DECL npc_mistAI : public ScriptedAI
|
|||||||
if (m_creature->isAlive())
|
if (m_creature->isAlive())
|
||||||
{
|
{
|
||||||
if (Player* pPlayer = Unit::GetPlayer(uiPlayerGUID))
|
if (Player* pPlayer = Unit::GetPlayer(uiPlayerGUID))
|
||||||
m_creature->GetMotionMaster()->MoveFollow(pPlayer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
|
m_creature->GetMotionMaster()->MoveFollow(pPlayer, PET_FOLLOW_DIST, m_creature->GetFollowAngle());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_creature->GetMotionMaster()->MovementExpired();
|
m_creature->GetMotionMaster()->MovementExpired();
|
||||||
@@ -100,7 +100,7 @@ struct TRINITY_DLL_DECL npc_mistAI : public ScriptedAI
|
|||||||
m_creature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
|
m_creature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
|
||||||
|
|
||||||
if (Player* pPlayer = Unit::GetPlayer(uiPlayer))
|
if (Player* pPlayer = Unit::GetPlayer(uiPlayer))
|
||||||
m_creature->GetMotionMaster()->MoveFollow(pPlayer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
|
m_creature->GetMotionMaster()->MoveFollow(pPlayer, PET_FOLLOW_DIST, m_creature->GetFollowAngle());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoComplete()
|
void DoComplete()
|
||||||
|
|||||||
@@ -2577,3 +2577,4 @@ time_t Creature::GetLinkedCreatureRespawnTime() const
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -163,6 +163,7 @@ enum SummonMask
|
|||||||
SUMMON_MASK_VEHICLE = 0x00000020,
|
SUMMON_MASK_VEHICLE = 0x00000020,
|
||||||
SUMMON_MASK_PUPPET = 0x00000040,
|
SUMMON_MASK_PUPPET = 0x00000040,
|
||||||
SUMMON_MASK_HUNTER_PET = 0x00000080,
|
SUMMON_MASK_HUNTER_PET = 0x00000080,
|
||||||
|
SUMMON_MASK_CONTROLABLE_GUARDIAN = 0x00000100,
|
||||||
};
|
};
|
||||||
|
|
||||||
// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform
|
// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform
|
||||||
|
|||||||
@@ -148,7 +148,6 @@ bool CreatureAI::UpdateVictim()
|
|||||||
{
|
{
|
||||||
if(!me->isInCombat())
|
if(!me->isInCombat())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(Unit *victim = me->SelectVictim())
|
if(Unit *victim = me->SelectVictim())
|
||||||
AttackStart(victim);
|
AttackStart(victim);
|
||||||
return me->getVictim();
|
return me->getVictim();
|
||||||
@@ -195,7 +194,10 @@ void CreatureAI::EnterEvadeMode()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if(Unit *owner = me->GetCharmerOrOwner())
|
if(Unit *owner = me->GetCharmerOrOwner())
|
||||||
me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE, MOTION_SLOT_ACTIVE);
|
{
|
||||||
|
me->GetMotionMaster()->Clear(false);
|
||||||
|
me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, m_creature->GetFollowAngle(), MOTION_SLOT_ACTIVE);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
me->GetMotionMaster()->MoveTargetedHome();
|
me->GetMotionMaster()->MoveTargetedHome();
|
||||||
|
|
||||||
|
|||||||
@@ -54,13 +54,13 @@ namespace FactorySelector
|
|||||||
// select by NPC flags
|
// select by NPC flags
|
||||||
if(!ai_factory)
|
if(!ai_factory)
|
||||||
{
|
{
|
||||||
if(creature->isGuardian() && ((Guardian*)creature)->GetOwner()->GetTypeId() == TYPEID_PLAYER)
|
if(creature->HasSummonMask(SUMMON_MASK_CONTROLABLE_GUARDIAN) && ((Guardian*)creature)->GetOwner()->GetTypeId() == TYPEID_PLAYER)
|
||||||
ai_factory = ai_registry.GetRegistryItem("PetAI");
|
ai_factory = ai_registry.GetRegistryItem("PetAI");
|
||||||
else if(creature->isVehicle() || creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK))
|
else if(creature->isVehicle() || creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK))
|
||||||
ai_factory = ai_registry.GetRegistryItem("NullCreatureAI");
|
ai_factory = ai_registry.GetRegistryItem("NullCreatureAI");
|
||||||
else if(creature->isGuard())
|
else if(creature->isGuard())
|
||||||
ai_factory = ai_registry.GetRegistryItem("GuardAI");
|
ai_factory = ai_registry.GetRegistryItem("GuardAI");
|
||||||
else if(creature->isGuardian())
|
else if(creature->HasSummonMask(SUMMON_MASK_CONTROLABLE_GUARDIAN))
|
||||||
ai_factory = ai_registry.GetRegistryItem("PetAI");
|
ai_factory = ai_registry.GetRegistryItem("PetAI");
|
||||||
else if(creature->isTotem())
|
else if(creature->isTotem())
|
||||||
ai_factory = ai_registry.GetRegistryItem("TotemAI");
|
ai_factory = ai_registry.GetRegistryItem("TotemAI");
|
||||||
|
|||||||
+1
-1
@@ -1661,7 +1661,7 @@ bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Follow player - Using pet's default dist and angle
|
// Follow player - Using pet's default dist and angle
|
||||||
creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
|
creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, creature->GetFollowAngle());
|
||||||
|
|
||||||
PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName());
|
PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName());
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1718,6 +1718,8 @@ TempSummon *Map::SummonCreature(uint32 entry, float x, float y, float z, float a
|
|||||||
mask = SUMMON_MASK_PUPPET;
|
mask = SUMMON_MASK_PUPPET;
|
||||||
else if(properties->Type == SUMMON_TYPE_MINIPET)
|
else if(properties->Type == SUMMON_TYPE_MINIPET)
|
||||||
mask = SUMMON_MASK_MINION;
|
mask = SUMMON_MASK_MINION;
|
||||||
|
else if (properties->Flags & 512) // Mirror Image, Summon Gargoyle
|
||||||
|
mask = SUMMON_MASK_GUARDIAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 phase = PHASEMASK_NORMAL, team = 0;
|
uint32 phase = PHASEMASK_NORMAL, team = 0;
|
||||||
|
|||||||
@@ -1053,7 +1053,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
|
|||||||
/*0x3FE*/ { "MSG_GUILD_BANK_MONEY_WITHDRAWN", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankMoneyWithdrawn },
|
/*0x3FE*/ { "MSG_GUILD_BANK_MONEY_WITHDRAWN", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankMoneyWithdrawn },
|
||||||
/*0x3FF*/ { "MSG_GUILD_EVENT_LOG_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGuildEventLogQueryOpcode },
|
/*0x3FF*/ { "MSG_GUILD_EVENT_LOG_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGuildEventLogQueryOpcode },
|
||||||
/*0x400*/ { "CMSG_MAELSTROM_RENAME_GUILD", STATUS_NEVER, &WorldSession::Handle_NULL },
|
/*0x400*/ { "CMSG_MAELSTROM_RENAME_GUILD", STATUS_NEVER, &WorldSession::Handle_NULL },
|
||||||
/*0x401*/ { "CMSG_GET_MIRRORIMAGE_DATA", STATUS_NEVER, &WorldSession::Handle_NULL },
|
/*0x401*/ { "CMSG_GET_MIRRORIMAGE_DATA", STATUS_LOGGEDIN, &WorldSession::HandleMirrrorImageDataRequest },
|
||||||
/*0x402*/ { "SMSG_MIRRORIMAGE_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide },
|
/*0x402*/ { "SMSG_MIRRORIMAGE_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide },
|
||||||
/*0x403*/ { "SMSG_FORCE_DISPLAY_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
|
/*0x403*/ { "SMSG_FORCE_DISPLAY_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
|
||||||
/*0x404*/ { "SMSG_SPELL_CHANCE_RESIST_PUSHBACK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
|
/*0x404*/ { "SMSG_SPELL_CHANCE_RESIST_PUSHBACK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
|
||||||
|
|||||||
+1
-1
@@ -166,7 +166,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
float px, py, pz;
|
float px, py, pz;
|
||||||
owner->GetClosePoint(px, py, pz, GetObjectSize(), PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
|
owner->GetClosePoint(px, py, pz, GetObjectSize(), PET_FOLLOW_DIST, GetFollowAngle());
|
||||||
Relocate(px, py, pz, owner->GetOrientation());
|
Relocate(px, py, pz, owner->GetOrientation());
|
||||||
|
|
||||||
if (!IsPositionValid())
|
if (!IsPositionValid())
|
||||||
|
|||||||
+4
-2
@@ -74,7 +74,7 @@ void PetAI::_stopAttack()
|
|||||||
|
|
||||||
if(owner && m_creature->GetCharmInfo() && m_creature->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
|
if(owner && m_creature->GetCharmInfo() && m_creature->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
|
||||||
{
|
{
|
||||||
m_creature->GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE);
|
m_creature->GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST, m_creature->GetFollowAngle());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -112,8 +112,10 @@ void PetAI::UpdateAI(const uint32 diff)
|
|||||||
if(owner->isInCombat() && !(m_creature->HasReactState(REACT_PASSIVE) || m_creature->GetCharmInfo()->HasCommandState(COMMAND_STAY)))
|
if(owner->isInCombat() && !(m_creature->HasReactState(REACT_PASSIVE) || m_creature->GetCharmInfo()->HasCommandState(COMMAND_STAY)))
|
||||||
AttackStart(owner->getAttackerForHelper());
|
AttackStart(owner->getAttackerForHelper());
|
||||||
else if(m_creature->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW) && !m_creature->hasUnitState(UNIT_STAT_FOLLOW))
|
else if(m_creature->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW) && !m_creature->hasUnitState(UNIT_STAT_FOLLOW))
|
||||||
m_creature->GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE);
|
m_creature->GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST, m_creature->GetFollowAngle());
|
||||||
}
|
}
|
||||||
|
else if (owner && !m_creature->hasUnitState(UNIT_STAT_FOLLOW)) // no charm info and no victim
|
||||||
|
m_creature->GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST, m_creature->GetFollowAngle());
|
||||||
|
|
||||||
if(!me->GetCharmInfo())
|
if(!me->GetCharmInfo())
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ void WorldSession::HandlePetActionHelper(Unit *pet, uint64 guid1, uint16 spellid
|
|||||||
case COMMAND_FOLLOW: //spellid=1792 //FOLLOW
|
case COMMAND_FOLLOW: //spellid=1792 //FOLLOW
|
||||||
pet->AttackStop();
|
pet->AttackStop();
|
||||||
pet->InterruptNonMeleeSpells(false);
|
pet->InterruptNonMeleeSpells(false);
|
||||||
pet->GetMotionMaster()->MoveFollow(_player,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE);
|
pet->GetMotionMaster()->MoveFollow(_player,PET_FOLLOW_DIST,pet->GetFollowAngle());
|
||||||
charmInfo->SetCommandState( COMMAND_FOLLOW );
|
charmInfo->SetCommandState( COMMAND_FOLLOW );
|
||||||
break;
|
break;
|
||||||
case COMMAND_ATTACK: //spellid=1792 //ATTACK
|
case COMMAND_ATTACK: //spellid=1792 //ATTACK
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ enum AuraType
|
|||||||
SPELL_AURA_COMPREHEND_LANGUAGE = 244,
|
SPELL_AURA_COMPREHEND_LANGUAGE = 244,
|
||||||
SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL = 245,
|
SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL = 245,
|
||||||
SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK = 246,
|
SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK = 246,
|
||||||
SPELL_AURA_247 = 247,
|
SPELL_AURA_CLONE_CASTER = 247,
|
||||||
SPELL_AURA_MOD_COMBAT_RESULT_CHANCE = 248,
|
SPELL_AURA_MOD_COMBAT_RESULT_CHANCE = 248,
|
||||||
SPELL_AURA_CONVERT_RUNE = 249,
|
SPELL_AURA_CONVERT_RUNE = 249,
|
||||||
SPELL_AURA_MOD_INCREASE_HEALTH_2 = 250,
|
SPELL_AURA_MOD_INCREASE_HEALTH_2 = 250,
|
||||||
@@ -324,7 +324,7 @@ enum AuraType
|
|||||||
SPELL_AURA_276 = 276, // Only "Test Mod Damage % Mechanic" spell, possible mod damage done
|
SPELL_AURA_276 = 276, // Only "Test Mod Damage % Mechanic" spell, possible mod damage done
|
||||||
SPELL_AURA_MOD_MAX_AFFECTED_TARGETS = 277,
|
SPELL_AURA_MOD_MAX_AFFECTED_TARGETS = 277,
|
||||||
SPELL_AURA_MOD_DISARM_RANGED = 278,
|
SPELL_AURA_MOD_DISARM_RANGED = 278,
|
||||||
SPELL_AURA_279 = 279,
|
SPELL_AURA_INITIALIZE_IMAGES = 279,
|
||||||
SPELL_AURA_MOD_ARMOR_PENETRATION_PCT = 280,
|
SPELL_AURA_MOD_ARMOR_PENETRATION_PCT = 280,
|
||||||
SPELL_AURA_MOD_HONOR_GAIN_PCT = 281,
|
SPELL_AURA_MOD_HONOR_GAIN_PCT = 281,
|
||||||
SPELL_AURA_MOD_BASE_HEALTH_PCT = 282,
|
SPELL_AURA_MOD_BASE_HEALTH_PCT = 282,
|
||||||
|
|||||||
+37
-4
@@ -300,7 +300,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
|
|||||||
&Aura::HandleComprehendLanguage, //244 SPELL_AURA_COMPREHEND_LANGUAGE
|
&Aura::HandleComprehendLanguage, //244 SPELL_AURA_COMPREHEND_LANGUAGE
|
||||||
&Aura::HandleNoImmediateEffect, //245 SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL
|
&Aura::HandleNoImmediateEffect, //245 SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL
|
||||||
&Aura::HandleNoImmediateEffect, //246 SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK implemented in Spell::EffectApplyAura
|
&Aura::HandleNoImmediateEffect, //246 SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK implemented in Spell::EffectApplyAura
|
||||||
&Aura::HandleNULL, //247 target to become a clone of the caster
|
&Aura::HandleAuraCloneCaster, //247 SPELL_AURA_CLONE_CASTER
|
||||||
&Aura::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
|
&Aura::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
|
||||||
&Aura::HandleAuraConvertRune, //249 SPELL_AURA_CONVERT_RUNE
|
&Aura::HandleAuraConvertRune, //249 SPELL_AURA_CONVERT_RUNE
|
||||||
&Aura::HandleAuraModIncreaseHealth, //250 SPELL_AURA_MOD_INCREASE_HEALTH_2
|
&Aura::HandleAuraModIncreaseHealth, //250 SPELL_AURA_MOD_INCREASE_HEALTH_2
|
||||||
@@ -332,7 +332,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
|
|||||||
&Aura::HandleNULL, //276 mod damage % mechanic?
|
&Aura::HandleNULL, //276 mod damage % mechanic?
|
||||||
&Aura::HandleNoImmediateEffect, //277 SPELL_AURA_MOD_ABILITY_AFFECTED_TARGETS implemented in spell::settargetmap
|
&Aura::HandleNoImmediateEffect, //277 SPELL_AURA_MOD_ABILITY_AFFECTED_TARGETS implemented in spell::settargetmap
|
||||||
&Aura::HandleAuraModDisarm, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon
|
&Aura::HandleAuraModDisarm, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon
|
||||||
&Aura::HandleNULL, //279 visual effects? 58836 and 57507 - makes summon to have name of caster
|
&Aura::HandleAuraInitializeImages, //279 SPELL_AURA_INITIALIZE_IMAGES
|
||||||
&Aura::HandleModArmorPenetrationPct, //280 SPELL_AURA_MOD_ARMOR_PENETRATION_PCT
|
&Aura::HandleModArmorPenetrationPct, //280 SPELL_AURA_MOD_ARMOR_PENETRATION_PCT
|
||||||
&Aura::HandleNoImmediateEffect, //281 SPELL_AURA_MOD_HONOR_GAIN_PCT implemented in Player::RewardHonor
|
&Aura::HandleNoImmediateEffect, //281 SPELL_AURA_MOD_HONOR_GAIN_PCT implemented in Player::RewardHonor
|
||||||
&Aura::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT
|
&Aura::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT
|
||||||
@@ -6966,7 +6966,7 @@ void AuraEffect::PeriodicDummyTick()
|
|||||||
if (spell->Id == 55342)
|
if (spell->Id == 55342)
|
||||||
{
|
{
|
||||||
// Set name of summons to name of caster
|
// Set name of summons to name of caster
|
||||||
m_target->CastSpell(m_target, m_spellProto->EffectTriggerSpell[m_effIndex], true);
|
m_target->CastSpell((Unit *)NULL, m_spellProto->EffectTriggerSpell[m_effIndex], true);
|
||||||
m_isPeriodic = false;
|
m_isPeriodic = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -7357,7 +7357,7 @@ void AuraEffect::HandleModPossessPet(bool apply, bool Real, bool /*changeAmount*
|
|||||||
((Player*)caster)->PetSpellInitialize();
|
((Player*)caster)->PetSpellInitialize();
|
||||||
if(!m_target->getVictim())
|
if(!m_target->getVictim())
|
||||||
{
|
{
|
||||||
m_target->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
|
m_target->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, m_target->GetFollowAngle());
|
||||||
m_target->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW);
|
m_target->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7489,7 +7489,40 @@ void AuraEffect::HandleReflectSpells( bool Apply, bool Real , bool /*changeAmoun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void AuraEffect::HandleAuraInitializeImages( bool Apply, bool Real , bool /*changeAmount*/)
|
||||||
|
{
|
||||||
|
if (!Real || !Apply)
|
||||||
|
return;
|
||||||
|
Unit * caster = GetCaster();
|
||||||
|
if (!caster)
|
||||||
|
return;
|
||||||
|
// Set item visual
|
||||||
|
if (caster->GetTypeId()== TYPEID_PLAYER)
|
||||||
|
{
|
||||||
|
if (Item const * item = ((Player *)caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND))
|
||||||
|
m_target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, item->GetProto()->ItemId);
|
||||||
|
if (Item const * item = ((Player *)caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND))
|
||||||
|
m_target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, item->GetProto()->ItemId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, caster->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID));
|
||||||
|
m_target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, caster->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1));
|
||||||
|
m_target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, caster->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AuraEffect::HandleAuraCloneCaster( bool Apply, bool Real , bool /*changeAmount*/)
|
||||||
|
{
|
||||||
|
if (!Real || !Apply)
|
||||||
|
return;
|
||||||
|
Unit * caster = GetCaster();
|
||||||
|
if (!caster)
|
||||||
|
return;
|
||||||
|
// Set item visual
|
||||||
|
m_target->SetDisplayId(caster->GetDisplayId());
|
||||||
|
m_target->SetUInt32Value(UNIT_FIELD_FLAGS_2, 2064);
|
||||||
|
}
|
||||||
int32 AuraEffect::CalculateCrowdControlAuraAmount(Unit * caster)
|
int32 AuraEffect::CalculateCrowdControlAuraAmount(Unit * caster)
|
||||||
{
|
{
|
||||||
// Damage cap for CC effects
|
// Damage cap for CC effects
|
||||||
|
|||||||
@@ -335,6 +335,8 @@ class TRINITY_DLL_SPEC AuraEffect
|
|||||||
void HandleCharmConvert(bool apply, bool Real, bool changeAmount);
|
void HandleCharmConvert(bool apply, bool Real, bool changeAmount);
|
||||||
void HandleReflectSpells( bool Apply, bool Real , bool changeAmount);
|
void HandleReflectSpells( bool Apply, bool Real , bool changeAmount);
|
||||||
void HandleModArmorPenetrationPct(bool Apply, bool Real, bool changeAmount);
|
void HandleModArmorPenetrationPct(bool Apply, bool Real, bool changeAmount);
|
||||||
|
void HandleAuraInitializeImages(bool Apply, bool Real, bool changeAmount);
|
||||||
|
void HandleAuraCloneCaster(bool Apply, bool Real, bool changeAmount);
|
||||||
|
|
||||||
int32 CalculateCrowdControlAuraAmount(Unit * caster);
|
int32 CalculateCrowdControlAuraAmount(Unit * caster);
|
||||||
|
|
||||||
|
|||||||
@@ -3280,6 +3280,9 @@ void Spell::EffectSummonType(uint32 i)
|
|||||||
switch(properties->Category)
|
switch(properties->Category)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
|
if (properties->Flags & 512)
|
||||||
|
SummonGuardian(entry, properties);
|
||||||
|
break;
|
||||||
switch(properties->Type)
|
switch(properties->Type)
|
||||||
{
|
{
|
||||||
case SUMMON_TYPE_PET:
|
case SUMMON_TYPE_PET:
|
||||||
@@ -3363,7 +3366,7 @@ void Spell::EffectSummonType(uint32 i)
|
|||||||
TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
|
TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
|
||||||
|
|
||||||
TempSummon * summon = m_originalCaster->SummonCreature(entry,px,py,pz,m_caster->GetOrientation(),summonType,duration);
|
TempSummon * summon = m_originalCaster->SummonCreature(entry,px,py,pz,m_caster->GetOrientation(),summonType,duration);
|
||||||
summon->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_originalCaster->GetGUID());
|
summon->SetUInt64Value(UNIT_FIELD_SUMONEDBY, m_originalCaster->GetGUID());
|
||||||
if (properties->Category == SUMMON_CATEGORY_ALLY)
|
if (properties->Category == SUMMON_CATEGORY_ALLY)
|
||||||
summon->setFaction(m_originalCaster->getFaction());
|
summon->setFaction(m_originalCaster->getFaction());
|
||||||
}
|
}
|
||||||
@@ -4556,6 +4559,15 @@ void Spell::EffectScriptEffect(uint32 effIndex)
|
|||||||
{
|
{
|
||||||
switch(m_spellInfo->Id)
|
switch(m_spellInfo->Id)
|
||||||
{
|
{
|
||||||
|
case 45204: // Clone Me!
|
||||||
|
case 41055: // Copy Weapon
|
||||||
|
case 45206: // Copy Off-hand Weapon
|
||||||
|
unitTarget->CastSpell(m_caster, damage, false);
|
||||||
|
break;
|
||||||
|
case 45205: // Copy Offhand Weapon
|
||||||
|
case 41054: // Copy Weapon
|
||||||
|
m_caster->CastSpell(unitTarget, damage, false);
|
||||||
|
break;
|
||||||
// Despawn Horse
|
// Despawn Horse
|
||||||
case 52267:
|
case 52267:
|
||||||
{
|
{
|
||||||
@@ -6695,6 +6707,8 @@ void Spell::SummonGuardian(uint32 entry, SummonPropertiesEntry const *properties
|
|||||||
((Guardian*)summon)->InitStatsForLevel(level);
|
((Guardian*)summon)->InitStatsForLevel(level);
|
||||||
|
|
||||||
summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
|
summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
|
||||||
|
if(summon->HasSummonMask(SUMMON_MASK_MINION) && m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
|
||||||
|
((Minion*)summon)->SetFollowAngle(m_caster->GetAngle(summon));
|
||||||
|
|
||||||
summon->AI()->EnterEvadeMode();
|
summon->AI()->EnterEvadeMode();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -537,3 +537,79 @@ void WorldSession::HandleSpellClick( WorldPacket & recv_data )
|
|||||||
if(unit->isVehicle())
|
if(unit->isVehicle())
|
||||||
_player->EnterVehicle((Vehicle*)unit);
|
_player->EnterVehicle((Vehicle*)unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorldSession::HandleMirrrorImageDataRequest( WorldPacket & recv_data )
|
||||||
|
{
|
||||||
|
sLog.outDebug("WORLD: CMSG_GET_MIRRORIMAGE_DATA");
|
||||||
|
CHECK_PACKET_SIZE(recv_data, 8);
|
||||||
|
uint64 guid;
|
||||||
|
recv_data >> guid;
|
||||||
|
|
||||||
|
// Get unit for which data is needed by client
|
||||||
|
Unit *unit = ObjectAccessor::GetObjectInWorld(guid, (Unit*)NULL);
|
||||||
|
if(!unit)
|
||||||
|
return;
|
||||||
|
// Get creator of the unit
|
||||||
|
Unit *creator = ObjectAccessor::GetObjectInWorld(unit->GetCreatorGUID(),(Unit*)NULL);
|
||||||
|
if (!creator)
|
||||||
|
return;
|
||||||
|
WorldPacket data(SMSG_MIRRORIMAGE_DATA, 68);
|
||||||
|
data << (uint64)guid;
|
||||||
|
data << (uint32)creator->GetDisplayId();
|
||||||
|
if (creator->GetTypeId()==TYPEID_PLAYER)
|
||||||
|
{
|
||||||
|
Player * pCreator = (Player *)creator;
|
||||||
|
data << (uint8)pCreator->getRace();
|
||||||
|
data << (uint8)pCreator->getGender();
|
||||||
|
data << (uint8)pCreator->getClass();
|
||||||
|
data << (uint8)pCreator->GetByteValue(PLAYER_BYTES, 0); // skin
|
||||||
|
|
||||||
|
data << (uint8)pCreator->GetByteValue(PLAYER_BYTES, 1); // face
|
||||||
|
data << (uint8)pCreator->GetByteValue(PLAYER_BYTES, 2); // hair
|
||||||
|
data << (uint8)pCreator->GetByteValue(PLAYER_BYTES, 3); // haircolor
|
||||||
|
data << (uint8)pCreator->GetByteValue(PLAYER_BYTES_2, 0); // facialhair
|
||||||
|
|
||||||
|
data << (uint32)0; // unk
|
||||||
|
static const EquipmentSlots ItemSlots[] =
|
||||||
|
{
|
||||||
|
EQUIPMENT_SLOT_HEAD,
|
||||||
|
EQUIPMENT_SLOT_SHOULDERS,
|
||||||
|
EQUIPMENT_SLOT_BODY,
|
||||||
|
EQUIPMENT_SLOT_CHEST,
|
||||||
|
EQUIPMENT_SLOT_WAIST,
|
||||||
|
EQUIPMENT_SLOT_LEGS,
|
||||||
|
EQUIPMENT_SLOT_FEET,
|
||||||
|
EQUIPMENT_SLOT_WRISTS,
|
||||||
|
EQUIPMENT_SLOT_HANDS,
|
||||||
|
EQUIPMENT_SLOT_BACK,
|
||||||
|
EQUIPMENT_SLOT_TABARD,
|
||||||
|
EQUIPMENT_SLOT_END
|
||||||
|
};
|
||||||
|
// Display items in visible slots
|
||||||
|
for (EquipmentSlots const* itr = &ItemSlots[0];*itr!=EQUIPMENT_SLOT_END;++itr)
|
||||||
|
if (Item const *item = pCreator->GetItemByPos(INVENTORY_SLOT_BAG_0, *itr))
|
||||||
|
data << (uint32)item->GetProto()->DisplayInfoID;
|
||||||
|
else
|
||||||
|
data << (uint32)0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Skip player data for creatures
|
||||||
|
data << (uint32)0;
|
||||||
|
data << (uint32)0;
|
||||||
|
data << (uint32)0;
|
||||||
|
data << (uint32)0;
|
||||||
|
data << (uint32)0;
|
||||||
|
data << (uint32)0;
|
||||||
|
data << (uint32)0;
|
||||||
|
data << (uint32)0;
|
||||||
|
data << (uint32)0;
|
||||||
|
data << (uint32)0;
|
||||||
|
data << (uint32)0;
|
||||||
|
data << (uint32)0;
|
||||||
|
data << (uint32)0;
|
||||||
|
data << (uint32)0;
|
||||||
|
}
|
||||||
|
SendPacket( &data );
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -265,6 +265,7 @@ Minion::Minion(SummonPropertiesEntry const *properties, Unit *owner) : TempSummo
|
|||||||
{
|
{
|
||||||
assert(m_owner);
|
assert(m_owner);
|
||||||
m_summonMask |= SUMMON_MASK_MINION;
|
m_summonMask |= SUMMON_MASK_MINION;
|
||||||
|
m_followAngle = PET_FOLLOW_ANGLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Minion::InitStats(uint32 duration)
|
void Minion::InitStats(uint32 duration)
|
||||||
@@ -302,7 +303,11 @@ Guardian::Guardian(SummonPropertiesEntry const *properties, Unit *owner) : Minio
|
|||||||
, m_bonusdamage(0)
|
, m_bonusdamage(0)
|
||||||
{
|
{
|
||||||
m_summonMask |= SUMMON_MASK_GUARDIAN;
|
m_summonMask |= SUMMON_MASK_GUARDIAN;
|
||||||
|
if (properties && properties->Type == SUMMON_TYPE_PET)
|
||||||
|
{
|
||||||
|
m_summonMask |= SUMMON_MASK_CONTROLABLE_GUARDIAN;
|
||||||
InitCharmInfo();
|
InitCharmInfo();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Guardian::InitStats(uint32 duration)
|
void Guardian::InitStats(uint32 duration)
|
||||||
@@ -311,7 +316,7 @@ void Guardian::InitStats(uint32 duration)
|
|||||||
|
|
||||||
InitStatsForLevel(m_owner->getLevel());
|
InitStatsForLevel(m_owner->getLevel());
|
||||||
|
|
||||||
if(m_owner->GetTypeId() == TYPEID_PLAYER)
|
if(m_owner->GetTypeId() == TYPEID_PLAYER && HasSummonMask(SUMMON_MASK_CONTROLABLE_GUARDIAN))
|
||||||
m_charmInfo->InitCharmCreateSpells();
|
m_charmInfo->InitCharmCreateSpells();
|
||||||
|
|
||||||
SetReactState(REACT_AGGRESSIVE);
|
SetReactState(REACT_AGGRESSIVE);
|
||||||
|
|||||||
@@ -54,9 +54,12 @@ class Minion : public TempSummon
|
|||||||
void InitSummon();
|
void InitSummon();
|
||||||
void RemoveFromWorld();
|
void RemoveFromWorld();
|
||||||
Unit *GetOwner() { return m_owner; }
|
Unit *GetOwner() { return m_owner; }
|
||||||
|
float GetFollowAngle() { return m_followAngle; }
|
||||||
|
void SetFollowAngle(float angle) { m_followAngle = angle; }
|
||||||
bool IsPetGhoul() const {return GetEntry() == 26125;} // Ghoul may be guardian or pet
|
bool IsPetGhoul() const {return GetEntry() == 26125;} // Ghoul may be guardian or pet
|
||||||
protected:
|
protected:
|
||||||
Unit * const m_owner;
|
Unit * const m_owner;
|
||||||
|
float m_followAngle;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Guardian : public Minion
|
class Guardian : public Minion
|
||||||
|
|||||||
+48
-9
@@ -218,13 +218,13 @@ void Unit::Update( uint32 p_time )
|
|||||||
if (CanHaveThreatList() && getThreatManager().isNeedUpdateToClient(p_time))
|
if (CanHaveThreatList() && getThreatManager().isNeedUpdateToClient(p_time))
|
||||||
SendThreatListUpdate();
|
SendThreatListUpdate();
|
||||||
|
|
||||||
// update combat timer only for players and pets
|
// update combat timer only for players and pets (only pets with PetAI)
|
||||||
if (isInCombat() && IsControlledByPlayer())
|
if (isInCombat() && (GetTypeId() == TYPEID_PLAYER || (((Creature *)this)->isPet()) && IsControlledByPlayer()))
|
||||||
{
|
{
|
||||||
// Check UNIT_STAT_MELEE_ATTACKING or UNIT_STAT_CHASE (without UNIT_STAT_FOLLOW in this case) so pets can reach far away
|
// Check UNIT_STAT_MELEE_ATTACKING or UNIT_STAT_CHASE (without UNIT_STAT_FOLLOW in this case) so pets can reach far away
|
||||||
// targets without stopping half way there and running off.
|
// targets without stopping half way there and running off.
|
||||||
// These flags are reset after target dies or another command is given.
|
// These flags are reset after target dies or another command is given.
|
||||||
if( m_HostilRefManager.isEmpty() )
|
if( m_HostilRefManager.isEmpty())
|
||||||
{
|
{
|
||||||
// m_CombatTimer set at aura start and it will be freeze until aura removing
|
// m_CombatTimer set at aura start and it will be freeze until aura removing
|
||||||
if ( m_CombatTimer <= p_time )
|
if ( m_CombatTimer <= p_time )
|
||||||
@@ -8359,7 +8359,7 @@ bool Unit::Attack(Unit *victim, bool meleeAttack)
|
|||||||
//if(GetTypeId()==TYPEID_UNIT)
|
//if(GetTypeId()==TYPEID_UNIT)
|
||||||
// ((Creature*)this)->SetCombatStartPosition(GetPositionX(), GetPositionY(), GetPositionZ());
|
// ((Creature*)this)->SetCombatStartPosition(GetPositionX(), GetPositionY(), GetPositionZ());
|
||||||
|
|
||||||
if(GetTypeId()==TYPEID_UNIT && !IsControlledByPlayer())
|
if(GetTypeId()==TYPEID_UNIT)
|
||||||
{
|
{
|
||||||
// should not let player enter combat by right clicking target
|
// should not let player enter combat by right clicking target
|
||||||
SetInCombatWith(victim);
|
SetInCombatWith(victim);
|
||||||
@@ -8704,13 +8704,13 @@ void Unit::SetMinion(Minion *minion, bool apply)
|
|||||||
assert((*itr)->GetOwnerGUID() == GetGUID());
|
assert((*itr)->GetOwnerGUID() == GetGUID());
|
||||||
assert((*itr)->GetTypeId() == TYPEID_UNIT);
|
assert((*itr)->GetTypeId() == TYPEID_UNIT);
|
||||||
|
|
||||||
if(!((Creature*)(*itr))->HasSummonMask(SUMMON_MASK_GUARDIAN))
|
if(!((Creature*)(*itr))->HasSummonMask(SUMMON_MASK_CONTROLABLE_GUARDIAN))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(AddUInt64Value(UNIT_FIELD_SUMMON, (*itr)->GetGUID()))
|
if(AddUInt64Value(UNIT_FIELD_SUMMON, (*itr)->GetGUID()))
|
||||||
{
|
{
|
||||||
//show another pet bar if there is no charm bar
|
//show another pet bar if there is no charm bar
|
||||||
if(GetTypeId() == TYPEID_PLAYER && !GetCharmGUID() && ((Creature*)(*itr))->HasSummonMask(SUMMON_MASK_GUARDIAN))
|
if(GetTypeId() == TYPEID_PLAYER && !GetCharmGUID() && ((Creature*)(*itr))->HasSummonMask(SUMMON_MASK_CONTROLABLE_GUARDIAN))
|
||||||
{
|
{
|
||||||
if(((Creature*)(*itr))->isPet())
|
if(((Creature*)(*itr))->isPet())
|
||||||
((Player*)this)->PetSpellInitialize();
|
((Player*)this)->PetSpellInitialize();
|
||||||
@@ -11140,8 +11140,8 @@ bool Unit::CanHaveThreatList() const
|
|||||||
//if( ((Creature*)this)->isVehicle() )
|
//if( ((Creature*)this)->isVehicle() )
|
||||||
// return false;
|
// return false;
|
||||||
|
|
||||||
// pets can not have a threat list, unless they are controlled by a creature
|
// summons can not have a threat list, unless they are controlled by a creature
|
||||||
if( ((Creature*)this)->isPet() && IS_PLAYER_GUID(((Pet*)this)->GetOwnerGUID()) )
|
if( ((Creature*)this)->HasSummonMask(SUMMON_MASK_MINION | SUMMON_MASK_GUARDIAN | SUMMON_MASK_CONTROLABLE_GUARDIAN) && IS_PLAYER_GUID(((Pet*)this)->GetOwnerGUID()) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -11284,9 +11284,39 @@ Unit* Creature::SelectVictim()
|
|||||||
target = getVictim();
|
target = getVictim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CanHaveThreatList())
|
||||||
|
{
|
||||||
if ( !target && !m_ThreatManager.isThreatListEmpty() )
|
if ( !target && !m_ThreatManager.isThreatListEmpty() )
|
||||||
// No taunt aura or taunt aura caster is dead standart target selection
|
// No taunt aura or taunt aura caster is dead standart target selection
|
||||||
target = m_ThreatManager.getHostilTarget();
|
target = m_ThreatManager.getHostilTarget();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We have player pet probably
|
||||||
|
target = getAttackerForHelper();
|
||||||
|
if (!target && isSummon())
|
||||||
|
{
|
||||||
|
if (Unit * owner = ((TempSummon*)this)->GetOwner())
|
||||||
|
{
|
||||||
|
if (HasReactState(REACT_AGGRESSIVE) || HasReactState(REACT_DEFENSIVE))
|
||||||
|
{
|
||||||
|
if (owner->isInCombat())
|
||||||
|
target = owner->getAttackerForHelper();
|
||||||
|
if (!target)
|
||||||
|
{
|
||||||
|
for(ControlList::const_iterator itr = owner->m_Controlled.begin(); itr != owner->m_Controlled.end(); ++itr)
|
||||||
|
{
|
||||||
|
if ((*itr)->isInCombat())
|
||||||
|
{
|
||||||
|
target = (*itr)->getAttackerForHelper();
|
||||||
|
if (target) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(target)
|
if(target)
|
||||||
{
|
{
|
||||||
@@ -11299,7 +11329,7 @@ Unit* Creature::SelectVictim()
|
|||||||
// it in combat but attacker not make any damage and not enter to aggro radius to have record in threat list
|
// it in combat but attacker not make any damage and not enter to aggro radius to have record in threat list
|
||||||
// for example at owner command to pet attack some far away creature
|
// for example at owner command to pet attack some far away creature
|
||||||
// Note: creature not have targeted movement generator but have attacker in this case
|
// Note: creature not have targeted movement generator but have attacker in this case
|
||||||
if(m_attackers.size() && m_ThreatManager.isThreatListEmpty()) //there are some cases null target are always returned,so creature evade can not be called at all. such as pull creature at a distance beyond the attackdist to the attacker
|
if(m_attackers.size() && CanHaveThreatList() && m_ThreatManager.isThreatListEmpty()) //there are some cases null target are always returned,so creature evade can not be called at all. such as pull creature at a distance beyond the attackdist to the attacker
|
||||||
return NULL;
|
return NULL;
|
||||||
/*if( GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE )
|
/*if( GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE )
|
||||||
{
|
{
|
||||||
@@ -14846,6 +14876,15 @@ void Unit::SetFlying(bool apply)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Unit::GetFollowAngle() const
|
||||||
|
{
|
||||||
|
if (GetTypeId()!=TYPEID_UNIT)
|
||||||
|
return PET_FOLLOW_ANGLE;
|
||||||
|
if (!((Creature*)this)->HasSummonMask(SUMMON_MASK_MINION))
|
||||||
|
return PET_FOLLOW_ANGLE;
|
||||||
|
return ((Minion*)this)->GetFollowAngle();
|
||||||
|
}
|
||||||
|
|
||||||
void Unit::NearTeleportTo( float x, float y, float z, float orientation, bool casting /*= false*/ )
|
void Unit::NearTeleportTo( float x, float y, float z, float orientation, bool casting /*= false*/ )
|
||||||
{
|
{
|
||||||
if(GetTypeId() == TYPEID_PLAYER)
|
if(GetTypeId() == TYPEID_PLAYER)
|
||||||
|
|||||||
@@ -1803,6 +1803,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
|
|||||||
bool canFly() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FLY_MODE); }
|
bool canFly() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FLY_MODE); }
|
||||||
bool IsFlying() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FLYING); }
|
bool IsFlying() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FLYING); }
|
||||||
void SetFlying(bool apply);
|
void SetFlying(bool apply);
|
||||||
|
float GetFollowAngle() const;
|
||||||
protected:
|
protected:
|
||||||
explicit Unit ();
|
explicit Unit ();
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -348,7 +348,7 @@ void SimpleCharmedAI::UpdateAI(const uint32 /*diff*/)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!charmer->isInCombat())
|
if(!charmer->isInCombat())
|
||||||
me->GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
|
me->GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, me->GetFollowAngle());
|
||||||
|
|
||||||
Unit *target = me->getVictim();
|
Unit *target = me->getVictim();
|
||||||
if(!target || !charmer->canAttack(target))
|
if(!target || !charmer->canAttack(target))
|
||||||
|
|||||||
@@ -711,6 +711,7 @@ class TRINITY_DLL_SPEC WorldSession
|
|||||||
void HandleCalendarGetNumPending(WorldPacket& recv_data);
|
void HandleCalendarGetNumPending(WorldPacket& recv_data);
|
||||||
|
|
||||||
void HandleSpellClick(WorldPacket& recv_data);
|
void HandleSpellClick(WorldPacket& recv_data);
|
||||||
|
void HandleMirrrorImageDataRequest( WorldPacket & recv_data );
|
||||||
void HandleAlterAppearance(WorldPacket& recv_data);
|
void HandleAlterAppearance(WorldPacket& recv_data);
|
||||||
void HandleRemoveGlyph(WorldPacket& recv_data);
|
void HandleRemoveGlyph(WorldPacket& recv_data);
|
||||||
void HandleCharCustomize(WorldPacket& recv_data);
|
void HandleCharCustomize(WorldPacket& recv_data);
|
||||||
|
|||||||
Reference in New Issue
Block a user