diff --git a/sql/scriptdev2/scriptdev2.sql b/sql/scriptdev2/scriptdev2.sql index d321d51829a..f62d70e1de5 100644 --- a/sql/scriptdev2/scriptdev2.sql +++ b/sql/scriptdev2/scriptdev2.sql @@ -570,6 +570,8 @@ UPDATE gameobject_template SET ScriptName='go_defias_cannon' WHERE entry=16398; UPDATE creature_template SET ScriptName='npc_aged_dying_ancient_kodo' WHERE entry IN (4700, 4701, 4702, 11627); UPDATE creature_template SET ScriptName='npc_dalinda_malem' WHERE entry=5644; UPDATE creature_template SET ScriptName='npc_melizza_brimbuzzle' WHERE entry=12277; +UPDATE creature_template SET ScriptName='npc_cork_gizelton' WHERE entry=11625; +UPDATE creature_template SET ScriptName='npc_rigger_gizelton' WHERE entry=11626; /* DIRE MAUL */ UPDATE instance_template SET ScriptName='instance_dire_maul' WHERE map=429; @@ -2914,7 +2916,15 @@ INSERT INTO script_texts (entry,content_default,sound,type,language,emote,commen (-1001187,'Gah! I spent too much time in that weak little shell.',14426,1,0,0,'malganis_icecrown SAY_TRANSFORM'), (-1001188,'Kirel narak! I am Mal\'Ganis. I AM ETERNAL!',14427,1,0,0,'malganis_icecrown SAY_20_HP'), (-1001189,'ENOUGH! I waste my time here. I must gather my strength on the homeworld.',14428,1,0,0,'malganis_icecrown SAY_DEFEATED'), -(-1001190,'You\'ll never defeat the Lich King without my forces. I\'ll have my revenge... on him AND you!',14429,1,0,0,'malganis_icecrown SAY_ESCAPE'); +(-1001190,'You\'ll never defeat the Lich King without my forces. I\'ll have my revenge... on him AND you!',14429,1,0,0,'malganis_icecrown SAY_ESCAPE'), + +(-1001191,'Hey, you call yourself a body guard? Get to work and protect us...',0,0,0,0,'SAY_CORK_AMBUSH1'), +(-1001192,'Mister body guard, are you going to earn your money or what?',0,0,0,0,'SAY_CORK_AMBUSH2'), +(-1001193,'You\'re fired! I mean, help!',0,0,0,0,'SAY_CORK_AMBUSH3'), +(-1001194,'Blast those stupid centaurs! Sigh - well, it seems you kept your bargain. Up the road you shall find Smeed Scrabblescrew, he has your money.',0,0,0,1,'SAY_CORK_END'), +(-1001195,'Eeck! Demons hungry for the kodos!',0,0,0,0,'SAY_RIGGER_AMBUSH1'), +(-1001196,'What am I paying you for? The kodos are nearly dead!',0,0,0,0,'SAY_RIGGER_AMBUSH2'), +(-1001197,'Wow! We did it... not sure why we thought we needed the likes of you. Nevertheless, speak with Smeed Srablescrew; he will give you your earnings!',0,0,0,0,'SAY_RIGGER_END'); -- -1 033 000 SHADOWFANG KEEP INSERT INTO script_texts (entry,content_default,sound,type,language,emote,comment) VALUES diff --git a/src/scriptdev2/scripts/kalimdor/desolace.cpp b/src/scriptdev2/scripts/kalimdor/desolace.cpp old mode 100644 new mode 100755 index 3c3f6f2cedb..deb63e6938a --- a/src/scriptdev2/scripts/kalimdor/desolace.cpp +++ b/src/scriptdev2/scripts/kalimdor/desolace.cpp @@ -17,7 +17,7 @@ /* ScriptData SDName: Desolace SD%Complete: 100 -SDComment: Quest support: 1440, 5561, 6132 +SDComment: Quest support: 1440, 5561, 5821, 5943, 6132 SDCategory: Desolace EndScriptData */ @@ -392,6 +392,281 @@ bool QuestAccept_npc_melizza_brimbuzzle(Player* pPlayer, Creature* pCreature, co return true; } +/*###### +## npc_cork_gizelton +######*/ + +enum +{ + SAY_CORK_AMBUSH1 = -1001191, + SAY_CORK_AMBUSH2 = -1001192, + SAY_CORK_AMBUSH3 = -1001193, + SAY_CORK_END = -1001194, + SAY_RIGGER_AMBUSH1 = -1001195, + SAY_RIGGER_AMBUSH2 = -1001196, + SAY_RIGGER_END = -1001197, + + NPC_CORK_GIZELTON = 11625, + NPC_RIGGER_GIZELTON = 11626, + NPC_VENDOR_TRON = 12245, + NPC_SUPER_SELLER = 12246, + + NPC_KOLKAR_WAYLAYER = 12976, + NPC_KOLKAR_AMBUSHER = 12977, + + NPC_DOOMWARDER = 4677, + NPC_LESSER_INFERNAL = 4676, + NPC_NETHER_SORCERESS = 4684, + + QUEST_BODYGUARD_TO_HIRE = 5821, + QUEST_GIZELTON_CARAVAN = 5943, +}; + +static const SummonLocation aAmbushLocsBodyGuard[12] = +{ + // Quest QUEST_BODYGUARD_TO_HIRE + {-969.05f, 1174.91f, 90.39f}, // First ambush + {-985.71f, 1173.95f, 91.02f}, + {-983.01f, 1192.88f, 90.01f}, + {-965.51f, 1193.58f, 92.15f}, + {-1147.83f, 1180.87f, 91.38f}, // Second ambush + {-1163.96f, 1183.72f, 93.79f}, + {-1160.97f, 1201.36f, 93.15f}, + {-1146.20f, 1199.75f, 91.37f}, + {-1277.78f, 1218.56f, 109.30f}, // Third ambush + {-1292.65f, 1221.28f, 109.99f}, + {-1289.25f, 1239.20f, 108.79f}, + {-1272.91f, 1234.39f, 108.14f}, +}; + +static const SummonLocation aAmbushLocsGizelton[9] = +{ + // Quest QUEST_GIZELTON_CARAVAN + {-1823.7f, 2060.88f, 62.0925f}, // First ambush + {-1814.46f, 2060.13f, 62.4916f}, + {-1814.87f, 2080.6f, 63.6323f}, + {-1782.92f, 1942.55f, 60.2205f}, // Second ambush + {-1786.5f, 1926.05f, 59.7502f}, + {-1805.74f, 1942.77f, 60.791f}, + {-1677.56f, 1835.67f, 58.9269f}, // Third ambush + {-1675.66f, 1863.0f, 59.0008f}, + {-1692.31f, 1862.69, 58.9553f}, +}; + +static const uint32 AmbushersBodyguard[4] = { NPC_KOLKAR_WAYLAYER, NPC_KOLKAR_AMBUSHER, NPC_KOLKAR_WAYLAYER, NPC_KOLKAR_AMBUSHER }; +static const uint32 AmbushersGizleton[3] = { NPC_NETHER_SORCERESS, NPC_LESSER_INFERNAL, NPC_DOOMWARDER }; + +struct npc_cork_gizeltonAI : public ScriptedAI +{ + npc_cork_gizeltonAI(Creature* pCreature) : ScriptedAI(pCreature){ Reset(); } + + void Reset() override {} + + Player* pPlayer; + uint8 questStatus = 0; + + void DoAmbush(uint32 QuestId, uint8 AmbushPoint) + { + AmbushPoint--; + switch (QuestId) + { + case QUEST_BODYGUARD_TO_HIRE: + // Summon 2 NPC_KOLKAR_WAYLAYER and 2 NPC_KOLKAR_AMBUSHER + for (uint8 i = 0; i < 4; ++i) + { + float fX, fY, fZ; + m_creature->GetRandomPoint(aAmbushLocsBodyGuard[i + 4 * AmbushPoint].m_fX, aAmbushLocsBodyGuard[i + 4 * AmbushPoint].m_fY, aAmbushLocsBodyGuard[i + 4 * AmbushPoint].m_fZ, 7.0f, fX, fY, fZ); + m_creature->SummonCreature(AmbushersBodyguard[i], fX, fY, fZ, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0); + } + break; + case QUEST_GIZELTON_CARAVAN: + // Summon 1 NPC_NETHER_SORCERESS, 1 NPC_LESSER_INFERNAL and 1 NPC_DOOMWARDER + for (uint8 i = 0; i < 3; ++i) + { + float fX, fY, fZ; + m_creature->GetRandomPoint(aAmbushLocsGizelton[i + 3 * AmbushPoint].m_fX, aAmbushLocsGizelton[i + 3 * AmbushPoint].m_fY, aAmbushLocsGizelton[i + 3 * AmbushPoint].m_fZ, 7.0f, fX, fY, fZ); + m_creature->SummonCreature(AmbushersGizleton[i], fX, fY, fZ, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0); + } + break; + } + + return; + } + + void MovementInform(uint32 uiType, uint32 uiPointId) override + { + if (uiType != WAYPOINT_MOTION_TYPE) + return; + + // No player assigned as quest taker: abort to avoid summoning adds + if (!pPlayer) + return; + + if (pPlayer->GetQuestStatus(QUEST_BODYGUARD_TO_HIRE) == QUEST_STATUS_INCOMPLETE) + { + switch (uiPointId) + { + case 77: + questStatus = 1; + // First Ambush + case 96: + DoScriptText(SAY_CORK_AMBUSH1, m_creature); + DoAmbush(QUEST_BODYGUARD_TO_HIRE, 1); + break; + // Second Ambush + case 103: + DoScriptText(SAY_CORK_AMBUSH2, m_creature); + DoAmbush(QUEST_BODYGUARD_TO_HIRE, 2); + break; + // Third Ambush + case 111: + DoScriptText(SAY_CORK_AMBUSH3, m_creature); + DoAmbush(QUEST_BODYGUARD_TO_HIRE, 3); + break; + case 116: + DoScriptText(SAY_CORK_END, m_creature); + // Award quest credit + if (pPlayer) + pPlayer->GroupEventHappens(QUEST_BODYGUARD_TO_HIRE, m_creature); + // Remove player to avoid adds being spawned again next turn + pPlayer = nullptr; + questStatus = 0; + break; + } + } + // The second escort quest is also handled by NPC Cork though it is given by NPC Rigger + else if (pPlayer->GetQuestStatus(QUEST_GIZELTON_CARAVAN) == QUEST_STATUS_INCOMPLETE) + { + switch (uiPointId) + { + case 209: + questStatus = 2; + // First Ambush + case 218: + if (Creature* pRigger = GetClosestCreatureWithEntry(m_creature, NPC_RIGGER_GIZELTON, 100.0f)) + DoScriptText(SAY_RIGGER_AMBUSH1, pRigger); + DoAmbush(QUEST_GIZELTON_CARAVAN, 1); + break; + // Second Ambush + case 225: + if (Creature* pRigger = GetClosestCreatureWithEntry(m_creature, NPC_RIGGER_GIZELTON, 100.0f)) + DoScriptText(SAY_RIGGER_AMBUSH2, pRigger); + DoAmbush(QUEST_GIZELTON_CARAVAN, 2); + break; + // Third Ambush + case 235: + if (Creature* pRigger = GetClosestCreatureWithEntry(m_creature, NPC_RIGGER_GIZELTON, 100.0f)) + DoScriptText(SAY_RIGGER_AMBUSH1, pRigger); + DoAmbush(QUEST_GIZELTON_CARAVAN, 3); + break; + case 241: + if (Creature* pRigger = GetClosestCreatureWithEntry(m_creature, NPC_RIGGER_GIZELTON, 100.0f)) + DoScriptText(SAY_RIGGER_END, pRigger); + // Award quest credit + if (pPlayer) + pPlayer->GroupEventHappens(QUEST_GIZELTON_CARAVAN, m_creature); + // Remove player to avoid adds being spawned again next turn + pPlayer = nullptr; + questStatus = 0; + break; + } + } + } + + void JustSummoned(Creature* summoned) override + { + // By default: summoned for the two escort quests will attack + // So we want to add a special case to avoid the two summoned NPC vendors to also attack + if (summoned->GetEntry() != NPC_VENDOR_TRON && summoned->GetEntry() != NPC_SUPER_SELLER) + summoned->AI()->AttackStart(m_creature); + } + + void JustDied() + { + if (!pPlayer) + return; + + // Handle all players in group (if they took quest) + if (Group* pGroup = pPlayer->GetGroup()) + { + for (GroupReference* pRef = pGroup->GetFirstMember(); pRef != nullptr; pRef = pRef->next()) + { + if (Player* pMember = pRef->getSource()) + { + if (pMember->GetQuestStatus(QUEST_BODYGUARD_TO_HIRE) == QUEST_STATUS_INCOMPLETE) + pMember->FailQuest(QUEST_BODYGUARD_TO_HIRE); + if (pMember->GetQuestStatus(QUEST_GIZELTON_CARAVAN) == QUEST_STATUS_INCOMPLETE) + pMember->FailQuest(QUEST_GIZELTON_CARAVAN); + } + } + } + else + { + if (pPlayer->GetQuestStatus(QUEST_BODYGUARD_TO_HIRE) == QUEST_STATUS_INCOMPLETE) + pPlayer->FailQuest(QUEST_BODYGUARD_TO_HIRE); + if (pPlayer->GetQuestStatus(QUEST_GIZELTON_CARAVAN) == QUEST_STATUS_INCOMPLETE) + pPlayer->FailQuest(QUEST_GIZELTON_CARAVAN); + } + } +}; + +CreatureAI* GetAI_npc_cork_gizelton(Creature* pCreature) +{ + return new npc_cork_gizeltonAI(pCreature); +} + +bool QuestAccept_npc_cork_gizelton(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_BODYGUARD_TO_HIRE) + { + if (pPlayer->GetTeam() == ALLIANCE) + pCreature->SetFactionTemporary(FACTION_ESCORT_A_PASSIVE, TEMPFACTION_RESTORE_RESPAWN); + + if (pPlayer->GetTeam() == HORDE) + pCreature->SetFactionTemporary(FACTION_ESCORT_H_PASSIVE, TEMPFACTION_RESTORE_RESPAWN); + + if (npc_cork_gizeltonAI* pCork = dynamic_cast(pCreature->AI())) + pCork->pPlayer = pPlayer; + } + return true; +} + +/*###### +## npc_rigger_gizelton +######*/ + +struct npc_rigger_gizeltonAI : public ScriptedAI +{ + npc_rigger_gizeltonAI(Creature* pCreature) : ScriptedAI(pCreature){ Reset(); } + + void Reset() override {} +}; + +CreatureAI* GetAI_npc_rigger_gizelton(Creature* pCreature) +{ + return new npc_rigger_gizeltonAI(pCreature); +} + +bool QuestAccept_npc_rigger_gizelton(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_GIZELTON_CARAVAN) + { + if (pPlayer->GetTeam() == ALLIANCE) + pCreature->SetFactionTemporary(FACTION_ESCORT_A_PASSIVE, TEMPFACTION_RESTORE_RESPAWN); + + if (pPlayer->GetTeam() == HORDE) + pCreature->SetFactionTemporary(FACTION_ESCORT_H_PASSIVE, TEMPFACTION_RESTORE_RESPAWN); + + // Now the quest is accepted, tell NPC Cork what player took it so it can handle quest credit/failure + // because NPC Cork will handle both escort quests + if (Creature* pCork = GetClosestCreatureWithEntry(pCreature, NPC_CORK_GIZELTON, 100.0f)) + if (npc_cork_gizeltonAI* pCorkAI = dynamic_cast(pCork->AI())) + pCorkAI->pPlayer = pPlayer; + } + + return true; +} + void AddSC_desolace() { Script* pNewScript; @@ -414,4 +689,16 @@ void AddSC_desolace() pNewScript->GetAI = &GetAI_npc_melizza_brimbuzzle; pNewScript->pQuestAcceptNPC = &QuestAccept_npc_melizza_brimbuzzle; pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_cork_gizelton"; + pNewScript->GetAI = &GetAI_npc_cork_gizelton; + pNewScript->pQuestAcceptNPC = &QuestAccept_npc_cork_gizelton; + pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_rigger_gizelton"; + pNewScript->GetAI = &GetAI_npc_rigger_gizelton; + pNewScript->pQuestAcceptNPC = &QuestAccept_npc_rigger_gizelton; + pNewScript->RegisterSelf(); }