diff options
13 files changed, 482 insertions, 73 deletions
diff --git a/sql/updates/world/2012_09_22_00_world_utgarde.sql b/sql/updates/world/2012_09_22_00_world_utgarde.sql new file mode 100644 index 00000000000..83cc227f9cd --- /dev/null +++ b/sql/updates/world/2012_09_22_00_world_utgarde.sql @@ -0,0 +1,102 @@ +-- Frenzied geist +DELETE FROM `creature_loot_template` WHERE `entry`=31671; +-- Savage worg +DELETE FROM `creature_loot_template` WHERE `entry`=31678 AND `item` IN(39211,39212,33454); +INSERT INTO `creature_loot_template` (`entry`, `item`, `ChanceOrQuestChance`, `mincountOrRef`, `maxcount`) VALUES  +(31678,39211,70,3,5), +(31678,39212,16,2,4), +(31678,33454, 3,1,1); + +-- Keleseth +UPDATE `creature_template` SET `mechanic_immune_mask`=617289692 WHERE `entry` IN(23953,30748); +-- Tunneling ghoul +DELETE FROM `creature_loot_template` WHERE `entry`=31681; +-- Dalronn heartsplitter +UPDATE `creature_template` SET `mindmg`=380,`maxdmg`=580,`attackpower`=0,`dmg_multiplier`=10 WHERE `entry`=31660; +-- Frenzied geist +UPDATE `creature_template` SET `lootid`=28419 WHERE `entry`=31671; +UPDATE `creature_template` SET `AIName`='SmartAI',`ScriptName`='' WHERE `entry`=28419; +-- Skarvald the constructor - On level 81 health fits/is blizzlike, depending on wowhead his level range is 72 - 81 +UPDATE `creature_template` SET `minlevel`=81,`maxlevel`=81 WHERE `entry`=31679; +-- Tunneling ghoul +UPDATE `creature_template` SET `lootid`=24084 WHERE `entry`=31681; +-- Dragonflayer runecaster +UPDATE `creature_template` SET `ScriptName`='',`AIName`='SmartAI' WHERE `entry`=23960; +-- Dragonflayer strategist +UPDATE `creature_template` SET `minlevel`=80,`maxlevel`=80,`unit_flags`=`unit_flags`|131072 WHERE `entry`=32246; +-- Ingvar and undead Ingvar +UPDATE `creature_template` SET `mindmg`=650,`maxdmg`=900,`attackpower`=200, `dmg_multiplier`=10 WHERE `entry` IN(31673,31674); +UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|1  WHERE `entry` IN(23954,31673,23980,31674); +-- Throw axe dummy +UPDATE `creature_template` SET `unit_flags`=2|131072|33554432, `flags_extra`=`flags_extra`|2, `equipment_id`=720 WHERE `entry` IN(23997,31835); +-- Throw axe target +UPDATE `creature_template` SET `unit_flags`=2|4|256|512, `faction_A`=35, `faction_H`=35, `flags_extra`=`flags_extra`|128 WHERE `entry`=23996; + +-- Dragonflayer runecaster +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=23960; +DELETE FROM `smart_scripts` WHERE `entryorguid`=23960 AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `id`, `event_type`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `target_type`, `target_param2`, `comment`) VALUES  +(23960,1,0,2,5000,7000,14000,17000,11,42740,11,30,'Dragonflayer Runecaster - In combat - Cast Njords Rune of Protection'), +(23960,2,0,4,5000,7000,14000,17000,11,59616,11,30,'Dragonflayer Runecaster - In combat - Cast Njords Rune of Protection'), +(23960,3,0,2,1000,2000,15000,18000,11,54965, 1, 0,'Dragonflayer Runecaster - In combat - Cast Bolthorns Rune of Flame'), +(23960,4,0,4,1000,2000,15000,18000,11,59617, 1, 0,'Dragonflayer Runecaster - In combat - Cast Bolthorns Rune of Flame'); + +-- Frenzied geist +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=28419; +DELETE FROM `smart_scripts` WHERE `entryorguid`=28419 AND `source_type`=0; +INSERT INTO `smart_scripts`(`entryorguid`,`event_type`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`target_type`,`comment`) VALUES +(28419,0,5000,5000,30000,30000,11,40414,5,'Frenzied geist - In combat - Cast Fixate'); + +-- Difficulty data for spells used in utgarde keep +DELETE FROM `spelldifficulty_dbc` WHERE `id` IN(42669,42708,42750,42723,42729,43667,42702) OR `spellid0` IN(42669,42708,42750,42723,42729,43667,42702); +INSERT INTO `spelldifficulty_dbc`(`id`,`spellid0`,`spellid1`) VALUES +(42669,42669,59706), -- Smash +(42708,42708,59708), -- Staggering Roar +(42750,42750,59719), -- Throw Axe +(42723,42723,59709), -- Dark Smash +(42729,42729,59734), -- Dreadful Roar +(43667,43667,59389), -- Shadow Bolt +(42702,42702,59397); -- Decrepify + +-- Ticking Time Bomb, Fixate +DELETE FROM `spell_script_names` WHERE `spell_id` IN(59686,40414); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES  +(59686,'spell_ticking_time_bomb'), +(40414,'spell_fixate'); + +-- Proto-drake striders +UPDATE `creature` SET `position_x`=212.429,`position_y`=-127.793,`position_z`=256.101,`MovementType`=2 WHERE `guid`=125914; +UPDATE `creature` SET `position_x`=211.854,`position_y`=-112.602,`position_z`=262.188,`MovementType`=2 WHERE `guid`=125915; +UPDATE `creature` SET `position_x`=211.024,`position_y`=-100.299,`position_z`=266.201,`MovementType`=2 WHERE `guid`=125920; +UPDATE `creature` SET `position_x`=213.777,`position_y`=-140.709,`position_z`=251.048,`MovementType`=2 WHERE `guid`=125922; +UPDATE `creature` SET `position_x`=252.247,`position_y`=-350.532,`position_z`=185.813,`MovementType`=2 WHERE `guid`=125934; +UPDATE `creature` SET `position_x`=243.964,`position_y`=-194.833,`position_z`=227.126,`MovementType`=2 WHERE `guid`=125936; +UPDATE `creature` SET `position_x`=221.534,`position_y`=-239.809,`position_z`=196.459,`MovementType`=2 WHERE `guid`=125937; +UPDATE `creature` SET `position_x`=238.382,`position_y`=-353.086,`position_z`=188.785,`MovementType`=2 WHERE `guid`=125940; + +-- Waypoint assignments +DELETE FROM `creature_addon` WHERE `guid` IN (125940,125934,125915,125920,125914,125936,125937,125922); +INSERT INTO `creature_addon`(`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`auras`) VALUES +(125914,1259140,22657,50331648,1,'54775'), +(125915,1259150,22657,50331648,1,'54775'), +(125920,1259200,22657,50331648,1,'54775'), +(125922,1259220,22657,50331648,1,'54775'), +(125934,1259340,22657,50331648,1,'54775'), +(125936,1259360,22657,50331648,1,'54775'), +(125937,1259370,22657,50331648,1,'54775'), +(125940,1259400,22657,50331648,1,'54775'); + +-- Waypoint data +DELETE FROM `waypoint_data` WHERE `id` IN (1259400,1259340,1259150,1259200,1259140,1259360,1259370,1259220); +INSERT INTO `waypoint_data`(`id`,`point`,`position_x`,`position_y`,`position_z`) VALUES  +(1259400,1,211.864,-352.629,196.144), +(1259340,1,271.911,-318.506,185.049), +(1259150,1,265.478,-199.246,186.812), +(1259200,1,346.765,-99.2527,220.519), +(1259140,1,295.597,-181.162,207.374), +(1259360,1,271.68,-194.911,220.248), +(1259370,1,238.947,-255.704,191.639), +(1259220,1,149.42,-247.696,194.145); + +INSERT INTO `waypoint_data`(`id`,`point`,`position_x`,`position_y`,`position_z`) +SELECT `guid`*10,2,`position_x`,`position_y`,`position_z` FROM `creature` WHERE `guid` IN (125940,125934,125915,125920,125914,125936,125937,125922); diff --git a/sql/updates/world/2012_09_22_01_world_i_was_a_lot_of_things.sql b/sql/updates/world/2012_09_22_01_world_i_was_a_lot_of_things.sql new file mode 100644 index 00000000000..1682d9f699b --- /dev/null +++ b/sql/updates/world/2012_09_22_01_world_i_was_a_lot_of_things.sql @@ -0,0 +1,32 @@ +-- Quest: I was a lot of things +UPDATE `creature_template` SET `AIName`='',`ScriptName`='npc_shadowmoon_tuber_node',`flags_extra`=`flags_extra`|128 WHERE `entry`=21347; + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=36652; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`Comment`) VALUES  +(13,1,36652,31,3,21347,'Tuber Whistle targets Shadowmoon Valley Tuber Node'); + +UPDATE `creature_template` SET `AIName`='SmartAI',`ScriptName`='' WHERE `entry`=21195; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=21195; +DELETE FROM `smart_scripts` WHERE `entryorguid`=21195 AND `source_type`=0; +INSERT INTO `smart_scripts`(`entryorguid`,`id`,`link`,`event_type`,`event_param2`,`action_type`,`action_param1`,`action_param2`,`target_type`,`target_param1`,`target_param2`,`comment`) VALUES +(21195,1,0,34,1,24,0,0, 1,    0,0, 'Domesticated Felboar - Movementinform - Evade (Required for core script npc_shadowmoon_tuber_node)'), +(21195,2,0,34,1,45,1,1,11,21347,5, 'Domesticated Felboar - Movementinform - Set data (Required for core script npc_shadowmoon_tuber_node)'); + +SET @TRIGGER_GUID = 77821; -- 10 +SET @BOAR_GUID    = 77832; -- 8 + +DELETE FROM `creature` WHERE `id`=21347 OR `guid` BETWEEN @TRIGGER_GUID AND @TRIGGER_GUID + 9; +SET @TRIGGER_GUID = @TRIGGER_GUID - 1; +INSERT INTO `creature`(`guid`,`id`,`map`,`phaseMask`,`position_x`,`position_y`,`position_z`)  +SELECT (SELECT @TRIGGER_GUID:=@TRIGGER_GUID+1),21347,`map`,3,`position_x`,`position_y`,`position_z` FROM `gameobject` WHERE `id`=184701 LIMIT 10; + +DELETE FROM `creature` WHERE (`id`=21195 AND `map`=530) OR `guid` BETWEEN @BOAR_GUID AND @BOAR_GUID + 7; +INSERT INTO `creature`(`guid`,`id`,`map`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`curhealth`,`MovementType`) VALUES +(@BOAR_GUID  ,21195,530,-2506.78,1190.22,55.9496,4.15084,300,5,6116,1), +(@BOAR_GUID+1,21195,530,-2486.92,1326.49,64.4239,5.31872,300,5,6116,1), +(@BOAR_GUID+2,21195,530,-2476.05,1284.68,48.0809,1.20087,300,5,5914,1), +(@BOAR_GUID+3,21195,530,-2476.74,1228.44,40.4087,3.72907,300,5,5914,1), +(@BOAR_GUID+4,21195,530,-2549.03,1162.94,78.8947,1.48754,300,5,6116,1), +(@BOAR_GUID+5,21195,530,-2553.91,1186.80,78.5604,1.17575,300,5,6116,1), +(@BOAR_GUID+6,21195,530,-2694.88,1495.00,19.2922,2.33106,300,5,5914,1), +(@BOAR_GUID+7,21195,530,-2706.26,1538.41,16.6343,1.96146,300,5,5914,1); diff --git a/sql/updates/world/2012_09_22_03_world_game_event.sql b/sql/updates/world/2012_09_22_03_world_game_event.sql new file mode 100644 index 00000000000..5e05ba03898 --- /dev/null +++ b/sql/updates/world/2012_09_22_03_world_game_event.sql @@ -0,0 +1,2 @@ +-- Brewfest (372) duration fix by nelegalno +UPDATE `game_event` SET `length` = 21600 WHERE `eventEntry` = 24; diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp index 17cef3ec1a1..e5868117da8 100755 --- a/src/server/game/AI/CreatureAI.cpp +++ b/src/server/game/AI/CreatureAI.cpp @@ -153,13 +153,20 @@ void CreatureAI::EnterEvadeMode()              me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle(), MOTION_SLOT_ACTIVE);          }          else +        { +            // Required to prevent attacking creatures that are evading and cause them to reenter combat +            // Does not apply to MoveFollow +            me->AddUnitState(UNIT_STATE_EVADE);              me->GetMotionMaster()->MoveTargetedHome(); +        }      }      Reset();      if (me->IsVehicle()) // use the same sequence of addtoworld, aireset may remove all summons!          me->GetVehicleKit()->Reset(true); + +    me->SetLastDamagedTime(0);  }  /*void CreatureAI::AttackedBy(Unit* attacker) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 3952f70af71..71976bb3bfd 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -173,6 +173,7 @@ Unit::Unit(bool isWorldObject): WorldObject(isWorldObject)      , m_vehicleKit(NULL)      , m_unitTypeMask(UNIT_MASK_NONE)      , m_HostileRefManager(this) +    , _lastDamagedTime(0)  {  #ifdef _MSC_VER  #pragma warning(default:4355) @@ -11190,6 +11191,10 @@ int32 Unit::ModifyHealth(int32 dVal)      if (dVal == 0)          return 0; +    // Part of Evade mechanics. Only track health lost, not gained. +    if (dVal < 0 && GetTypeId() != TYPEID_PLAYER && !isPet()) +        SetLastDamagedTime(time(NULL)); +      int32 curHealth = (int32)GetHealth();      int32 val = dVal + curHealth; @@ -12134,6 +12139,14 @@ Unit* Creature::SelectVictim()          return target;      } +    // Case where mob is being kited. +    // Mob may not be in range to attack or may have dropped target. In any case, +    //  don't evade if damage received within the last 10 seconds +    // Does not apply to world bosses to prevent kiting to cities +    if (!isWorldBoss() && !GetInstanceId()) +        if (time(NULL) - GetLastDamagedTime() <= MAX_AGGRO_RESET_TIME) +            return target; +      // last case when creature must not go to evade mode:      // 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 diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 7d9088bfabb..73d4cea3ba4 100755 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -263,6 +263,8 @@ enum UnitRename  #define MAX_SPELL_POSSESS       8  #define MAX_SPELL_CONTROL_BAR   10 +#define MAX_AGGRO_RESET_TIME 10 // in seconds +  enum Swing  {      NOSWING                    = 0, @@ -2219,6 +2221,10 @@ class Unit : public WorldObject          // Movement info          Movement::MoveSpline * movespline; +        // Part of Evade mechanics +        time_t GetLastDamagedTime() const { return _lastDamagedTime; } +        void SetLastDamagedTime(time_t val) { _lastDamagedTime = val; } +      protected:          explicit Unit (bool isWorldObject); @@ -2345,6 +2351,8 @@ class Unit : public WorldObject          Spell const* _focusSpell;   ///> Locks the target during spell cast for proper facing          bool _isWalkingBeforeCharm; // Are we walking before we were charmed? + +        time_t _lastDamagedTime; // Part of Evade mechanics  };  namespace Trinity diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 91041384200..57337d3c6a6 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -74,6 +74,9 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto,              // Pet charge effects (Infernal Awakening, Demon Charge)              if (spellproto->SpellVisual[0] == 2816 && spellproto->SpellIconID == 15)                  return DIMINISHING_CONTROLLED_STUN; +            // Frost Tomb +            else if (spellproto->Id == 48400) +                return DIMINISHING_NONE;              // Gnaw              else if (spellproto->Id == 47481)                  return DIMINISHING_CONTROLLED_STUN; @@ -3004,6 +3007,16 @@ void SpellMgr::LoadDbcDataCorrections()          switch (spellInfo->Id)          { +            case 42730:  +                spellInfo->EffectTriggerSpell[EFFECT_1] = 42739; +                break; +            case 59735: +                spellInfo->EffectTriggerSpell[EFFECT_1] = 59736; +                break; +            case 52611: // Summon Skeletons +            case 52612: // Summon Skeletons +                spellInfo->EffectMiscValueB[0] = 64; +                break;              case 40244: // Simon Game Visual              case 40245: // Simon Game Visual              case 40246: // Simon Game Visual diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_eregos.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_eregos.cpp index e68e28be99b..76237fe1890 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/boss_eregos.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_eregos.cpp @@ -160,7 +160,7 @@ public:                  _emeraldVoid = false;              if (me->FindNearestCreature(NPC_AMBER_DRAKE_VEHICLE, 500.0f, true))                  _amberVoid = false; -		} +        }          uint32 GetData(uint32 type)          { diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp index 48667053373..ef17d6c0721 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp @@ -56,13 +56,16 @@ enum Events      EVENT_DARK_SMASH,      EVENT_DREADFUL_ROAR,      EVENT_WOE_STRIKE, -    EVENT_SHADOW_AXE +    EVENT_SHADOW_AXE, +    EVENT_JUST_TRANSFORMED, +    EVENT_SUMMON_BANSHEE  };  enum Phases  {      PHASE_HUMAN = 1,      PHASE_UNDEAD, +    PHASE_EVENT  };  enum Spells @@ -83,7 +86,7 @@ enum Spells      SPELL_WOE_STRIKE                            = 42730,      ENTRY_THROW_TARGET                          = 23996, -    SPELL_SHADOW_AXE_SUMMON                     = 42749 +    SPELL_SHADOW_AXE_SUMMON                     = 42748  };  class boss_ingvar_the_plunderer : public CreatureScript @@ -107,9 +110,6 @@ public:          InstanceScript* instance;          bool bIsUndead; -        bool bEventInProgress; - -        uint32 uiSpawnResTimer;          void Reset()          { @@ -117,7 +117,6 @@ public:                  me->UpdateEntry(MOB_INGVAR_HUMAN);              bIsUndead = false; -            bEventInProgress = false;              me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);              me->SetStandState(UNIT_STAND_STATE_STAND); @@ -130,13 +129,6 @@ public:              events.ScheduleEvent(EVENT_ENRAGE, urand(7,14)*IN_MILLISECONDS, 0, PHASE_HUMAN);              events.ScheduleEvent(EVENT_SMASH, urand(12,17)*IN_MILLISECONDS, 0, PHASE_HUMAN); -            events.ScheduleEvent(EVENT_DARK_SMASH, urand(14,22)*IN_MILLISECONDS, 0, PHASE_UNDEAD); -            events.ScheduleEvent(EVENT_DREADFUL_ROAR, urand(18,21)*IN_MILLISECONDS, 0, PHASE_UNDEAD); -            events.ScheduleEvent(EVENT_WOE_STRIKE, urand(10,14)*IN_MILLISECONDS, 0, PHASE_UNDEAD); -            events.ScheduleEvent(EVENT_SHADOW_AXE, 30*IN_MILLISECONDS, 0, PHASE_UNDEAD); - -            uiSpawnResTimer = 3000; -              if (instance)                  instance->SetData(DATA_INGVAR_EVENT, NOT_STARTED);          } @@ -156,37 +148,34 @@ public:                  me->SetStandState(UNIT_STAND_STATE_DEAD);                  // visuel hack end -                bEventInProgress = true; -                bIsUndead = true; -                events.SetPhase(PHASE_UNDEAD); +                events.SetPhase(PHASE_EVENT); +                events.ScheduleEvent(EVENT_SUMMON_BANSHEE, 3 * IN_MILLISECONDS, 0, PHASE_EVENT);                  DoScriptText(YELL_DEAD_1, me);              } -            if (bEventInProgress) -            { +            if (events.GetPhaseMask() & PHASE_EVENT)                  damage = 0; -            }          }          void StartZombiePhase()          {              bIsUndead = true; -            bEventInProgress = false; -            me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);              me->UpdateEntry(MOB_INGVAR_UNDEAD); -            me->SetInCombatWith(me->getVictim()); -            me->GetMotionMaster()->MoveChase(me->getVictim()); +            events.ScheduleEvent(EVENT_JUST_TRANSFORMED, 2 * IN_MILLISECONDS, 0, PHASE_EVENT);              DoScriptText(YELL_AGGRO_2, me);          }          void EnterCombat(Unit* /*who*/)          { -            DoScriptText(YELL_AGGRO_1, me); +            if (!bIsUndead) +                DoScriptText(YELL_AGGRO_1, me);              if (instance)                  instance->SetData(DATA_INGVAR_EVENT, IN_PROGRESS); + +            me->SetInCombatWithZone();          }          void JustDied(Unit* /*killer*/) @@ -201,6 +190,15 @@ public:              }          } +        void ScheduleSecondPhase() +        { +            events.SetPhase(PHASE_UNDEAD); +            events.ScheduleEvent(EVENT_DARK_SMASH, urand(14,18)*IN_MILLISECONDS, 0, PHASE_UNDEAD); +            events.ScheduleEvent(EVENT_DREADFUL_ROAR, urand(18,22)*IN_MILLISECONDS, 0, PHASE_UNDEAD); +            events.ScheduleEvent(EVENT_WOE_STRIKE, urand(10,14)*IN_MILLISECONDS, 0, PHASE_UNDEAD); +            events.ScheduleEvent(EVENT_SHADOW_AXE, 30*IN_MILLISECONDS, 0, PHASE_UNDEAD); +        } +          void KilledUnit(Unit* /*victim*/)          {              if (bIsUndead) @@ -211,24 +209,9 @@ public:          void UpdateAI(const uint32 diff)          { -            if (!UpdateVictim()) +            if (!UpdateVictim() && !(events.GetPhaseMask() & PHASE_EVENT))                  return; -            if (bEventInProgress) -            { -                if (uiSpawnResTimer) -                { -                    if (uiSpawnResTimer <= diff) -                    { -                        DoCast(me, SPELL_SUMMON_BANSHEE); // Summons directly on caster position -                        // DoCast(me, SPELL_SCOURG_RESURRECTION, true); // Not needed ? -                        uiSpawnResTimer = 0; -                    } else uiSpawnResTimer -= diff; -                } - -                return; -            } -              events.Update(diff);              if (me->HasUnitState(UNIT_STATE_CASTING)) @@ -245,7 +228,7 @@ public:                          break;                      case EVENT_STAGGERING_ROAR:                          DoCast(me, SPELL_STAGGERING_ROAR); -                        events.ScheduleEvent(EVENT_STAGGERING_ROAR, urand(18,21)*IN_MILLISECONDS, 0, PHASE_HUMAN); +                        events.ScheduleEvent(EVENT_STAGGERING_ROAR, urand(18,22)*IN_MILLISECONDS, 0, PHASE_HUMAN);                          break;                      case EVENT_ENRAGE:                          DoCast(me, SPELL_ENRAGE); @@ -253,16 +236,25 @@ public:                          break;                      case EVENT_SMASH:                          DoCastVictim(SPELL_SMASH); -                        events.ScheduleEvent(EVENT_SMASH, urand(12,17)*IN_MILLISECONDS, 0, PHASE_HUMAN); +                        events.ScheduleEvent(EVENT_SMASH, urand(12,16)*IN_MILLISECONDS, 0, PHASE_HUMAN);                          break; +                    case EVENT_JUST_TRANSFORMED: +                        me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); +                        me->SetInCombatWithZone(); +                        me->GetMotionMaster()->MoveChase(me->getVictim()); +                        ScheduleSecondPhase(); +                        return; +                    case EVENT_SUMMON_BANSHEE: +                        DoCast(me, SPELL_SUMMON_BANSHEE); +                        return;                      // PHASE TWO                      case EVENT_DARK_SMASH:                          DoCastVictim(SPELL_DARK_SMASH); -                        events.ScheduleEvent(EVENT_DARK_SMASH, urand(14,22)*IN_MILLISECONDS, 0, PHASE_UNDEAD); +                        events.ScheduleEvent(EVENT_DARK_SMASH, urand(12,16)*IN_MILLISECONDS, 0, PHASE_UNDEAD);                          break;                      case EVENT_DREADFUL_ROAR:                          DoCast(me, SPELL_DREADFUL_ROAR); -                        events.ScheduleEvent(EVENT_DREADFUL_ROAR, urand(18,21)*IN_MILLISECONDS, 0, PHASE_UNDEAD); +                        events.ScheduleEvent(EVENT_DREADFUL_ROAR, urand(18,22)*IN_MILLISECONDS, 0, PHASE_UNDEAD);                          break;                      case EVENT_WOE_STRIKE:                          DoCastVictim(SPELL_WOE_STRIKE); @@ -271,8 +263,7 @@ public:                      case EVENT_SHADOW_AXE:                          if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1))                          { -                            me->SummonCreature(ENTRY_THROW_TARGET, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 2000); -                            DoCast(me, SPELL_SHADOW_AXE_SUMMON); +                            DoCast(target, SPELL_SHADOW_AXE_SUMMON);                          }                          events.ScheduleEvent(EVENT_SHADOW_AXE, 30*IN_MILLISECONDS, 0, PHASE_UNDEAD);                          break; @@ -430,32 +421,34 @@ public:          {          } -        uint32 uiDespawnTimer; -          void Reset()          { -            Unit* target = me->FindNearestCreature(ENTRY_THROW_TARGET, 50); -            if (target) +            if (Creature* target = me->FindNearestCreature(ENTRY_THROW_TARGET, 50.0f))              { -                DoCast(me, SPELL_SHADOW_AXE_DAMAGE);                  float x, y, z;                  target->GetPosition(x, y, z); -                me->GetMotionMaster()->MovePoint(0, x, y, z); +                me->GetMotionMaster()->MoveCharge(x, y, z, 42.0f, 28); +                target->DisappearAndDie(); +            } +            else +            { +                me->DisappearAndDie();              } -            uiDespawnTimer = 7000;          } -        void AttackStart(Unit* /*who*/) {} -        void MoveInLineOfSight(Unit* /*who*/) {} -        void EnterCombat(Unit* /*who*/) {} -        void UpdateAI(const uint32 diff) +        void MovementInform(uint32 type, uint32 id)          { -            if (uiDespawnTimer <= diff) +            if (type == POINT_MOTION_TYPE && id == 28)              { -                me->DealDamage(me, me->GetHealth()); -                me->RemoveCorpse(); -                uiDespawnTimer = 0; -            } else uiDespawnTimer -= diff; +                DoCast(me, SPELL_SHADOW_AXE_DAMAGE); +                me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); +                if (TempSummon* summon = me->ToTempSummon()) +                { +                    summon->UnSummon(10000); +                } +                else +                    me->DisappearAndDie(); +            }          }      };  }; diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp index b987b00fa5b..e718942d091 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp @@ -43,6 +43,9 @@ enum KelsethEncounter      NPC_FROSTTOMB                            = 23965,      NPC_SKELETON                             = 23970, +    NPC_RUNEMAGE                             = 23960, +    NPC_STRATEGIST                           = 23956, +      SAY_START_COMBAT = 1,      SAY_SUMMON_SKELETONS,      SAY_FROST_TOMB, @@ -118,10 +121,7 @@ public:      struct boss_kelesethAI : public BossAI      { -        boss_kelesethAI(Creature* creature) : BossAI(creature, DATA_PRINCEKELESETH_EVENT) -        { -            creature->SetReactState(REACT_DEFENSIVE); -        } +        boss_kelesethAI(Creature* creature) : BossAI(creature, DATA_PRINCEKELESETH_EVENT){}          void Reset()          { @@ -138,12 +138,37 @@ public:              onTheRocks = true;          } -        void EnterCombat(Unit* /*who*/) +        void EnterCombat(Unit* who)          {              me->SetInCombatWithZone();              if (instance)                  instance->SetData(DATA_PRINCEKELESETH_EVENT, IN_PROGRESS);              Talk(SAY_START_COMBAT); + +            if (!who) +                return; + +            std::list<Creature*> runemages; +            me->GetCreatureListWithEntryInGrid(runemages, NPC_RUNEMAGE, 60.0f); +            if (!runemages.empty()) +            { +                for (std::list<Creature*>::iterator itr = runemages.begin(); itr != runemages.end(); ++itr) +                { +                    if ((*itr)->isAlive() && (*itr)->IsWithinLOSInMap(me)) +                        (*itr)->AI()->AttackStart(who); +                } +            } + +            std::list<Creature*> strategists; +            me->GetCreatureListWithEntryInGrid(strategists, NPC_STRATEGIST, 60.0f); +            if (!strategists.empty()) +            { +                for (std::list<Creature*>::iterator itr = strategists.begin(); itr != strategists.end(); ++itr) +                { +                    if ((*itr)->isAlive() && (*itr)->IsWithinLOSInMap(me)) +                        (*itr)->AI()->AttackStart(who); +                } +            }          }          void JustDied(Unit* /*killer*/) @@ -168,10 +193,20 @@ public:              return 0;          } -        void ExecuteEvent(uint32 const eventId) +        void UpdateAI(uint32 const diff)          { -            switch (eventId) +            if (!UpdateVictim()) +                return; + +            events.Update(diff); + +            if (me->HasUnitState(UNIT_STATE_CASTING)) +                return; + +            while (uint32 eventId = events.ExecuteEvent())              { +                switch (eventId) +                {                  case EVENT_SUMMON_SKELETONS:                      Talk(SAY_SUMMON_SKELETONS);                      SummonSkeletons(); @@ -192,7 +227,10 @@ public:                      }                      events.ScheduleEvent(EVENT_FROST_TOMB, urand(14,19)*IN_MILLISECONDS);                      break; +                }              } + +            DoMeleeAttackIfReady();          }          void SummonSkeletons() @@ -225,7 +263,6 @@ public:              events.Reset();              events.ScheduleEvent(EVENT_DECREPIFY, urand(4,6)*IN_MILLISECONDS); -            DoCast(SPELL_BONE_ARMOR);          }          void DamageTaken(Unit* /*done_by*/, uint32 &damage) @@ -278,6 +315,13 @@ public:                          break;                      case EVENT_SHADOW_FISSURE:                          DoCast(me, SPELL_SHADOW_FISSURE, true); +                        if (TempSummon* temp = me->ToTempSummon()) +                        { +                            if (Unit* summoner = temp->GetSummoner()) +                            { +                                DoCast(summoner, SPELL_BONE_ARMOR); +                            } +                        }                          me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);                          me->RemoveFlag(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD);                          me->GetMotionMaster()->MoveChase(me->getVictim()); diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp index be8d60fbeb9..7c977250e79 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp @@ -47,6 +47,7 @@ enum eEnums      SPELL_CHARGE                                = 43651,      SPELL_STONE_STRIKE                          = 48583,      SPELL_SUMMON_SKARVALD_GHOST                 = 48613, +    SPELL_ENRAGE                                = 48193,      MOB_SKARVALD_GHOST                          = 27390,  //Spells of Dalronn and his Ghost      MOB_DALRONN_THE_CONTROLLER                  = 24201, @@ -58,6 +59,20 @@ enum eEnums      MOB_DALRONN_GHOST                           = 27389  }; +class SkarvaldChargePredicate +{ +   public: +      SkarvaldChargePredicate(Unit* unit) : me(unit) {} + +    bool operator() (WorldObject* object) const +    { +        return object->GetDistance2d(me) >= 5.0f && object->GetDistance2d(me) <= 30.0f; +    } + +    private: +        Unit* me; +}; +  class boss_skarvald_the_constructor : public CreatureScript  {  public: @@ -83,6 +98,7 @@ public:          uint32 Response_Timer;          uint32 Check_Timer;          bool Dalronn_isDead; +        bool Enraged;          void Reset()          { @@ -90,6 +106,7 @@ public:              StoneStrike_Timer = 10000;              Dalronn_isDead = false;              Check_Timer = 5000; +            Enraged = false;              ghost = (me->GetEntry() == MOB_SKARVALD_GHOST);              if (!ghost && instance) @@ -116,6 +133,15 @@ public:              }          } +        void DamageTaken(Unit* /*attacker*/, uint32& damage) +        { +            if (!Enraged && !ghost && me->HealthBelowPctDamaged(15, damage)) +            { +                Enraged = true; +                DoCast(me, SPELL_ENRAGE); +            } +        } +          void JustDied(Unit* killer)          {              if (!ghost && instance) @@ -194,7 +220,7 @@ public:              if (Charge_Timer <= diff)              { -                DoCast(SelectTarget(SELECT_TARGET_RANDOM, 1), SPELL_CHARGE); +                DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, SkarvaldChargePredicate(me)), SPELL_CHARGE);                  Charge_Timer = 5000+rand()%5000;              } else Charge_Timer -= diff; @@ -204,7 +230,8 @@ public:                  StoneStrike_Timer = 5000+rand()%5000;              } else StoneStrike_Timer -= diff; -            DoMeleeAttackIfReady(); +            if (!me->HasUnitState(UNIT_STATE_CASTING)) +                DoMeleeAttackIfReady();          }      }; diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp index 2d53e7062eb..35bf7ee0b10 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp @@ -18,6 +18,8 @@  #include "ScriptMgr.h"  #include "ScriptedCreature.h"  #include "utgarde_keep.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h"  uint32 entry_search[3] =  { @@ -164,7 +166,82 @@ public:      };  }; +enum TickingTimeBomb  +{ +    SPELL_TICKING_TIME_BOMB_EXPLODE = 59687 +}; +class spell_ticking_time_bomb : public SpellScriptLoader +{ +    public: +        spell_ticking_time_bomb() : SpellScriptLoader("spell_ticking_time_bomb") { } + +        class spell_ticking_time_bomb_AuraScript : public AuraScript +        { +            PrepareAuraScript(spell_ticking_time_bomb_AuraScript); + +            bool Validate(SpellInfo const* /*spellEntry*/) +            { +                return (bool) sSpellMgr->GetSpellInfo(SPELL_TICKING_TIME_BOMB_EXPLODE); +            } + +            void HandleOnEffectRemove(AuraEffect const* /* aurEff */, AuraEffectHandleModes /* mode */) +            { +                if (GetCaster() == GetTarget()) +                { +                    GetTarget()->CastSpell(GetTarget(), SPELL_TICKING_TIME_BOMB_EXPLODE, true); +                }                 +            } + +            void Register() +            { +                OnEffectRemove += AuraEffectRemoveFn(spell_ticking_time_bomb_AuraScript::HandleOnEffectRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); +            } +        }; + +        AuraScript* GetAuraScript() const +        { +            return new spell_ticking_time_bomb_AuraScript(); +        } +}; + +enum Fixate +{ +    SPELL_FIXATE_TRIGGER = 40415 +}; +class spell_fixate : public SpellScriptLoader +{ +    public: +        spell_fixate() : SpellScriptLoader("spell_fixate") { } + +        class spell_fixate_SpellScript : public SpellScript +        { +            PrepareSpellScript(spell_fixate_SpellScript); + +            bool Validate(SpellInfo const* /*spellEntry*/) +            { +                return (bool) sSpellMgr->GetSpellInfo(SPELL_FIXATE_TRIGGER); +            } + +            void HandleScriptEffect(SpellEffIndex /*effIndex*/) +            { +                // The unit has to cast the taunt on hisself, but we need the original caster for SPELL_AURA_MOD_TAUNT +                GetCaster()->CastSpell(GetCaster(), SPELL_FIXATE_TRIGGER, true, 0, 0, GetHitUnit()->GetGUID()); +            } + +            void Register() +            { +                OnEffectHitTarget += SpellEffectFn(spell_fixate_SpellScript::HandleScriptEffect, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT); +            } +        }; + +        SpellScript* GetSpellScript() const +        { +            return new spell_fixate_SpellScript(); +        } +};  void AddSC_utgarde_keep()  {      new npc_dragonflayer_forge_master(); +    new spell_ticking_time_bomb(); +    new spell_fixate();  } diff --git a/src/server/scripts/Outland/shadowmoon_valley.cpp b/src/server/scripts/Outland/shadowmoon_valley.cpp index 078f8f5a4f0..c84df2ee3d4 100644 --- a/src/server/scripts/Outland/shadowmoon_valley.cpp +++ b/src/server/scripts/Outland/shadowmoon_valley.cpp @@ -1899,6 +1899,96 @@ class spell_unlocking_zuluheds_chains : public SpellScriptLoader          }  }; +enum ShadowMoonTuberEnum +{ +    SPELL_WHISTLE               = 36652, +    SPELL_SHADOWMOON_TUBER      = 36462, + +    NPC_BOAR_ENTRY              = 21195, +    GO_SHADOWMOON_TUBER_MOUND   = 184701, + +    POINT_TUBER                 = 1, +    TYPE_BOAR                   = 1, +    DATA_BOAR                   = 1 +}; + +class npc_shadowmoon_tuber_node : public CreatureScript +{ +public: +    npc_shadowmoon_tuber_node() : CreatureScript("npc_shadowmoon_tuber_node") {} + +    struct npc_shadowmoon_tuber_nodeAI : public ScriptedAI +    { +        npc_shadowmoon_tuber_nodeAI(Creature* creature) : ScriptedAI(creature) {} + +        void Reset() +        { +            tapped = false; +            tuberGUID = 0; +            resetTimer = 60000; +        } + +        void SetData(uint32 id, uint32 data) +        { +            if (id == TYPE_BOAR && data == DATA_BOAR) +            { +                // Spawn chest GO +                DoCast(SPELL_SHADOWMOON_TUBER); + +                // Despawn the tuber +                if (GameObject* tuber = me->FindNearestGameObject(GO_SHADOWMOON_TUBER_MOUND, 5.0f)) +                { +                    tuberGUID = tuber->GetGUID(); +                    // @Workaround: find how to properly despawn the GO +                    tuber->SetPhaseMask(2, true); +                } +            } +        } + +        void SpellHit(Unit* /*caster*/, const SpellInfo* spell) +        { +            if (!tapped && spell->Id == SPELL_WHISTLE) +            { +                if (Creature* boar = me->FindNearestCreature(NPC_BOAR_ENTRY, 30.0f)) +                { +                    // Disable trigger and force nearest boar to walk to him +                    tapped = true; +                    boar->SetWalk(false); +                    boar->GetMotionMaster()->MovePoint(POINT_TUBER, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); +                } +            } +        } + +        void UpdateAI(const uint32 diff) +        { +            if (tapped) +            { +                if (resetTimer <= diff) +                { +                    // Respawn the tuber +                    if (tuberGUID) +                        if (GameObject* tuber = GameObject::GetGameObject(*me, tuberGUID)) +                        // @Workaround: find how to properly respawn the GO +                            tuber->SetPhaseMask(1, true); + +                    Reset(); +                } +                else +                    resetTimer -= diff; +            } +        } +    private: +        bool tapped; +        uint64 tuberGUID; +        uint32 resetTimer; +    }; + +    CreatureAI* GetAI(Creature* creature) const +    { +        return new npc_shadowmoon_tuber_nodeAI(creature); +    } +}; +  void AddSC_shadowmoon_valley()  {      new mob_mature_netherwing_drake(); @@ -1917,4 +2007,5 @@ void AddSC_shadowmoon_valley()      new mob_torloth_the_magnificent();      new npc_enraged_spirit();      new spell_unlocking_zuluheds_chains(); +    new npc_shadowmoon_tuber_node();  }  | 
