diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp index 4224aef..5b8ac70 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp @@ -1,5 +1,5 @@ - /* - * Copyright (C) 2008-2018 TrinityCore +/* + * This file is part of the DestinyCore Project. See AUTHORS file for Copyright information * * 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 @@ -15,6 +15,13 @@ * with this program. If not, see . */ +// Nalorakk n'avait qu'une coquille de script : il frappait en melee et rien d'autre, +// ni sorts ni changement de forme. Le combat est ici ecrit a partir du script amont +// TrinityCore, en gardant NOTRE numerotation de creature_text (0-11). +// Ce qui n'est pas porte : les quatre vagues de trolls qui l'annoncent dans la rampe. +// L'amont les pilote par des spawn groups et des chemins de waypoints que ce core +// n'a pas (pas de table spawn_group) -- cela demanderait de recreer les donnees. + #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "zulaman.h" @@ -37,10 +44,33 @@ enum Says enum Spells { + // Forme troll + SPELL_BRUTAL_SWIPE = 42384, + SPELL_MANGLE = 42389, + SPELL_SURGE = 44019, + + // Forme d'ours + SPELL_LACERATING_SLASH = 42395, + SPELL_REND_FLESH = 42397, + SPELL_DEAFENING_ROAR = 42398, + + // Communs + SPELL_SHAPE_OF_THE_BEAR = 42377, + SPELL_BERSERK = 45078 }; enum Events { + EVENT_BRUTAL_SWIPE = 1, + EVENT_MANGLE, + EVENT_SURGE, + + EVENT_LACERATING_SLASH, + EVENT_REND_FLESH, + EVENT_DEAFENING_ROAR, + + EVENT_SHAPESHIFT, + EVENT_BERSERK }; class boss_nalorakk : public CreatureScript @@ -51,17 +81,23 @@ class boss_nalorakk : public CreatureScript struct boss_nalorakkAI : public BossAI { - boss_nalorakkAI(Creature* creature) : BossAI(creature, DATA_NALORAKK) { } + boss_nalorakkAI(Creature* creature) : BossAI(creature, DATA_NALORAKK), _bearForm(false) { } void Reset() override { _Reset(); + _bearForm = false; + me->RemoveAurasDueToSpell(SPELL_SHAPE_OF_THE_BEAR); } void EnterCombat(Unit* /*who*/) override { Talk(SAY_AGGRO); _EnterCombat(); + + ScheduleTrollEvents(); + events.ScheduleEvent(EVENT_SHAPESHIFT, 45000); + events.ScheduleEvent(EVENT_BERSERK, 600000); } void JustDied(Unit* /*killer*/) override @@ -76,6 +112,30 @@ class boss_nalorakk : public CreatureScript Talk(SAY_PLAYER_KILL); } + void ScheduleTrollEvents() + { + events.ScheduleEvent(EVENT_BRUTAL_SWIPE, urand(10000, 20000)); + events.ScheduleEvent(EVENT_MANGLE, urand(15000, 20000)); + events.ScheduleEvent(EVENT_SURGE, urand(20000, 25000)); + } + + void ScheduleBearEvents() + { + events.ScheduleEvent(EVENT_LACERATING_SLASH, urand(10000, 15000)); + events.ScheduleEvent(EVENT_REND_FLESH, urand(12000, 18000)); + events.ScheduleEvent(EVENT_DEAFENING_ROAR, urand(20000, 25000)); + } + + void CancelFormEvents() + { + events.CancelEvent(EVENT_BRUTAL_SWIPE); + events.CancelEvent(EVENT_MANGLE); + events.CancelEvent(EVENT_SURGE); + events.CancelEvent(EVENT_LACERATING_SLASH); + events.CancelEvent(EVENT_REND_FLESH); + events.CancelEvent(EVENT_DEAFENING_ROAR); + } + void UpdateAI(uint32 diff) override { if (!UpdateVictim()) @@ -85,19 +145,76 @@ class boss_nalorakk : public CreatureScript if (me->HasUnitState(UNIT_STATE_CASTING)) return; - /* + while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { + case EVENT_BRUTAL_SWIPE: + DoCastVictim(SPELL_BRUTAL_SWIPE); + events.ScheduleEvent(EVENT_BRUTAL_SWIPE, urand(10000, 20000)); + break; + case EVENT_MANGLE: + DoCastVictim(SPELL_MANGLE); + events.ScheduleEvent(EVENT_MANGLE, urand(15000, 20000)); + break; + case EVENT_SURGE: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(me))) + { + Talk(SAY_SURGE); + Talk(EMOTE_SURGE, target); + DoCast(target, SPELL_SURGE); + } + events.ScheduleEvent(EVENT_SURGE, urand(20000, 25000)); + break; + case EVENT_LACERATING_SLASH: + DoCastVictim(SPELL_LACERATING_SLASH); + events.ScheduleEvent(EVENT_LACERATING_SLASH, urand(10000, 15000)); + break; + case EVENT_REND_FLESH: + DoCastVictim(SPELL_REND_FLESH); + events.ScheduleEvent(EVENT_REND_FLESH, urand(12000, 18000)); + break; + case EVENT_DEAFENING_ROAR: + DoCast(me, SPELL_DEAFENING_ROAR); + events.ScheduleEvent(EVENT_DEAFENING_ROAR, urand(20000, 25000)); + break; + case EVENT_SHAPESHIFT: + CancelFormEvents(); + _bearForm = !_bearForm; + + if (_bearForm) + { + Talk(SAY_BEAR); + Talk(EMOTE_BEAR); + DoCast(me, SPELL_SHAPE_OF_THE_BEAR); + ScheduleBearEvents(); + events.ScheduleEvent(EVENT_SHAPESHIFT, 45000); + } + else + { + Talk(SAY_TROLL); + me->RemoveAurasDueToSpell(SPELL_SHAPE_OF_THE_BEAR); + ScheduleTrollEvents(); + events.ScheduleEvent(EVENT_SHAPESHIFT, 45000); + } + break; + case EVENT_BERSERK: + DoCast(me, SPELL_BERSERK); + break; default: break; } + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; } - */ DoMeleeAttackIfReady(); } + + private: + bool _bearForm; }; CreatureAI* GetAI(Creature* creature) const override diff --git a/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp b/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp index c91d4d9..4d1ad5f 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp @@ -20,10 +20,27 @@ #include "GameObject.h" #include "InstanceScript.h" #include "Map.h" +#include "Player.h" #include "ScriptedCreature.h" #include "WorldStatePackets.h" #include "zulaman.h" +// Les quatre captifs liberes par la course contre la montre. Chacun apparait la +// ou son boss vient de tomber et remet un coffre de recompense quand on lui parle. +struct HostageInfoEntry +{ + uint32 Npc; + float X, Y, Z, O; +}; + +static HostageInfoEntry const HostageInfo[4] = +{ + { 23790, -57.0f, 1343.0f, 40.77f, 3.2f }, // Tanzar - ours (Nalorakk) + { 23999, 400.0f, 1414.0f, 74.36f, 3.3f }, // Harkor - aigle (Akil'zon) + { 24001, -35.0f, 1134.0f, 18.71f, 1.9f }, // Ashli - dragonhalc (Jan'alai) + { 24024, 413.0f, 1117.0f, 6.32f, 3.1f } // Kraz - lynx (Halazzi) +}; + class instance_zulaman : public InstanceMapScript { public: @@ -139,6 +156,28 @@ class instance_zulaman : public InstanceMapScript return ObjectGuid::Empty; } + // Rien n'invoquait les captifs : la course contre la montre se deroulait + // jusqu'au bout sans que personne n'apparaisse, donc sans recompense. + void SummonHostage(uint8 num) + { + if (ZulAmanState != IN_PROGRESS) + return; + + Map::PlayerList const& playerList = instance->GetPlayers(); + if (playerList.isEmpty()) + return; + + if (Player* player = playerList.begin()->GetSource()) + { + HostageInfoEntry const& hostageInfo = HostageInfo[num]; + if (Creature* hostage = player->SummonCreature(hostageInfo.Npc, hostageInfo.X, hostageInfo.Y, hostageInfo.Z, hostageInfo.O, TEMPSUMMON_DEAD_DESPAWN)) + { + hostage->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + hostage->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + } + } + void SetData(uint32 type, uint32 data) override { switch (type) @@ -202,12 +241,21 @@ class instance_zulaman : public InstanceMapScript switch (type) { case DATA_AKILZON: + if (state == DONE) + SummonHostage(1); break; case DATA_NALORAKK: + if (state == DONE) + SummonHostage(0); break; case DATA_JANALAI: + if (state == DONE) + SummonHostage(2); break; case DATA_HALAZZI: + if (state == DONE) + SummonHostage(3); + break; case DATA_HEXLORD: case DATA_DAAKARA: break; diff --git a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp index fca2d98..a7a192c 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp @@ -250,8 +250,73 @@ class spell_banging_the_gong : public SpellScriptLoader } }; +// Tanzar, Harkor, Ashli et Kraz : les captifs liberes par la course contre la +// montre. Ils sont invoques par l'instance a la mort de leur boss ; leur seule +// raison d'etre est de remettre le coffre de recompense quand on leur parle. +// Rien ne les scriptait, donc meme invoques ils n'auraient rien donne. +class npc_zulaman_hostage : public CreatureScript +{ +public: + npc_zulaman_hostage() : CreatureScript("npc_zulaman_hostage") { } + + enum Hostages + { + NPC_TANZAR = 23790, + NPC_HARKOR = 23999, + NPC_ASHLI = 24001, + NPC_KRAZ = 24024, + + GO_HAZLEKS_TRUNK = 186648, // Tanzar + GO_BAKKALZUS_SATCHEL = 187021, // Harkor + GO_KASHAS_BAG = 186672, // Ashli + GO_NORKANIS_PACKAGE = 186667, // Kraz + + ACTION_FREE_HOSTAGE = GOSSIP_ACTION_INFO_DEF + 1 + }; + + static uint32 ChestForHostage(uint32 entry) + { + switch (entry) + { + case NPC_TANZAR: return GO_HAZLEKS_TRUNK; + case NPC_HARKOR: return GO_BAKKALZUS_SATCHEL; + case NPC_ASHLI: return GO_KASHAS_BAG; + case NPC_KRAZ: return GO_NORKANIS_PACKAGE; + default: return 0; + } + } + + bool OnGossipHello(Player* player, Creature* creature) override + { + AddGossipItemFor(player, GOSSIP_ICON_CHAT, "Vous etes libre ! Partez d'ici !", GOSSIP_SENDER_MAIN, ACTION_FREE_HOSTAGE); + SendGossipMenuFor(player, player->GetGossipTextId(creature), creature->GetGUID()); + return true; + } + + bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override + { + CloseGossipMenuFor(player); + + if (action != ACTION_FREE_HOSTAGE) + return true; + + // Un seul coffre par captif, quel que soit le nombre de joueurs qui lui parlent. + if (!creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP)) + return true; + + creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + if (uint32 chest = ChestForHostage(creature->GetEntry())) + creature->SummonGameObject(chest, creature->GetPositionX() - 2.0f, creature->GetPositionY(), + creature->GetPositionZ(), 0.0f, QuaternionData(), WEEK); + + return true; + } +}; + void AddSC_zulaman() { + new npc_zulaman_hostage(); new npc_voljin_zulaman(); new spell_banging_the_gong(); }