diff options
Diffstat (limited to 'src/server/scripts')
32 files changed, 868 insertions, 154 deletions
diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp index b7acfb85f50..039af61c010 100644 --- a/src/server/scripts/Commands/cs_go.cpp +++ b/src/server/scripts/Commands/cs_go.cpp @@ -424,7 +424,7 @@ public: uint32 areaId = id ? (uint32)atoi(id) : player->GetZoneId(); - AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(areaId); + AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(areaId); if (x < 0 || x > 100 || y < 0 || y > 100 || !areaEntry) { @@ -434,7 +434,7 @@ public: } // update to parent zone if exist (client map show only zones without parents) - AreaTableEntry const* zoneEntry = areaEntry->zone ? GetAreaEntryByAreaID(areaEntry->zone) : areaEntry; + AreaTableEntry const* zoneEntry = areaEntry->zone ? sAreaTableStore.LookupEntry(areaEntry->zone) : areaEntry; ASSERT(zoneEntry); Map const* map = sMapMgr->CreateBaseMap(zoneEntry->mapid); diff --git a/src/server/scripts/Commands/cs_group.cpp b/src/server/scripts/Commands/cs_group.cpp index 5e8952ce881..9f2bc86f9c0 100644 --- a/src/server/scripts/Commands/cs_group.cpp +++ b/src/server/scripts/Commands/cs_group.cpp @@ -348,10 +348,10 @@ public: phase = (!p->IsGameMaster() ? p->GetPhaseMask() : -1); uint32 locale = handler->GetSessionDbcLocale(); - AreaTableEntry const* area = GetAreaEntryByAreaID(p->GetAreaId()); + AreaTableEntry const* area = sAreaTableStore.LookupEntry(p->GetAreaId()); if (area) { - AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone); + AreaTableEntry const* zone = sAreaTableStore.LookupEntry(area->zone); if (zone) zoneName = zone->area_name[locale]; } diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp index 4e749d33fcf..61e6acfb4d8 100644 --- a/src/server/scripts/Commands/cs_lookup.cpp +++ b/src/server/scripts/Commands/cs_lookup.cpp @@ -97,9 +97,9 @@ public: wstrToLower(wNamePart); // Search in AreaTable.dbc - for (uint32 areaflag = 0; areaflag < sAreaStore.GetNumRows(); ++areaflag) + for (uint32 i = 0; i < sAreaTableStore.GetNumRows(); ++i) { - AreaTableEntry const* areaEntry = sAreaStore.LookupEntry(areaflag); + AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(i); if (areaEntry) { int locale = handler->GetSessionDbcLocale(); diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 6ae509af443..c70246f7fb5 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -198,8 +198,8 @@ public: uint32 mapId = object->GetMapId(); MapEntry const* mapEntry = sMapStore.LookupEntry(mapId); - AreaTableEntry const* zoneEntry = GetAreaEntryByAreaID(zoneId); - AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(areaId); + AreaTableEntry const* zoneEntry = sAreaTableStore.LookupEntry(zoneId); + AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(areaId); float zoneX = object->GetPositionX(); float zoneY = object->GetPositionY(); @@ -961,7 +961,7 @@ public: uint32 zoneId = player->GetZoneId(); - AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(zoneId); + AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(zoneId); if (!areaEntry || areaEntry->zone !=0) { handler->PSendSysMessage(LANG_COMMAND_GRAVEYARDWRONGZONE, graveyardId, zoneId); @@ -1052,17 +1052,23 @@ public: return false; } - int32 area = GetAreaFlagByAreaID(atoi((char*)args)); - int32 offset = area / 32; + AreaTableEntry const* area = sAreaTableStore.LookupEntry(atoi(args)); + if (!area) + { + handler->SendSysMessage(LANG_BAD_VALUE); + handler->SetSentErrorMessage(true); + return false; + } - if (area<0 || offset >= PLAYER_EXPLORED_ZONES_SIZE) + int32 offset = area->exploreFlag / 32; + if (offset >= PLAYER_EXPLORED_ZONES_SIZE) { handler->SendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); return false; } - uint32 val = uint32((1 << (area % 32))); + uint32 val = uint32((1 << (area->exploreFlag % 32))); uint32 currFields = playerTarget->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset); playerTarget->SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, uint32((currFields | val))); @@ -1083,17 +1089,23 @@ public: return false; } - int32 area = GetAreaFlagByAreaID(atoi((char*)args)); - int32 offset = area / 32; + AreaTableEntry const* area = sAreaTableStore.LookupEntry(atoi(args)); + if (!area) + { + handler->SendSysMessage(LANG_BAD_VALUE); + handler->SetSentErrorMessage(true); + return false; + } - if (area < 0 || offset >= PLAYER_EXPLORED_ZONES_SIZE) + int32 offset = area->exploreFlag / 32; + if (offset >= PLAYER_EXPLORED_ZONES_SIZE) { handler->SendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); return false; } - uint32 val = uint32((1 << (area % 32))); + uint32 val = uint32((1 << (area->exploreFlag % 32))); uint32 currFields = playerTarget->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset); playerTarget->SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, uint32((currFields ^ val))); @@ -1737,12 +1749,12 @@ public: // Position data MapEntry const* map = sMapStore.LookupEntry(mapId); - AreaTableEntry const* area = GetAreaEntryByAreaID(areaId); + AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaId); if (area) { areaName = area->area_name[locale]; - AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone); + AreaTableEntry const* zone = sAreaTableStore.LookupEntry(area->zone); if (zone) zoneName = zone->area_name[locale]; } diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index daf4fe5866a..fbd199b99db 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -43,7 +43,7 @@ struct EnumName #define CREATE_NAMED_ENUM(VALUE) { VALUE, STRINGIZE(VALUE) } #define NPCFLAG_COUNT 24 -#define FLAGS_EXTRA_COUNT 16 +#define FLAGS_EXTRA_COUNT 19 EnumName<NPCFlags, int32> const npcFlagTexts[NPCFLAG_COUNT] = { @@ -162,7 +162,10 @@ EnumName<CreatureFlagsExtra> const flagsExtra[FLAGS_EXTRA_COUNT] = CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_SKILLGAIN), CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_TAUNT_DIMINISH), CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_ALL_DIMINISH), - CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_DUNGEON_BOSS) + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_PLAYER_DAMAGE_REQ), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_DUNGEON_BOSS), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK) }; class npc_commandscript : public CommandScript diff --git a/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp b/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp index b23b9e645d0..b725f421c8f 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp @@ -44,6 +44,13 @@ EndScriptData */ 11 - Nightbane */ +const Position OptionalSpawn[] = +{ + { -10960.981445f, -1940.138428f, 46.178097f, 4.12f }, // Hyakiss the Lurker + { -10899.903320f, -2085.573730f, 49.474449f, 1.38f }, // Rokad the Ravager + { -10945.769531f, -2040.153320f, 49.474438f, 0.077f } // Shadikith the Glider +}; + class instance_karazhan : public InstanceMapScript { public: @@ -64,6 +71,7 @@ public: // 1 - OZ, 2 - HOOD, 3 - RAJ, this never gets altered. m_uiOperaEvent = urand(1, 3); m_uiOzDeathCount = 0; + OptionalBossCount = 0; } uint32 m_auiEncounter[MAX_ENCOUNTER]; @@ -71,6 +79,7 @@ public: uint32 m_uiOperaEvent; uint32 m_uiOzDeathCount; + uint32 OptionalBossCount; ObjectGuid m_uiCurtainGUID; ObjectGuid m_uiStageDoorLeftGUID; @@ -107,6 +116,29 @@ public: } } + void OnUnitDeath(Unit* unit) override + { + Creature* creature = unit->ToCreature(); + if (!creature) + return; + + switch (creature->GetEntry()) + { + case NPC_COLDMIST_WIDOW: + case NPC_COLDMIST_STALKER: + case NPC_SHADOWBAT: + case NPC_VAMPIRIC_SHADOWBAT: + case NPC_GREATER_SHADOWBAT: + case NPC_PHASE_HOUND: + case NPC_DREADBEAST: + case NPC_SHADOWBEAST: + SetData(TYPE_OPTIONAL_BOSS, NOT_STARTED); + break; + default: + break; + } + } + void SetData(uint32 type, uint32 uiData) override { switch (type) @@ -118,7 +150,28 @@ public: m_auiEncounter[1] = uiData; break; case TYPE_MAIDEN: m_auiEncounter[2] = uiData; break; - case TYPE_OPTIONAL_BOSS: m_auiEncounter[3] = uiData; break; + case TYPE_OPTIONAL_BOSS: + m_auiEncounter[3] = uiData; + if (uiData == NOT_STARTED) + { + ++OptionalBossCount; + if (OptionalBossCount == 50) + { + switch (urand(0, 2)) + { + case 0: + instance->SummonCreature(NPC_HYAKISS_THE_LURKER, OptionalSpawn[0]); + break; + case 1: + instance->SummonCreature(NPC_ROKAD_THE_RAVAGER, OptionalSpawn[1]); + break; + case 2: + instance->SummonCreature(NPC_SHADIKITH_THE_GLIDER, OptionalSpawn[2]); + break; + } + } + } + break; case TYPE_OPERA: m_auiEncounter[4] = uiData; if (uiData == DONE) diff --git a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.h b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.h index db68484c4a8..4d86492257c 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.h +++ b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.h @@ -64,4 +64,20 @@ enum OperaEvents EVENT_RAJ = 3 }; +enum MiscCreatures +{ + NPC_HYAKISS_THE_LURKER = 16179, + NPC_ROKAD_THE_RAVAGER = 16181, + NPC_SHADIKITH_THE_GLIDER = 16180, + + // Trash + NPC_COLDMIST_WIDOW = 16171, + NPC_COLDMIST_STALKER = 16170, + NPC_SHADOWBAT = 16173, + NPC_VAMPIRIC_SHADOWBAT = 16175, + NPC_GREATER_SHADOWBAT = 16174, + NPC_PHASE_HOUND = 16178, + NPC_DREADBEAST = 16177, + NPC_SHADOWBEAST = 16176 +}; #endif diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp index b48f0edec25..6386bb50e1a 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp @@ -16,8 +16,10 @@ */ #include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "InstanceScript.h" #include "magisters_terrace.h" +#include "EventMap.h" /* 0 - Selin Fireheart @@ -36,6 +38,8 @@ DoorData const doorData[] = { 0, 0, DOOR_TYPE_ROOM } // END }; +Position const KalecgosSpawnPos = { 164.3747f, -397.1197f, 2.151798f, 1.66219f }; + class instance_magisters_terrace : public InstanceMapScript { public: @@ -93,6 +97,10 @@ class instance_magisters_terrace : public InstanceMapScript case NPC_DELRISSA: DelrissaGUID = creature->GetGUID(); break; + case NPC_KALECGOS: + case NPC_HUMAN_KALECGOS: + KalecgosGUID = creature->GetGUID(); + break; default: break; } @@ -139,6 +147,25 @@ class instance_magisters_terrace : public InstanceMapScript } } + void ProcessEvent(WorldObject* obj, uint32 eventId) override + { + if (eventId == EVENT_SPAWN_KALECGOS) + if (!ObjectAccessor::GetCreature(*obj, KalecgosGUID) && Events.Empty()) + Events.ScheduleEvent(EVENT_SPAWN_KALECGOS, Minutes(1)); + } + + void Update(uint32 diff) override + { + Events.Update(diff); + + if (Events.ExecuteEvent() == EVENT_SPAWN_KALECGOS) + if (Creature* kalecgos = instance->SummonCreature(NPC_KALECGOS, KalecgosSpawnPos)) + { + kalecgos->GetMotionMaster()->MovePath(PATH_KALECGOS_FLIGHT, false); + kalecgos->AI()->Talk(SAY_KALECGOS_SPAWN); + } + } + bool SetBossState(uint32 type, EncounterState state) override { if (!InstanceScript::SetBossState(type, state)) @@ -177,10 +204,12 @@ class instance_magisters_terrace : public InstanceMapScript } protected: + EventMap Events; ObjectGuid SelinGUID; ObjectGuid DelrissaGUID; ObjectGuid KaelStatue[2]; ObjectGuid EscapeOrbGUID; + ObjectGuid KalecgosGUID; uint32 DelrissaDeathCount; }; diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp index e216a024468..5b90ac8ccf4 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp @@ -31,7 +31,8 @@ EndContentData */ #include "ScriptedCreature.h" #include "ScriptedGossip.h" #include "Player.h" -#include "SpellInfo.h" +#include "magisters_terrace.h" +#include "EventMap.h" /*###### ## npc_kalecgos @@ -39,30 +40,29 @@ EndContentData */ enum Spells { - SPELL_TRANSFORM_TO_KAEL = 44670, + SPELL_KALECGOS_TRANSFORM = 44670, + SPELL_TRANSFORM_VISUAL = 24085, + SPELL_CAMERA_SHAKE = 44762, SPELL_ORB_KILL_CREDIT = 46307 }; -enum Creatures +enum MovementPoints { - NPC_KAEL = 24848 //human form entry + POINT_ID_PREPARE_LANDING = 6 }; -enum Misc +enum EventIds { - POINT_ID_LAND = 1 + EVENT_KALECGOS_TRANSFORM = 1, + EVENT_KALECGOS_LANDING = 2 }; -const float afKaelLandPoint[] = {225.045f, -276.236f, -5.434f}; - #define GOSSIP_ITEM_KAEL_1 "Who are you?" #define GOSSIP_ITEM_KAEL_2 "What can we do to assist you?" #define GOSSIP_ITEM_KAEL_3 "What brings you to the Sunwell?" #define GOSSIP_ITEM_KAEL_4 "You're not alone here?" #define GOSSIP_ITEM_KAEL_5 "What would Kil'jaeden want with a mortal woman?" -// This is friendly keal that appear after used Orb. -// If we assume DB handle summon, summon appear somewhere outside the platform where Orb is class npc_kalecgos : public CreatureScript { public: @@ -115,52 +115,46 @@ public: struct npc_kalecgosAI : public ScriptedAI { - npc_kalecgosAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - } + npc_kalecgosAI(Creature* creature) : ScriptedAI(creature) { } - void Initialize() + void MovementInform(uint32 type, uint32 pointId) override { - m_uiTransformTimer = 0; - } - - uint32 m_uiTransformTimer; - - void Reset() override - { - Initialize(); - - // we must assume he appear as dragon somewhere outside the platform of orb, and then move directly to here - if (me->GetEntry() != NPC_KAEL) - me->GetMotionMaster()->MovePoint(POINT_ID_LAND, afKaelLandPoint[0], afKaelLandPoint[1], afKaelLandPoint[2]); - } - - void MovementInform(uint32 uiType, uint32 uiPointId) override - { - if (uiType != POINT_MOTION_TYPE) + if (type != WAYPOINT_MOTION_TYPE) return; - if (uiPointId == POINT_ID_LAND) - m_uiTransformTimer = MINUTE*IN_MILLISECONDS; + if (pointId == POINT_ID_PREPARE_LANDING) + { + me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + me->SetDisableGravity(false); + me->SetHover(false); + events.ScheduleEvent(EVENT_KALECGOS_LANDING, Seconds(2)); + } } - void UpdateAI(uint32 uiDiff) override + void UpdateAI(uint32 diff) override { - if (m_uiTransformTimer) + events.Update(diff); + + switch (events.ExecuteEvent()) { - if (m_uiTransformTimer <= uiDiff) - { + case EVENT_KALECGOS_LANDING: + DoCastAOE(SPELL_CAMERA_SHAKE); + me->SetObjectScale(0.6f); + events.ScheduleEvent(EVENT_KALECGOS_TRANSFORM, Seconds(1)); + break; + case EVENT_KALECGOS_TRANSFORM: DoCast(me, SPELL_ORB_KILL_CREDIT, true); - - // Transform and update entry, now ready for quest/read gossip - DoCast(me, SPELL_TRANSFORM_TO_KAEL, false); - me->UpdateEntry(NPC_KAEL); - - m_uiTransformTimer = 0; - } else m_uiTransformTimer -= uiDiff; + DoCast(me, SPELL_TRANSFORM_VISUAL, false); + DoCast(me, SPELL_KALECGOS_TRANSFORM, false); + me->UpdateEntry(NPC_HUMAN_KALECGOS); + break; + default: + break; } } + + private: + EventMap events; }; }; diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h index 917ad0eb50b..05718dfc1dd 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h @@ -42,7 +42,9 @@ enum CreatureIds { NPC_SELIN = 24723, NPC_DELRISSA = 24560, - NPC_FEL_CRYSTAL = 24722 + NPC_FEL_CRYSTAL = 24722, + NPC_KALECGOS = 24844, + NPC_HUMAN_KALECGOS = 24848 }; enum GameObjectIds @@ -57,4 +59,19 @@ enum GameObjectIds GO_ESCAPE_ORB = 188173 }; +enum InstanceEventIds +{ + EVENT_SPAWN_KALECGOS = 16547 +}; + +enum InstanceText +{ + SAY_KALECGOS_SPAWN = 0 +}; + +enum MovementData +{ + PATH_KALECGOS_FLIGHT = 248440 +}; + #endif diff --git a/src/server/scripts/EasternKingdoms/Uldaman/uldaman.cpp b/src/server/scripts/EasternKingdoms/Uldaman/uldaman.cpp index 622c8f0de01..447dbcd67f9 100644 --- a/src/server/scripts/EasternKingdoms/Uldaman/uldaman.cpp +++ b/src/server/scripts/EasternKingdoms/Uldaman/uldaman.cpp @@ -132,7 +132,10 @@ public: ## at_map_chamber ######*/ -#define QUEST_HIDDEN_CHAMBER 2240 +enum MapChamber +{ + QUEST_HIDDEN_CHAMBER = 2240 +}; class AreaTrigger_at_map_chamber : public AreaTriggerScript { diff --git a/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp b/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp index b1a00f35bb5..a01b93a140b 100644 --- a/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp +++ b/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp @@ -25,7 +25,6 @@ EndScriptData */ /* ContentData npcs_dithers_and_arbington -npc_myranda_the_hag npc_the_scourge_cauldron npc_andorhal_tower EndContentData */ @@ -33,7 +32,6 @@ EndContentData */ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "ScriptedGossip.h" -#include "ScriptedEscortAI.h" #include "Player.h" #include "WorldSession.h" @@ -120,54 +118,6 @@ public: }; /*###### -## npc_myranda_the_hag -######*/ - -enum Myranda -{ - ILLUSION_GOSSIP = 4773, - QUEST_SUBTERFUGE = 5862, - QUEST_IN_DREAMS = 5944, - SPELL_SCARLET_ILLUSION = 17961 -}; - -class npc_myranda_the_hag : public CreatureScript -{ -public: - npc_myranda_the_hag() : CreatureScript("npc_myranda_the_hag") { } - - bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF + 1) - { - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, SPELL_SCARLET_ILLUSION, false); - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(QUEST_SUBTERFUGE) == QUEST_STATUS_COMPLETE && - player->GetQuestStatus(QUEST_IN_DREAMS) != QUEST_STATUS_COMPLETE && - !player->HasAura(SPELL_SCARLET_ILLUSION)) - { - player->ADD_GOSSIP_ITEM_DB(Player::GetDefaultGossipMenuForSource(creature), 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->SEND_GOSSIP_MENU(ILLUSION_GOSSIP, creature->GetGUID()); - return true; - } - else - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - - return true; - } -}; - -/*###### ## npc_the_scourge_cauldron ######*/ @@ -195,7 +145,7 @@ public: me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); //override any database `spawntimesecs` to prevent duplicated summons uint32 rTime = me->GetRespawnDelay(); - if (rTime<600) + if (rTime < 600) me->SetRespawnDelay(600); } @@ -274,7 +224,6 @@ public: } void MoveInLineOfSight(Unit* who) override - { if (!who || who->GetTypeId() != TYPEID_PLAYER) return; @@ -286,14 +235,9 @@ public: }; }; -/*###### -## -######*/ - void AddSC_western_plaguelands() { new npcs_dithers_and_arbington(); - new npc_myranda_the_hag(); new npc_the_scourge_cauldron(); new npc_andorhal_tower(); } diff --git a/src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.cpp b/src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.cpp index 63c56e29414..29a754d5895 100644 --- a/src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.cpp +++ b/src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.cpp @@ -58,6 +58,10 @@ enum Enums SAY_FAREWELL = 5, SAY_ATTACKED = 11, + GOSSIP_OPTION_LET_EVENT_BEGIN = 201, + NPC_TEXT_NARALEX_SLEEPS_AGAIN = 698, + NPC_TEXT_FANGLORDS_ARE_DEAD = 699, + SPELL_MARK_OF_THE_WILD_RANK_2 = 5232, SPELL_SERPENTINE_CLEANSING = 6270, SPELL_NARALEXS_AWAKENING = 6271, @@ -70,10 +74,6 @@ enum Enums NPC_MUTANUS_THE_DEVOURER = 3654, }; -#define GOSSIP_ID_START_1 698 //Naralex sleeps again! -#define GOSSIP_ID_START_2 699 //The fanglords are dead! -#define GOSSIP_ITEM_NARALEX "Let the event begin!" - class npc_disciple_of_naralex : public CreatureScript { public: @@ -116,8 +116,8 @@ public: if ((instance->GetData(TYPE_LORD_COBRAHN) == DONE) && (instance->GetData(TYPE_LORD_PYTHAS) == DONE) && (instance->GetData(TYPE_LADY_ANACONDRA) == DONE) && (instance->GetData(TYPE_LORD_SERPENTIS) == DONE)) { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NARALEX, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->SEND_GOSSIP_MENU(GOSSIP_ID_START_2, creature->GetGUID()); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_OPTION_LET_EVENT_BEGIN, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->SEND_GOSSIP_MENU(NPC_TEXT_FANGLORDS_ARE_DEAD, creature->GetGUID()); if (!instance->GetData(TYPE_NARALEX_YELLED)) { @@ -127,7 +127,7 @@ public: } else { - player->SEND_GOSSIP_MENU(GOSSIP_ID_START_1, creature->GetGUID()); + player->SEND_GOSSIP_MENU(NPC_TEXT_NARALEX_SLEEPS_AGAIN, creature->GetGUID()); } } return true; diff --git a/src/server/scripts/Kalimdor/zone_ashenvale.cpp b/src/server/scripts/Kalimdor/zone_ashenvale.cpp index 52a83c02a8a..50730507b8f 100644 --- a/src/server/scripts/Kalimdor/zone_ashenvale.cpp +++ b/src/server/scripts/Kalimdor/zone_ashenvale.cpp @@ -31,6 +31,7 @@ EndContentData */ #include "ScriptedCreature.h" #include "ScriptedEscortAI.h" #include "Player.h" +#include "SpellScript.h" /*#### # npc_ruul_snowhoof @@ -344,9 +345,42 @@ class go_naga_brazier : public GameObjectScript } }; +enum KingoftheFoulwealdMisc +{ + GO_BANNER = 178205 +}; + +class spell_destroy_karangs_banner : public SpellScriptLoader +{ + public: + spell_destroy_karangs_banner() : SpellScriptLoader("spell_destroy_karangs_banner") { } + + class spell_destroy_karangs_banner_SpellScript : public SpellScript + { + PrepareSpellScript(spell_destroy_karangs_banner_SpellScript); + + void HandleAfterCast() + { + if (GameObject* banner = GetCaster()->FindNearestGameObject(GO_BANNER, GetSpellInfo()->GetMaxRange(true))) + banner->Delete(); + } + + void Register() override + { + AfterCast += SpellCastFn(spell_destroy_karangs_banner_SpellScript::HandleAfterCast); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_destroy_karangs_banner_SpellScript(); + } +}; + void AddSC_ashenvale() { new npc_ruul_snowhoof(); new npc_muglash(); new go_naga_brazier(); + new spell_destroy_karangs_banner(); } diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp index fb5642c6f3b..84d7d92acfe 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp @@ -135,9 +135,9 @@ class boss_general_zarithrian : public CreatureScript Talk(SAY_KILL); } - bool CanAIAttack(Unit const* /*target*/) const override + bool CanAIAttack(Unit const* target) const override { - return (instance->GetBossState(DATA_SAVIANA_RAGEFIRE) == DONE && instance->GetBossState(DATA_BALTHARUS_THE_WARBORN) == DONE); + return (instance->GetBossState(DATA_SAVIANA_RAGEFIRE) == DONE && instance->GetBossState(DATA_BALTHARUS_THE_WARBORN) == DONE && BossAI::CanAIAttack(target)); } void UpdateAI(uint32 diff) override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp index b8e7dcc91d5..f59701b9c25 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp @@ -1222,7 +1222,6 @@ class npc_kinetic_bomb : public CreatureScript _x = 0.f; _y = 0.f; _groundZ = 0.f; - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true); } void Reset() override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp index 7e9083115b8..3ea0de31764 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp @@ -598,7 +598,7 @@ class boss_deathbringer_saurfang : public CreatureScript if (target->GetTransport()) return false; - return true; + return BossAI::CanAIAttack(target); } static uint32 const FightWonValue; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp index 0f721148b72..2db9d206a00 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp @@ -317,14 +317,12 @@ class boss_professor_putricide : public CreatureScript // no possible aura seen in sniff adding the aurastate summon->ModifyAuraState(AURA_STATE_UNKNOWN22, true); summon->CastSpell(summon, SPELL_GASEOUS_BLOAT_PROC, true); - summon->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true); summon->SetReactState(REACT_PASSIVE); break; case NPC_VOLATILE_OOZE: // no possible aura seen in sniff adding the aurastate summon->ModifyAuraState(AURA_STATE_UNKNOWN19, true); summon->CastSpell(summon, SPELL_OOZE_ERUPTION_SEARCH_PERIODIC, true); - summon->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true); summon->SetReactState(REACT_PASSIVE); break; case NPC_CHOKING_GAS_BOMB: diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index 755bbd759e7..a598b09c71b 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -578,7 +578,7 @@ class boss_the_lich_king : public CreatureScript bool CanAIAttack(Unit const* target) const override { // The Lich King must not select targets in frostmourne room if he killed everyone outside - return !target->HasAura(SPELL_IN_FROSTMOURNE_ROOM); + return !target->HasAura(SPELL_IN_FROSTMOURNE_ROOM) && BossAI::CanAIAttack(target); } void EnterEvadeMode(EvadeReason why) override diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp index dbb00fa252e..89868fc7bf2 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp @@ -979,6 +979,9 @@ class go_celestial_planetarium_access : public GameObjectScript bool GossipHello(Player* player) override { + if (go->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE)) + return true; + bool hasKey = true; if (LockEntry const* lock = sLockStore.LookupEntry(go->GetGOInfo()->goober.lockId)) { diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp index 49927d236c1..6dfc3bf01e7 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp @@ -1186,6 +1186,7 @@ class npc_brann_bronzebeard_ulduar_intro : public CreatureScript { if (menuId == GOSSIP_MENU_BRANN_BRONZEBEARD && gossipListId == GOSSIP_OPTION_BRANN_BRONZEBEARD) { + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); player->PlayerTalkClass->SendCloseGossip(); if (Creature* loreKeeper = _instance->GetCreature(DATA_LORE_KEEPER_OF_NORGANNON)) loreKeeper->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); @@ -1238,6 +1239,7 @@ class npc_lorekeeper : public CreatureScript { if (menuId == GOSSIP_MENU_LORE_KEEPER && gossipListId == GOSSIP_OPTION_LORE_KEEPER) { + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); player->PlayerTalkClass->SendCloseGossip(); _instance->instance->LoadGrid(364, -16); // make sure leviathan is loaded @@ -1250,6 +1252,7 @@ class npc_lorekeeper : public CreatureScript { if (Creature* brann = _instance->GetCreature(DATA_BRANN_BRONZEBEARD_INTRO)) { + brann->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); delorah->GetMotionMaster()->MovePoint(0, brann->GetPositionX() - 4, brann->GetPositionY(), brann->GetPositionZ()); /// @todo delorah->AI()->Talk(xxxx, brann->GetGUID()); when reached at branz } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp index df5877d9220..05beacca638 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp @@ -222,7 +222,6 @@ class npc_iron_roots : public CreatureScript { SetCombatMovement(false); - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true); me->ApplySpellImmune(0, IMMUNITY_ID, 49560, true); // Death Grip me->setFaction(14); me->SetReactState(REACT_PASSIVE); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp index 385f7d6a69d..09d95b34521 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp @@ -380,7 +380,6 @@ class npc_saronite_vapors : public CreatureScript { Talk(EMOTE_VAPORS); instance = me->GetInstanceScript(); - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true); me->ApplySpellImmune(0, IMMUNITY_ID, 49560, true); // Death Grip jump effect me->SetReactState(REACT_PASSIVE); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp index 19289b55c36..e694433c614 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp @@ -1634,8 +1634,11 @@ class go_mimiron_hardmode_button : public GameObjectScript public: go_mimiron_hardmode_button() : GameObjectScript("go_mimiron_hardmode_button") { } - bool OnGossipHello(Player* /*player*/, GameObject* go) + bool OnGossipHello(Player* /*player*/, GameObject* go) override { + if (go->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE)) + return true; + InstanceScript* instance = go->GetInstanceScript(); if (!instance) return false; diff --git a/src/server/scripts/Northrend/isle_of_conquest.cpp b/src/server/scripts/Northrend/isle_of_conquest.cpp index baca7e38f43..68121e940c9 100644 --- a/src/server/scripts/Northrend/isle_of_conquest.cpp +++ b/src/server/scripts/Northrend/isle_of_conquest.cpp @@ -206,7 +206,7 @@ class spell_ioc_parachute_ic : public SpellScriptLoader class StartLaunchEvent : public BasicEvent { public: - StartLaunchEvent(Position const& pos, ObjectGuid::LowType lowGuid) : _pos(&pos), _lowGuid(lowGuid) + StartLaunchEvent(Position const& pos, ObjectGuid::LowType lowGuid) : _pos(pos), _lowGuid(lowGuid) { } @@ -218,15 +218,15 @@ class StartLaunchEvent : public BasicEvent player->AddAura(SPELL_LAUNCH_NO_FALLING_DAMAGE, player); // prevents falling damage float speedZ = 10.0f; - float dist = player->GetExactDist2d(_pos); + float dist = player->GetExactDist2d(&_pos); player->ExitVehicle(); - player->GetMotionMaster()->MoveJump(*_pos, dist, speedZ, EVENT_JUMP, true); + player->GetMotionMaster()->MoveJump(_pos, dist, speedZ, EVENT_JUMP, true); return true; } private: - Position const* _pos; + Position _pos; ObjectGuid::LowType _lowGuid; }; diff --git a/src/server/scripts/Northrend/zone_icecrown.cpp b/src/server/scripts/Northrend/zone_icecrown.cpp index 88217cb384e..1e020edd10a 100644 --- a/src/server/scripts/Northrend/zone_icecrown.cpp +++ b/src/server/scripts/Northrend/zone_icecrown.cpp @@ -213,7 +213,6 @@ class npc_tournament_training_dummy : public CreatureScript void Reset() override { me->SetControlled(true, UNIT_STATE_STUNNED); - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true); Initialize(); // Cast Defend spells to max stack size diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 5c3ee1d7f4a..abde43ef952 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -1930,10 +1930,7 @@ class spell_gen_mount : public SpellScriptLoader if (map == 530 || (map == 571 && target->HasSpell(SPELL_COLD_WEATHER_FLYING))) canFly = true; - float x, y, z; - target->GetPosition(x, y, z); - uint32 areaFlag = target->GetBaseMap()->GetAreaFlag(x, y, z); - AreaTableEntry const* area = sAreaStore.LookupEntry(areaFlag); + AreaTableEntry const* area = sAreaTableStore.LookupEntry(target->GetAreaId()); if (!area || (canFly && (area->flags & AREA_FLAG_NO_FLY_ZONE))) canFly = false; diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index 9475da91a77..0abff255e4b 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -29,6 +29,7 @@ #include "SpellAuraEffects.h" #include "SkillDiscovery.h" #include "Battleground.h" +#include "DBCStores.h" // Generic script for handling item dummy effects which trigger another spell. class spell_item_trigger_spell : public SpellScriptLoader @@ -2630,6 +2631,43 @@ public: } }; +class spell_item_toy_train_set_pulse : public SpellScriptLoader +{ +public: + spell_item_toy_train_set_pulse() : SpellScriptLoader("spell_item_toy_train_set_pulse") { } + + class spell_item_toy_train_set_pulse_SpellScript : public SpellScript + { + PrepareSpellScript(spell_item_toy_train_set_pulse_SpellScript); + + void HandleDummy(SpellEffIndex /*index*/) + { + if (Player* target = GetHitUnit()->ToPlayer()) + { + target->HandleEmoteCommand(EMOTE_ONESHOT_TRAIN); + if (EmotesTextSoundEntry const* soundEntry = FindTextSoundEmoteFor(TEXT_EMOTE_TRAIN, target->getRace(), target->getGender())) + target->PlayDistanceSound(soundEntry->SoundId); + } + } + + void HandleTargets(std::list<WorldObject*>& targetList) + { + targetList.remove_if([](WorldObject const* obj) { return obj->GetTypeId() != TYPEID_PLAYER; }); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_item_toy_train_set_pulse_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_item_toy_train_set_pulse_SpellScript::HandleTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ALLY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_item_toy_train_set_pulse_SpellScript(); + } +}; + void AddSC_item_spell_scripts() { // 23074 Arcanite Dragonling @@ -2698,4 +2736,5 @@ void AddSC_item_spell_scripts() new spell_item_chicken_cover(); new spell_item_muisek_vessel(); new spell_item_greatmothers_soulcatcher(); + new spell_item_toy_train_set_pulse(); } diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp index 3ca2db40d65..9b577d4e140 100644 --- a/src/server/scripts/Spells/spell_rogue.cpp +++ b/src/server/scripts/Spells/spell_rogue.cpp @@ -41,6 +41,9 @@ enum RogueSpells SPELL_ROGUE_SHIV_TRIGGERED = 5940, SPELL_ROGUE_TRICKS_OF_THE_TRADE_DMG_BOOST = 57933, SPELL_ROGUE_TRICKS_OF_THE_TRADE_PROC = 59628, + SPELL_ROGUE_HONOR_AMONG_THIEVES = 51698, + SPELL_ROGUE_HONOR_AMONG_THIEVES_PROC = 52916, + SPELL_ROGUE_HONOR_AMONG_THIEVES_2 = 51699 }; // 13877, 33735, (check 51211, 65956) - Blade Flurry @@ -703,6 +706,143 @@ class spell_rog_tricks_of_the_trade_proc : public SpellScriptLoader } }; +// 51698,51700,51701 - Honor Among Thieves +class spell_rog_honor_among_thieves : public SpellScriptLoader +{ +public: + spell_rog_honor_among_thieves() : SpellScriptLoader("spell_rog_honor_among_thieves") { } + + class spell_rog_honor_among_thieves_AuraScript : public AuraScript + { + PrepareAuraScript(spell_rog_honor_among_thieves_AuraScript); + + bool CheckProc(ProcEventInfo& /*eventInfo*/) + { + Unit* caster = GetCaster(); + if (!caster) + return false; + + if (!caster->GetSpellHistory()->HasCooldown(GetSpellInfo()->Effects[EFFECT_0].TriggerSpell)) + return true; + + return false; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + + Unit* caster = GetCaster(); + if (!caster) + return; + + Unit* target = GetTarget(); + target->CastSpell(target, GetSpellInfo()->Effects[EFFECT_0].TriggerSpell, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD), nullptr, aurEff, caster->GetGUID()); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_rog_honor_among_thieves_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_rog_honor_among_thieves_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_rog_honor_among_thieves_AuraScript(); + } +}; + +// 52916 - Honor Among Thieves (Proc) +class spell_rog_honor_among_thieves_proc : public SpellScriptLoader +{ +public: + spell_rog_honor_among_thieves_proc() : SpellScriptLoader("spell_rog_honor_among_thieves_proc") { } + + class spell_rog_honor_among_thieves_proc_SpellScript : public SpellScript + { + PrepareSpellScript(spell_rog_honor_among_thieves_proc_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_HONOR_AMONG_THIEVES_PROC)) + return false; + + return true; + } + + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.clear(); + + Unit* target = GetOriginalCaster(); + if (!target) + return; + + targets.push_back(target); + } + + void HandleBeforeHit() + { + Unit* target = GetHitUnit(); + if (!target) + return; + + /* + * The applied aura has a duration of 8 seconds + * This prevents new applications while its active + * Removing it on each new proc enables the application from different sources (different grouped players) + * and on new procs after the source cooldown is finished (1 second) + */ + if (target->HasAura(GetSpellInfo()->Id)) + target->RemoveAura(GetSpellInfo()->Id); + } + + void TriggerCooldown() + { + Unit* target = GetHitUnit(); + if (!target) + return; + + target->GetSpellHistory()->AddCooldown(GetSpellInfo()->Id, 0, std::chrono::seconds(1)); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_rog_honor_among_thieves_proc_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_CASTER_AREA_PARTY); + BeforeHit += SpellHitFn(spell_rog_honor_among_thieves_proc_SpellScript::HandleBeforeHit); + AfterHit += SpellHitFn(spell_rog_honor_among_thieves_proc_SpellScript::TriggerCooldown); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_rog_honor_among_thieves_proc_SpellScript(); + } + + class spell_rog_honor_among_thieves_proc_AuraScript : public AuraScript + { + PrepareAuraScript(spell_rog_honor_among_thieves_proc_AuraScript); + + void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Player* player = GetTarget()->ToPlayer()) + if (Unit* spellTarget = ObjectAccessor::GetUnit(*player, player->GetTarget())) + player->CastSpell(spellTarget, SPELL_ROGUE_HONOR_AMONG_THIEVES_2, true); + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_rog_honor_among_thieves_proc_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_rog_honor_among_thieves_proc_AuraScript(); + } +}; + void AddSC_rogue_spell_scripts() { new spell_rog_blade_flurry(); @@ -716,4 +856,6 @@ void AddSC_rogue_spell_scripts() new spell_rog_shiv(); new spell_rog_tricks_of_the_trade(); new spell_rog_tricks_of_the_trade_proc(); + new spell_rog_honor_among_thieves(); + new spell_rog_honor_among_thieves_proc(); } diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp index c8b0264995b..41e72b1388b 100644 --- a/src/server/scripts/Spells/spell_shaman.cpp +++ b/src/server/scripts/Spells/spell_shaman.cpp @@ -55,7 +55,8 @@ enum ShamanSpells SPELL_SHAMAN_TOTEM_EARTHBIND_EARTHGRAB = 64695, SPELL_SHAMAN_TOTEM_EARTHBIND_TOTEM = 6474, SPELL_SHAMAN_TOTEM_EARTHEN_POWER = 59566, - SPELL_SHAMAN_TOTEM_HEALING_STREAM_HEAL = 52042 + SPELL_SHAMAN_TOTEM_HEALING_STREAM_HEAL = 52042, + SPELL_SHAMAN_TOTEMIC_MASTERY = 38437 }; enum ShamanSpellIcons @@ -1025,6 +1026,46 @@ class spell_sha_thunderstorm : public SpellScriptLoader } }; +// 38443 - Totemic Mastery (Tier 6 - 2P) +class spell_sha_totemic_mastery : public SpellScriptLoader +{ +public: + spell_sha_totemic_mastery() : SpellScriptLoader("spell_sha_totemic_mastery") { } + + class spell_sha_totemic_mastery_AuraScript : public AuraScript + { + PrepareAuraScript(spell_sha_totemic_mastery_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_TOTEMIC_MASTERY)) + return false; + return true; + } + + void HandleDummy(AuraEffect const* /*aurEff*/) + { + Unit* target = GetTarget(); + for (uint8 i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i) + if (!target->m_SummonSlot[i]) + return; + + target->CastSpell(target, SPELL_SHAMAN_TOTEMIC_MASTERY, true); + PreventDefaultAction(); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_sha_totemic_mastery_AuraScript::HandleDummy, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_sha_totemic_mastery_AuraScript(); + } +}; + void AddSC_shaman_spell_scripts() { new spell_sha_ancestral_awakening_proc(); @@ -1048,4 +1089,5 @@ void AddSC_shaman_spell_scripts() new spell_sha_mana_tide_totem(); new spell_sha_sentry_totem(); new spell_sha_thunderstorm(); + new spell_sha_totemic_mastery(); } diff --git a/src/server/scripts/World/go_scripts.cpp b/src/server/scripts/World/go_scripts.cpp index ef4a2b0e32f..b90839f50c5 100644 --- a/src/server/scripts/World/go_scripts.cpp +++ b/src/server/scripts/World/go_scripts.cpp @@ -41,6 +41,7 @@ go_tadpole_cage go_amberpine_outhouse go_hive_pod go_veil_skith_cage +go_toy_train_set EndContentData */ #include "ScriptMgr.h" @@ -1196,6 +1197,48 @@ public: } }; + +enum ToyTrainSpells +{ + SPELL_TOY_TRAIN_PULSE = 61551, +}; + +class go_toy_train_set : public GameObjectScript +{ + public: + go_toy_train_set() : GameObjectScript("go_toy_train_set") { } + + struct go_toy_train_setAI : public GameObjectAI + { + go_toy_train_setAI(GameObject* go) : GameObjectAI(go), _pulseTimer(3 * IN_MILLISECONDS) { } + + void UpdateAI(uint32 diff) override + { + if (diff < _pulseTimer) + _pulseTimer -= diff; + else + { + go->CastSpell(nullptr, SPELL_TOY_TRAIN_PULSE, true); + _pulseTimer = 6 * IN_MILLISECONDS; + } + } + + // triggered on wrecker'd + void DoAction(int32 /*action*/) override + { + go->Delete(); + } + + private: + uint32 _pulseTimer; + }; + + GameObjectAI* GetAI(GameObject* go) const override + { + return new go_toy_train_setAI(go); + } +}; + void AddSC_go_scripts() { new go_cat_figurine(); @@ -1231,4 +1274,5 @@ void AddSC_go_scripts() new go_veil_skith_cage(); new go_frostblade_shrine(); new go_midsummer_bonfire(); + new go_toy_train_set(); } diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index 16b95e555bb..56d48949fac 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -38,6 +38,7 @@ npc_snake_trap_serpents 80% AI for snakes that summoned by Snake Trap npc_shadowfiend 100% restore 5% of owner's mana when shadowfiend die from damage npc_locksmith 75% list of keys needs to be confirmed npc_firework 100% NPC's summoned by rockets and rocket clusters, for making them cast visual +npc_train_wrecker 100% Wind-Up Train Wrecker that kills train set EndContentData */ #include "ScriptMgr.h" @@ -56,6 +57,7 @@ EndContentData */ #include "SpellHistory.h" #include "SpellAuras.h" #include "Pet.h" +#include "PetAI.h" #include "CreatureTextMgr.h" #include "SmartAI.h" @@ -519,6 +521,67 @@ public: }; /*###### +## npc_torch_tossing_target_bunny_controller +######*/ + +enum TorchTossingTarget +{ + NPC_TORCH_TOSSING_TARGET_BUNNY = 25535, + SPELL_TARGET_INDICATOR = 45723 +}; + +class npc_torch_tossing_target_bunny_controller : public CreatureScript +{ +public: + npc_torch_tossing_target_bunny_controller() : CreatureScript("npc_torch_tossing_target_bunny_controller") { } + + struct npc_torch_tossing_target_bunny_controllerAI : public ScriptedAI + { + npc_torch_tossing_target_bunny_controllerAI(Creature* creature) : ScriptedAI(creature) + { + _targetTimer = 3000; + } + + ObjectGuid DoSearchForTargets(ObjectGuid lastTargetGUID) + { + std::list<Creature*> targets; + me->GetCreatureListWithEntryInGrid(targets, NPC_TORCH_TOSSING_TARGET_BUNNY, 60.0f); + targets.remove_if([lastTargetGUID](Creature* creature) { return creature->GetGUID() == lastTargetGUID; }); + + if (!targets.empty()) + { + _lastTargetGUID = Trinity::Containers::SelectRandomContainerElement(targets)->GetGUID(); + + return _lastTargetGUID; + } + return ObjectGuid::Empty; + } + + void UpdateAI(uint32 diff) override + { + if (_targetTimer < diff) + { + if (Unit* target = ObjectAccessor::GetUnit(*me, DoSearchForTargets(_lastTargetGUID))) + target->CastSpell(target, SPELL_TARGET_INDICATOR, true); + + _targetTimer = 3000; + } + else + _targetTimer -= diff; + } + + private: + uint32 _targetTimer; + ObjectGuid _lastTargetGUID; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_torch_tossing_target_bunny_controllerAI(creature); + } +}; + +/*###### ## Triage quest ######*/ @@ -1422,7 +1485,6 @@ public: void Reset() override { me->SetControlled(true, UNIT_STATE_STUNNED);//disable rotate - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);//imune to knock aways like blast wave _events.Reset(); _damageTimes.clear(); @@ -2387,12 +2449,289 @@ class npc_stable_master : public CreatureScript } }; +enum TrainWrecker +{ + GO_TOY_TRAIN = 193963, + SPELL_TOY_TRAIN_PULSE = 61551, + SPELL_WRECK_TRAIN = 62943, + ACTION_WRECKED = 1, + EVENT_DO_JUMP = 1, + EVENT_DO_FACING = 2, + EVENT_DO_WRECK = 3, + EVENT_DO_DANCE = 4, + MOVEID_CHASE = 1, + MOVEID_JUMP = 2 +}; +class npc_train_wrecker : public CreatureScript +{ + public: + npc_train_wrecker() : CreatureScript("npc_train_wrecker") { } + + struct npc_train_wreckerAI : public NullCreatureAI + { + npc_train_wreckerAI(Creature* creature) : NullCreatureAI(creature), _isSearching(true), _nextAction(0), _timer(1 * IN_MILLISECONDS) { } + + GameObject* VerifyTarget() const + { + if (GameObject* target = ObjectAccessor::GetGameObject(*me, _target)) + return target; + me->HandleEmoteCommand(EMOTE_ONESHOT_RUDE); + me->DespawnOrUnsummon(3 * IN_MILLISECONDS); + return nullptr; + } + + void UpdateAI(uint32 diff) override + { + if (_isSearching) + { + if (diff < _timer) + _timer -= diff; + else + { + if (GameObject* target = me->FindNearestGameObject(GO_TOY_TRAIN, 15.0f)) + { + _isSearching = false; + _target = target->GetGUID(); + me->SetWalk(true); + me->GetMotionMaster()->MovePoint(MOVEID_CHASE, target->GetNearPosition(3.0f, target->GetAngle(me))); + } + else + _timer = 3 * IN_MILLISECONDS; + } + } + else + { + switch (_nextAction) + { + case EVENT_DO_JUMP: + if (GameObject* target = VerifyTarget()) + me->GetMotionMaster()->MoveJump(*target, 5.0, 10.0, MOVEID_JUMP); + _nextAction = 0; + break; + case EVENT_DO_FACING: + if (GameObject* target = VerifyTarget()) + { + me->SetFacingTo(target->GetOrientation()); + me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACK1H); + _timer = 1.5 * IN_MILLISECONDS; + _nextAction = EVENT_DO_WRECK; + } + else + _nextAction = 0; + break; + case EVENT_DO_WRECK: + if (diff < _timer) + { + _timer -= diff; + break; + } + if (GameObject* target = VerifyTarget()) + { + me->CastSpell(target, SPELL_WRECK_TRAIN, false); + target->AI()->DoAction(ACTION_WRECKED); + _timer = 2 * IN_MILLISECONDS; + _nextAction = EVENT_DO_DANCE; + } + else + _nextAction = 0; + break; + case EVENT_DO_DANCE: + if (diff < _timer) + { + _timer -= diff; + break; + } + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_DANCE); + me->DespawnOrUnsummon(5 * IN_MILLISECONDS); + _nextAction = 0; + break; + default: + break; + } + } + } + + void MovementInform(uint32 /*type*/, uint32 id) override + { + if (id == MOVEID_CHASE) + _nextAction = EVENT_DO_JUMP; + else if (id == MOVEID_JUMP) + _nextAction = EVENT_DO_FACING; + } + + private: + bool _isSearching; + uint8 _nextAction; + uint32 _timer; + ObjectGuid _target; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_train_wreckerAI(creature); + } +}; + +enum EgbertMisc +{ + EVENT_MOVE_POS = 1, + EVENT_RETURN = 2 +}; + +class npc_egbert : public CreatureScript +{ +public: + npc_egbert() : CreatureScript("npc_egbert") {} + + struct npc_egbertAI : public PetAI + { + npc_egbertAI(Creature* creature) : PetAI(creature) + { + if (Unit* owner = me->GetCharmerOrOwner()) + if (owner->GetMap()->GetEntry()->addon > 1) + me->SetCanFly(true); + } + + void Reset() override + { + _events.Reset(); + _events.ScheduleEvent(EVENT_MOVE_POS, urandms(1, 20)); + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_MOVE_POS: + if (Unit* owner = me->GetCharmerOrOwner()) + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(0, owner->GetPositionX() + frand(-30.0f, 30.0f), owner->GetPositionY() + frand(-30.0f, 30.0f), owner->GetPositionZ()); + } + _events.ScheduleEvent(EVENT_RETURN, urandms(3, 4)); + break; + case EVENT_RETURN: + if (Unit* owner = me->GetCharmerOrOwner()) + me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle()); + _events.ScheduleEvent(EVENT_MOVE_POS, urandms(1, 20)); + break; + default: + break; + } + } + } + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_egbertAI(creature); + } +}; + +enum PandarenMonkMisc +{ + SPELL_PANDAREN_MONK = 69800, + EVENT_FOCUS = 1, + EVENT_EMOTE = 2, + EVENT_FOLLOW = 3, + EVENT_DRINK = 4 +}; + +class npc_pandaren_monk : public CreatureScript +{ +public: + npc_pandaren_monk() : CreatureScript("npc_pandaren_monk") {} + + struct npc_pandaren_monkAI : public NullCreatureAI + { + npc_pandaren_monkAI(Creature* creature) : NullCreatureAI(creature) { } + + void Reset() override + { + _events.Reset(); + _events.ScheduleEvent(EVENT_FOCUS, 1000); + } + + void EnterEvadeMode(EvadeReason why) override + { + if (!_EnterEvadeMode(why)) + return; + + Reset(); + } + + void ReceiveEmote(Player* /*player*/, uint32 emote) override + { + me->InterruptSpell(CURRENT_CHANNELED_SPELL); + me->StopMoving(); + + switch (emote) + { + case TEXT_EMOTE_BOW: + _events.ScheduleEvent(EVENT_FOCUS, 1000); + break; + case TEXT_EMOTE_DRINK: + _events.ScheduleEvent(EVENT_DRINK, 1000); + break; + } + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + if (Unit* owner = me->GetCharmerOrOwner()) + if (!me->IsWithinDist(owner, 30.f)) + me->InterruptSpell(CURRENT_CHANNELED_SPELL); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_FOCUS: + if (Unit* owner = me->GetCharmerOrOwner()) + me->SetFacingToObject(owner); + _events.ScheduleEvent(EVENT_EMOTE, 1000); + break; + case EVENT_EMOTE: + me->HandleEmoteCommand(EMOTE_ONESHOT_BOW); + _events.ScheduleEvent(EVENT_FOLLOW, 1000); + break; + case EVENT_FOLLOW: + if (Unit* owner = me->GetCharmerOrOwner()) + me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + break; + case EVENT_DRINK: + me->CastSpell(me, SPELL_PANDAREN_MONK, false); + break; + default: + break; + } + } + } + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_pandaren_monkAI(creature); + } +}; + void AddSC_npcs_special() { new npc_air_force_bots(); new npc_lunaclaw_spirit(); new npc_chicken_cluck(); new npc_dancing_flames(); + new npc_torch_tossing_target_bunny_controller(); new npc_doctor(); new npc_injured_patient(); new npc_garments_of_quests(); @@ -2410,4 +2749,7 @@ void AddSC_npcs_special() new npc_spring_rabbit(); new npc_imp_in_a_ball(); new npc_stable_master(); + new npc_train_wrecker(); + new npc_egbert(); + new npc_pandaren_monk(); } |
