diff options
author | Vincent-Michael <Vincent_Michael@gmx.de> | 2013-08-09 19:22:16 +0200 |
---|---|---|
committer | Vincent-Michael <Vincent_Michael@gmx.de> | 2013-08-09 19:22:16 +0200 |
commit | dbb40dd4fedcae00a94e40b2a8d8a6bc62773cf1 (patch) | |
tree | ee45fdd40e28fa0814d738d378cd1144985ff4ee /src/server | |
parent | b7d88a3c469655ec3754e3822ddb82ba960f42b8 (diff) |
Scripted/Pets: Move some player pets in pet_xxx.cpp
Diffstat (limited to 'src/server')
-rw-r--r-- | src/server/game/Scripting/ScriptLoader.cpp | 19 | ||||
-rw-r--r-- | src/server/game/Scripting/ScriptLoader.h | 1 | ||||
-rw-r--r-- | src/server/scripts/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/server/scripts/Pet/CMakeLists.txt | 20 | ||||
-rw-r--r-- | src/server/scripts/Pet/pet_dk.cpp | 131 | ||||
-rw-r--r-- | src/server/scripts/Pet/pet_hunter.cpp | 146 | ||||
-rw-r--r-- | src/server/scripts/Pet/pet_mage.cpp | 81 | ||||
-rw-r--r-- | src/server/scripts/Pet/pet_priest.cpp | 91 | ||||
-rw-r--r-- | src/server/scripts/Pet/pet_shaman.cpp | 149 | ||||
-rw-r--r-- | src/server/scripts/World/npcs_special.cpp | 444 |
10 files changed, 639 insertions, 444 deletions
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index 8e2fc2953c9..a4ee553e9f7 100644 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -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 diff --git a/src/server/game/Scripting/ScriptLoader.h b/src/server/game/Scripting/ScriptLoader.h index ef29b54369d..79e2454518f 100644 --- a/src/server/game/Scripting/ScriptLoader.h +++ b/src/server/game/Scripting/ScriptLoader.h @@ -28,6 +28,7 @@ void AddKalimdorScripts(); void AddOutlandScripts(); void AddNorthrendScripts(); void AddEventScripts(); +void AddPetScripts(); void AddBattlegroundScripts(); void AddOutdoorPvPScripts(); void AddCustomScripts(); diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt index cf4618022b3..5be634d2060 100644 --- a/src/server/scripts/CMakeLists.txt +++ b/src/server/scripts/CMakeLists.txt @@ -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") diff --git a/src/server/scripts/Pet/CMakeLists.txt b/src/server/scripts/Pet/CMakeLists.txt new file mode 100644 index 00000000000..b4a8eea77d8 --- /dev/null +++ b/src/server/scripts/Pet/CMakeLists.txt @@ -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") diff --git a/src/server/scripts/Pet/pet_dk.cpp b/src/server/scripts/Pet/pet_dk.cpp new file mode 100644 index 00000000000..7a3776fb0b5 --- /dev/null +++ b/src/server/scripts/Pet/pet_dk.cpp @@ -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(); +} diff --git a/src/server/scripts/Pet/pet_hunter.cpp b/src/server/scripts/Pet/pet_hunter.cpp new file mode 100644 index 00000000000..90281654710 --- /dev/null +++ b/src/server/scripts/Pet/pet_hunter.cpp @@ -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(); +} diff --git a/src/server/scripts/Pet/pet_mage.cpp b/src/server/scripts/Pet/pet_mage.cpp new file mode 100644 index 00000000000..479cbc69ada --- /dev/null +++ b/src/server/scripts/Pet/pet_mage.cpp @@ -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(); +} diff --git a/src/server/scripts/Pet/pet_priest.cpp b/src/server/scripts/Pet/pet_priest.cpp new file mode 100644 index 00000000000..fa273de1870 --- /dev/null +++ b/src/server/scripts/Pet/pet_priest.cpp @@ -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(); +} diff --git a/src/server/scripts/Pet/pet_shaman.cpp b/src/server/scripts/Pet/pet_shaman.cpp new file mode 100644 index 00000000000..63ce0d6b3e3 --- /dev/null +++ b/src/server/scripts/Pet/pet_shaman.cpp @@ -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(); +} diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index f3d86c47b21..f45462fa80c 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -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, @@ -2071,159 +1787,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(); } |