Scripted/Pets: Move some player pets in pet_xxx.cpp

This commit is contained in:
Vincent-Michael
2013-08-09 19:22:16 +02:00
parent b7d88a3c46
commit dbb40dd4fe
11 changed files with 646 additions and 444 deletions

View File

@@ -619,6 +619,13 @@ void AddSC_zangarmarsh();
// Events
void AddSC_event_childrens_week();
// Pets
void AddSC_deathknight_pet_scripts();
void AddSC_hunter_pet_scripts();
void AddSC_mage_pet_scripts();
void AddSC_priest_pet_scripts();
void AddSC_shaman_pet_scripts();
// battlegrounds
// outdoor pvp
@@ -647,6 +654,7 @@ void AddScripts()
AddOutlandScripts();
AddNorthrendScripts();
AddEventScripts();
AddPetScripts();
AddBattlegroundScripts();
AddOutdoorPvPScripts();
AddCustomScripts();
@@ -1283,6 +1291,17 @@ void AddEventScripts()
#endif
}
void AddPetScripts()
{
#ifdef SCRIPTS
AddSC_deathknight_pet_scripts();
AddSC_hunter_pet_scripts();
AddSC_mage_pet_scripts();
AddSC_priest_pet_scripts();
AddSC_shaman_pet_scripts();
#endif
}
void AddOutdoorPvPScripts()
{
#ifdef SCRIPTS

View File

@@ -28,6 +28,7 @@ void AddKalimdorScripts();
void AddOutlandScripts();
void AddNorthrendScripts();
void AddEventScripts();
void AddPetScripts();
void AddBattlegroundScripts();
void AddOutdoorPvPScripts();
void AddCustomScripts();

View File

@@ -38,6 +38,7 @@ if(SCRIPTS)
include(Outland/CMakeLists.txt)
include(Northrend/CMakeLists.txt)
include(Events/CMakeLists.txt)
include(Pet/CMakeLists.txt)
endif()
message(STATUS "SCRIPT PREPARATION COMPLETE")

View File

@@ -0,0 +1,20 @@
# Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
set(scripts_STAT_SRCS
${scripts_STAT_SRCS}
Pet/pet_dk.cpp
Pet/pet_hunter.cpp
Pet/pet_mage.cpp
Pet/pet_priest.cpp
Pet/pet_shaman.cpp
)
message(" -> Prepared: Pet")

View File

@@ -0,0 +1,131 @@
/*
* Copyright (C) 2008-2013 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/>.
*/
/*
* Ordered alphabetically using scriptname.
* Scriptnames of files in this file should be prefixed with "npc_pet_dk_".
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
enum DeathKnightSpells
{
SPELL_DK_SUMMON_GARGOYLE_1 = 49206,
SPELL_DK_SUMMON_GARGOYLE_2 = 50514,
SPELL_DK_DISMISS_GARGOYLE = 50515,
SPELL_DK_SANCTUARY = 54661,
};
class npc_pet_dk_ebon_gargoyle : public CreatureScript
{
public:
npc_pet_dk_ebon_gargoyle() : CreatureScript("npc_pet_dk_ebon_gargoyle") { }
struct npc_pet_dk_ebon_gargoyleAI : CasterAI
{
npc_pet_dk_ebon_gargoyleAI(Creature* creature) : CasterAI(creature) { }
void InitializeAI() OVERRIDE
{
CasterAI::InitializeAI();
uint64 ownerGuid = me->GetOwnerGUID();
if (!ownerGuid)
return;
// Not needed to be despawned now
_despawnTimer = 0;
// Find victim of Summon Gargoyle spell
std::list<Unit*> targets;
Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 30.0f);
Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, targets, u_check);
me->VisitNearbyObject(30.0f, searcher);
for (std::list<Unit*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter)
if ((*iter)->GetAura(SPELL_DK_SUMMON_GARGOYLE_1, ownerGuid))
{
me->Attack((*iter), false);
break;
}
}
void JustDied(Unit* /*killer*/) OVERRIDE
{
// Stop Feeding Gargoyle when it dies
if (Unit* owner = me->GetOwner())
owner->RemoveAurasDueToSpell(SPELL_DK_SUMMON_GARGOYLE_2);
}
// Fly away when dismissed
void SpellHit(Unit* source, SpellInfo const* spell) OVERRIDE
{
if (spell->Id != SPELL_DK_DISMISS_GARGOYLE || !me->IsAlive())
return;
Unit* owner = me->GetOwner();
if (!owner || owner != source)
return;
// Stop Fighting
me->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE, true);
// Sanctuary
me->CastSpell(me, SPELL_DK_SANCTUARY, true);
me->SetReactState(REACT_PASSIVE);
//! HACK: Creature's can't have MOVEMENTFLAG_FLYING
// Fly Away
me->SetCanFly(true);
me->SetSpeed(MOVE_FLIGHT, 0.75f, true);
me->SetSpeed(MOVE_RUN, 0.75f, true);
float x = me->GetPositionX() + 20 * std::cos(me->GetOrientation());
float y = me->GetPositionY() + 20 * std::sin(me->GetOrientation());
float z = me->GetPositionZ() + 40;
me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MovePoint(0, x, y, z);
// Despawn as soon as possible
_despawnTimer = 4 * IN_MILLISECONDS;
}
void UpdateAI(uint32 diff) OVERRIDE
{
if (_despawnTimer > 0)
{
if (_despawnTimer > diff)
_despawnTimer -= diff;
else
me->DespawnOrUnsummon();
return;
}
CasterAI::UpdateAI(diff);
}
private:
uint32 _despawnTimer;
};
CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
return new npc_pet_dk_ebon_gargoyleAI(creature);
}
};
void AddSC_deathknight_pet_scripts()
{
new npc_pet_dk_ebon_gargoyle();
}

View File

@@ -0,0 +1,146 @@
/*
* Copyright (C) 2008-2013 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/>.
*/
/*
* Ordered alphabetically using scriptname.
* Scriptnames of files in this file should be prefixed with "npc_pet_hun_".
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
enum HunterSpells
{
SPELL_HUNTER_CRIPPLING_POISON = 30981, // Viper
SPELL_HUNTER_DEADLY_POISON = 34655, // Venomous Snake
SPELL_HUNTER_MIND_NUMBING_POISON = 25810 // Viper
};
enum HunterCreatures
{
NPC_HUNTER_VIPER = 19921
};
class npc_pet_hunter_snake_trap : public CreatureScript
{
public:
npc_pet_hunter_snake_trap() : CreatureScript("npc_pet_hunter_snake_trap") { }
struct npc_pet_hunter_snake_trapAI : public ScriptedAI
{
npc_pet_hunter_snake_trapAI(Creature* creature) : ScriptedAI(creature) { }
void EnterCombat(Unit* /*who*/) OVERRIDE { }
void Reset() OVERRIDE
{
_spellTimer = 0;
CreatureTemplate const* Info = me->GetCreatureTemplate();
_isViper = Info->Entry == NPC_HUNTER_VIPER ? true : false;
me->SetMaxHealth(uint32(107 * (me->getLevel() - 40) * 0.025f));
// Add delta to make them not all hit the same time
uint32 delta = (rand() % 7) * 100;
me->SetStatFloatValue(UNIT_FIELD_BASEATTACKTIME, float(Info->baseattacktime + delta));
me->SetStatFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER, float(Info->attackpower));
// Start attacking attacker of owner on first ai update after spawn - move in line of sight may choose better target
if (!me->GetVictim() && me->IsSummon())
if (Unit* Owner = me->ToTempSummon()->GetSummoner())
if (Owner->getAttackerForHelper())
AttackStart(Owner->getAttackerForHelper());
}
// Redefined for random target selection:
void MoveInLineOfSight(Unit* who) OVERRIDE
{
if (!me->GetVictim() && me->CanCreatureAttack(who))
{
if (me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)
return;
float attackRadius = me->GetAttackDistance(who);
if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who))
{
if (!(rand() % 5))
{
me->setAttackTimer(BASE_ATTACK, (rand() % 10) * 100);
_spellTimer = (rand() % 10) * 100;
AttackStart(who);
}
}
}
}
void UpdateAI(uint32 diff) OVERRIDE
{
if (!UpdateVictim())
return;
if (me->GetVictim()->HasBreakableByDamageCrowdControlAura(me))
{
me->InterruptNonMeleeSpells(false);
return;
}
if (_spellTimer <= diff)
{
if (_isViper) //Viper
{
if (urand(0, 2) == 0) //33% chance to cast
{
uint32 spell;
if (urand(0, 1) == 0)
spell = SPELL_HUNTER_MIND_NUMBING_POISON;
else
spell = SPELL_HUNTER_CRIPPLING_POISON;
DoCastVictim(spell);
}
_spellTimer = 3000;
}
else // Venomous Snake
{
if (urand(0, 2) == 0) // 33% chance to cast
DoCastVictim(SPELL_HUNTER_DEADLY_POISON);
_spellTimer = 1500 + (rand() % 5) * 100;
}
}
else
_spellTimer -= diff;
DoMeleeAttackIfReady();
}
private:
bool _isViper;
uint32 _spellTimer;
};
CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
return new npc_pet_hunter_snake_trapAI(creature);
}
};
void AddSC_hunter_pet_scripts()
{
new npc_pet_hunter_snake_trap();
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2008-2013 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/>.
*/
/*
* Ordered alphabetically using scriptname.
* Scriptnames of files in this file should be prefixed with "npc_pet_mag_".
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
enum MageSpells
{
SPELL_MAGE_CLONE_ME = 45204,
SPELL_MAGE_MASTERS_THREAT_LIST = 58838
};
class npc_pet_mage_mirror_image : public CreatureScript
{
public:
npc_pet_mage_mirror_image() : CreatureScript("npc_pet_mage_mirror_image") { }
struct npc_pet_mage_mirror_imageAI : CasterAI
{
npc_pet_mage_mirror_imageAI(Creature* creature) : CasterAI(creature) { }
void InitializeAI() OVERRIDE
{
CasterAI::InitializeAI();
Unit* owner = me->GetOwner();
if (!owner)
return;
// Inherit Master's Threat List (not yet implemented)
owner->CastSpell((Unit*)NULL, SPELL_MAGE_MASTERS_THREAT_LIST, 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, SPELL_MAGE_CLONE_ME, false);
}
// Do not reload Creature templates on evade mode enter - prevent visual lost
void EnterEvadeMode() OVERRIDE
{
if (me->IsInEvadeMode() || !me->IsAlive())
return;
Unit* owner = me->GetCharmerOrOwner();
me->CombatStop(true);
if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW))
{
me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle(), MOTION_SLOT_ACTIVE);
}
}
};
CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
return new npc_pet_mage_mirror_imageAI(creature);
}
};
void AddSC_mage_pet_scripts()
{
new npc_pet_mage_mirror_image();
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (C) 2008-2013 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/>.
*/
/*
* Ordered alphabetically using scriptname.
* Scriptnames of files in this file should be prefixed with "npc_pet_pri_".
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "PetAI.h"
enum PriestSpells
{
SPELL_PRIEST_GLYPH_OF_SHADOWFIEND = 58228,
SPELL_PRIEST_GLYPH_OF_SHADOWFIEND_MANA = 58227,
SPELL_PRIEST_LIGHTWELL_CHARGES = 59907
};
class npc_pet_pri_lightwell : public CreatureScript
{
public:
npc_pet_pri_lightwell() : CreatureScript("npc_pet_pri_lightwell") { }
struct npc_pet_pri_lightwellAI : public PassiveAI
{
npc_pet_pri_lightwellAI(Creature* creature) : PassiveAI(creature)
{
DoCast(me, SPELL_PRIEST_LIGHTWELL_CHARGES, false);
}
void EnterEvadeMode() OVERRIDE
{
if (!me->IsAlive())
return;
me->DeleteThreatList();
me->CombatStop(true);
me->ResetPlayerDamageReq();
}
};
CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
return new npc_pet_pri_lightwellAI(creature);
}
};
class npc_pet_pri_shadowfiend : public CreatureScript
{
public:
npc_pet_pri_shadowfiend() : CreatureScript("npc_pet_pri_shadowfiend") { }
struct npc_pet_pri_shadowfiendAI : public PetAI
{
npc_pet_pri_shadowfiendAI(Creature* creature) : PetAI(creature) { }
void JustDied(Unit* /*killer*/) OVERRIDE
{
if (me->IsSummon())
if (Unit* owner = me->ToTempSummon()->GetSummoner())
if (owner->HasAura(SPELL_PRIEST_GLYPH_OF_SHADOWFIEND))
owner->CastSpell(owner, SPELL_PRIEST_GLYPH_OF_SHADOWFIEND_MANA, true);
}
};
CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
return new npc_pet_pri_shadowfiendAI(creature);
}
};
void AddSC_priest_pet_scripts()
{
new npc_pet_pri_lightwell();
new npc_pet_pri_shadowfiend();
}

View File

@@ -0,0 +1,149 @@
/*
* Copyright (C) 2008-2013 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/>.
*/
/*
* Ordered alphabetically using scriptname.
* Scriptnames of files in this file should be prefixed with "npc_pet_sha_".
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
enum ShamanSpells
{
SPELL_SHAMAN_ANGEREDEARTH = 36213,
SPELL_SHAMAN_FIREBLAST = 57984,
SPELL_SHAMAN_FIRENOVA = 12470,
SPELL_SHAMAN_FIRESHIELD = 13376
};
enum ShamanEvents
{
// Earth Elemental
EVENT_SHAMAN_ANGEREDEARTH = 1,
// Fire Elemental
EVENT_SHAMAN_FIRENOVA = 1,
EVENT_SHAMAN_FIRESHIELD = 2,
EVENT_SHAMAN_FIREBLAST = 3
};
class npc_pet_shaman_earth_elemental : public CreatureScript
{
public:
npc_pet_shaman_earth_elemental() : CreatureScript("npc_pet_shaman_earth_elemental") { }
struct npc_pet_shaman_earth_elementalAI : public ScriptedAI
{
npc_pet_shaman_earth_elementalAI(Creature* creature) : ScriptedAI(creature) { }
void Reset() OVERRIDE
{
_events.Reset();
_events.ScheduleEvent(EVENT_SHAMAN_ANGEREDEARTH, 0);
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true);
}
void UpdateAI(uint32 diff) OVERRIDE
{
if (!UpdateVictim())
return;
if (_events.ExecuteEvent() == EVENT_SHAMAN_ANGEREDEARTH)
{
DoCastVictim(SPELL_SHAMAN_ANGEREDEARTH);
_events.ScheduleEvent(EVENT_SHAMAN_ANGEREDEARTH, urand(5000, 20000));
}
DoMeleeAttackIfReady();
}
private:
EventMap _events;
};
CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
return new npc_pet_shaman_earth_elementalAI(creature);
}
};
class npc_pet_shaman_fire_elemental : public CreatureScript
{
public:
npc_pet_shaman_fire_elemental() : CreatureScript("npc_pet_shaman_fire_elemental") { }
struct npc_pet_shaman_fire_elementalAI : public ScriptedAI
{
npc_pet_shaman_fire_elementalAI(Creature* creature) : ScriptedAI(creature) { }
void Reset() OVERRIDE
{
_events.Reset();
_events.ScheduleEvent(EVENT_SHAMAN_FIRENOVA, urand(5000, 20000));
_events.ScheduleEvent(EVENT_SHAMAN_FIREBLAST, urand(5000, 20000));
_events.ScheduleEvent(EVENT_SHAMAN_FIRESHIELD, 0);
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true);
}
void UpdateAI(uint32 diff) OVERRIDE
{
if (!UpdateVictim())
return;
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SHAMAN_FIRENOVA:
DoCastVictim(SPELL_SHAMAN_FIRENOVA);
_events.ScheduleEvent(EVENT_SHAMAN_FIRENOVA, urand(5000, 20000));
break;
case EVENT_SHAMAN_FIRESHIELD:
DoCastVictim(SPELL_SHAMAN_FIRESHIELD);
_events.ScheduleEvent(EVENT_SHAMAN_FIRESHIELD, 2000);
break;
case EVENT_SHAMAN_FIREBLAST:
DoCastVictim(SPELL_SHAMAN_FIREBLAST);
_events.ScheduleEvent(EVENT_SHAMAN_FIREBLAST, urand(5000, 20000));
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
EventMap _events;
};
CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
return new npc_pet_shaman_fire_elementalAI(creature);
}
};
void AddSC_shaman_pet_scripts()
{
new npc_pet_shaman_earth_elemental();
new npc_pet_shaman_fire_elemental();
}

View File

@@ -1602,124 +1602,6 @@ public:
};
/*####
## npc_snake_trap_serpents
####*/
enum SnakeTrapSerpents
{
SPELL_MIND_NUMBING_POISON = 25810, // Viper
SPELL_DEADLY_POISON = 34655, // Venomous Snake
SPELL_CRIPPLING_POISON = 30981, // Viper
NPC_VIPER = 19921
};
class npc_snake_trap : public CreatureScript
{
public:
npc_snake_trap() : CreatureScript("npc_snake_trap_serpents") { }
struct npc_snake_trap_serpentsAI : public ScriptedAI
{
npc_snake_trap_serpentsAI(Creature* creature) : ScriptedAI(creature) {}
uint32 SpellTimer;
bool IsViper;
void EnterCombat(Unit* /*who*/) OVERRIDE {}
void Reset() OVERRIDE
{
SpellTimer = 0;
CreatureTemplate const* Info = me->GetCreatureTemplate();
IsViper = Info->Entry == NPC_VIPER ? true : false;
me->SetMaxHealth(uint32(107 * (me->getLevel() - 40) * 0.025f));
//Add delta to make them not all hit the same time
uint32 delta = (rand() % 7) * 100;
me->SetStatFloatValue(UNIT_FIELD_BASEATTACKTIME, float(Info->baseattacktime + delta));
me->SetStatFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER, float(Info->attackpower));
// Start attacking attacker of owner on first ai update after spawn - move in line of sight may choose better target
if (!me->GetVictim() && me->IsSummon())
if (Unit* Owner = me->ToTempSummon()->GetSummoner())
if (Owner->getAttackerForHelper())
AttackStart(Owner->getAttackerForHelper());
}
//Redefined for random target selection:
void MoveInLineOfSight(Unit* who) OVERRIDE
{
if (!me->GetVictim() && me->CanCreatureAttack(who))
{
if (me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)
return;
float attackRadius = me->GetAttackDistance(who);
if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who))
{
if (!(rand() % 5))
{
me->setAttackTimer(BASE_ATTACK, (rand() % 10) * 100);
SpellTimer = (rand() % 10) * 100;
AttackStart(who);
}
}
}
}
void UpdateAI(uint32 diff) OVERRIDE
{
if (!UpdateVictim())
return;
if (me->GetVictim()->HasBreakableByDamageCrowdControlAura(me))
{
me->InterruptNonMeleeSpells(false);
return;
}
if (SpellTimer <= diff)
{
if (IsViper) //Viper
{
if (urand(0, 2) == 0) //33% chance to cast
{
uint32 spell;
if (urand(0, 1) == 0)
spell = SPELL_MIND_NUMBING_POISON;
else
spell = SPELL_CRIPPLING_POISON;
DoCastVictim(spell);
}
SpellTimer = 3000;
}
else //Venomous Snake
{
if (urand(0, 2) == 0) //33% chance to cast
DoCastVictim(SPELL_DEADLY_POISON);
SpellTimer = 1500 + (rand() % 5) * 100;
}
}
else
SpellTimer -= diff;
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
return new npc_snake_trap_serpentsAI(creature);
}
};
#define SAY_RANDOM_MOJO0 "Now that's what I call froggy-style!"
#define SAY_RANDOM_MOJO1 "Your lily pad or mine?"
#define SAY_RANDOM_MOJO2 "This won't take long, did it?"
@@ -1821,172 +1703,6 @@ public:
}
};
class npc_mirror_image : public CreatureScript
{
public:
npc_mirror_image() : CreatureScript("npc_mirror_image") { }
struct npc_mirror_imageAI : CasterAI
{
npc_mirror_imageAI(Creature* creature) : CasterAI(creature) {}
void InitializeAI() OVERRIDE
{
CasterAI::InitializeAI();
Unit* owner = me->GetOwner();
if (!owner)
return;
// 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);
}
// Do not reload Creature templates on evade mode enter - prevent visual lost
void EnterEvadeMode() OVERRIDE
{
if (me->IsInEvadeMode() || !me->IsAlive())
return;
Unit* owner = me->GetCharmerOrOwner();
me->CombatStop(true);
if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW))
{
me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle(), MOTION_SLOT_ACTIVE);
}
}
};
CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
return new npc_mirror_imageAI(creature);
}
};
class npc_ebon_gargoyle : public CreatureScript
{
public:
npc_ebon_gargoyle() : CreatureScript("npc_ebon_gargoyle") { }
struct npc_ebon_gargoyleAI : CasterAI
{
npc_ebon_gargoyleAI(Creature* creature) : CasterAI(creature) {}
uint32 despawnTimer;
void InitializeAI() OVERRIDE
{
CasterAI::InitializeAI();
uint64 ownerGuid = me->GetOwnerGUID();
if (!ownerGuid)
return;
// Not needed to be despawned now
despawnTimer = 0;
// Find victim of Summon Gargoyle spell
std::list<Unit*> targets;
Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 30);
Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, targets, u_check);
me->VisitNearbyObject(30, searcher);
for (std::list<Unit*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter)
if ((*iter)->GetAura(49206, ownerGuid))
{
me->Attack((*iter), false);
break;
}
}
void JustDied(Unit* /*killer*/) OVERRIDE
{
// Stop Feeding Gargoyle when it dies
if (Unit* owner = me->GetOwner())
owner->RemoveAurasDueToSpell(50514);
}
// Fly away when dismissed
void SpellHit(Unit* source, SpellInfo const* spell) OVERRIDE
{
if (spell->Id != 50515 || !me->IsAlive())
return;
Unit* owner = me->GetOwner();
if (!owner || owner != source)
return;
// Stop Fighting
me->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE, true);
// Sanctuary
me->CastSpell(me, 54661, true);
me->SetReactState(REACT_PASSIVE);
//! HACK: Creature's can't have MOVEMENTFLAG_FLYING
// Fly Away
me->SetCanFly(true);
me->SetSpeed(MOVE_FLIGHT, 0.75f, true);
me->SetSpeed(MOVE_RUN, 0.75f, true);
float x = me->GetPositionX() + 20 * std::cos(me->GetOrientation());
float y = me->GetPositionY() + 20 * std::sin(me->GetOrientation());
float z = me->GetPositionZ() + 40;
me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MovePoint(0, x, y, z);
// Despawn as soon as possible
despawnTimer = 4 * IN_MILLISECONDS;
}
void UpdateAI(uint32 diff) OVERRIDE
{
if (despawnTimer > 0)
{
if (despawnTimer > diff)
despawnTimer -= diff;
else
me->DespawnOrUnsummon();
return;
}
CasterAI::UpdateAI(diff);
}
};
CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
return new npc_ebon_gargoyleAI(creature);
}
};
class npc_lightwell : public CreatureScript
{
public:
npc_lightwell() : CreatureScript("npc_lightwell") { }
struct npc_lightwellAI : public PassiveAI
{
npc_lightwellAI(Creature* creature) : PassiveAI(creature)
{
DoCast(me, 59907, false);
}
void EnterEvadeMode() OVERRIDE
{
if (!me->IsAlive())
return;
me->DeleteThreatList();
me->CombatStop(true);
me->ResetPlayerDamageReq();
}
};
CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
return new npc_lightwellAI(creature);
}
};
enum TrainingDummy
{
NPC_ADVANCED_TARGET_DUMMY = 2674,
@@ -2070,159 +1786,6 @@ public:
}
};
/*######
# npc_shadowfiend
######*/
#define GLYPH_OF_SHADOWFIEND_MANA 58227
#define GLYPH_OF_SHADOWFIEND 58228
class npc_shadowfiend : public CreatureScript
{
public:
npc_shadowfiend() : CreatureScript("npc_shadowfiend") { }
struct npc_shadowfiendAI : public PetAI
{
npc_shadowfiendAI(Creature* creature) : PetAI(creature) {}
void JustDied(Unit* /*killer*/) OVERRIDE
{
if (me->IsSummon())
if (Unit* owner = me->ToTempSummon()->GetSummoner())
if (owner->HasAura(GLYPH_OF_SHADOWFIEND))
owner->CastSpell(owner, GLYPH_OF_SHADOWFIEND_MANA, true);
}
};
CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
return new npc_shadowfiendAI(creature);
}
};
/*######
# npc_fire_elemental
######*/
enum FireElemental
{
SPELL_FIRENOVA = 12470,
SPELL_FIRESHIELD = 13376,
SPELL_FIREBLAST = 57984
};
class npc_fire_elemental : public CreatureScript
{
public:
npc_fire_elemental() : CreatureScript("npc_fire_elemental") { }
struct npc_fire_elementalAI : public ScriptedAI
{
npc_fire_elementalAI(Creature* creature) : ScriptedAI(creature) {}
uint32 FireNova_Timer;
uint32 FireShield_Timer;
uint32 FireBlast_Timer;
void Reset() OVERRIDE
{
FireNova_Timer = 5000 + rand() % 15000; // 5-20 sec cd
FireBlast_Timer = 5000 + rand() % 15000; // 5-20 sec cd
FireShield_Timer = 0;
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true);
}
void UpdateAI(uint32 diff) OVERRIDE
{
if (!UpdateVictim())
return;
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (FireShield_Timer <= diff)
{
DoCastVictim(SPELL_FIRESHIELD);
FireShield_Timer = 2 * IN_MILLISECONDS;
}
else
FireShield_Timer -= diff;
if (FireBlast_Timer <= diff)
{
DoCastVictim(SPELL_FIREBLAST);
FireBlast_Timer = 5000 + rand() % 15000; // 5-20 sec cd
}
else
FireBlast_Timer -= diff;
if (FireNova_Timer <= diff)
{
DoCastVictim(SPELL_FIRENOVA);
FireNova_Timer = 5000 + rand() % 15000; // 5-20 sec cd
}
else
FireNova_Timer -= diff;
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
return new npc_fire_elementalAI(creature);
}
};
/*######
# npc_earth_elemental
######*/
enum EarthElemental
{
SPELL_ANGEREDEARTH = 36213
};
class npc_earth_elemental : public CreatureScript
{
public:
npc_earth_elemental() : CreatureScript("npc_earth_elemental") { }
struct npc_earth_elementalAI : public ScriptedAI
{
npc_earth_elementalAI(Creature* creature) : ScriptedAI(creature) {}
uint32 AngeredEarth_Timer;
void Reset() OVERRIDE
{
AngeredEarth_Timer = 0;
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true);
}
void UpdateAI(uint32 diff) OVERRIDE
{
if (!UpdateVictim())
return;
if (AngeredEarth_Timer <= diff)
{
DoCastVictim(SPELL_ANGEREDEARTH);
AngeredEarth_Timer = 5000 + rand() % 15000; // 5-20 sec cd
}
else
AngeredEarth_Timer -= diff;
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
return new npc_earth_elementalAI(creature);
}
};
/*######
# npc_wormhole
######*/
@@ -2993,19 +2556,12 @@ void AddSC_npcs_special()
new npc_steam_tonk();
new npc_tonk_mine();
new npc_brewfest_reveler();
new npc_snake_trap();
new npc_mirror_image();
new npc_ebon_gargoyle();
new npc_lightwell();
new npc_mojo();
new npc_training_dummy();
new npc_shadowfiend();
new npc_wormhole();
new npc_pet_trainer();
new npc_locksmith();
new npc_experience();
new npc_fire_elemental();
new npc_earth_elemental();
new npc_firework();
new npc_spring_rabbit();
}