diff options
-rw-r--r-- | sql/updates/377_world_scripts.sql | 10 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/zone/eversong_woods/eversong_woods.cpp | 419 |
2 files changed, 429 insertions, 0 deletions
diff --git a/sql/updates/377_world_scripts.sql b/sql/updates/377_world_scripts.sql new file mode 100644 index 00000000000..3fb8ef12fe8 --- /dev/null +++ b/sql/updates/377_world_scripts.sql @@ -0,0 +1,10 @@ +update creature_template set scriptname = 'npc_second_trial_paladin' where entry in (17809,17810,17811,17812); +update creature_template set scriptname = 'npc_second_trial_controller' where entry in (17807); +update gameobject_template set scriptname = 'go_second_trial' where entry in (182052); + +delete from `script_texts` where entry between -1645009 and -1645006; +INSERT INTO `script_texts` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`, `sound`, `type`, `language`, `comment`) VALUES +(-1645006,'Let the trial begin, Bloodwrath, attack!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,1,0,'master_kelerun_bloodmourn YELL_PHASE'), +(-1645007,'Champion Lightrend, make me proud!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,1,0,'master_kelerun_bloodmourn YELL_PHASE'), +(-1645008,'Show this upstart how a real Blood Knight fights, Swiftblade!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,1,0,'master_kelerun_bloodmourn YELL_PHASE'), +(-1645009,'Show $N the meaning of pain, Sunstriker!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,1,0,'master_kelerun_bloodmourn YELL_PHASE');
\ No newline at end of file diff --git a/src/bindings/scripts/scripts/zone/eversong_woods/eversong_woods.cpp b/src/bindings/scripts/scripts/zone/eversong_woods/eversong_woods.cpp index 4f9c2a775af..b2a09b547e4 100644 --- a/src/bindings/scripts/scripts/zone/eversong_woods/eversong_woods.cpp +++ b/src/bindings/scripts/scripts/zone/eversong_woods/eversong_woods.cpp @@ -145,6 +145,408 @@ bool GossipSelect_npc_prospector_anvilward(Player *player, Creature *_Creature, return true; } +/*###### +## Quest 9686 Second Trial +######*/ + +#define QUEST_SECOND_TRIAL 9686 + +#define MASTER_KELERUN_BLOODMOURN 17807 + +#define CHAMPION_BLOODWRATH 17809 +#define CHAMPION_LIGHTREND 17810 +#define CHAMPION_SWIFTBLADE 17811 +#define CHAMPION_SUNSTRIKER 17812 + +#define HARBINGER_OF_THE_SECOND_TRIAL 182052 + +#define SPELL_FLASH_OF_LIGHT 19939 +#define TIMER_FLASH_OF_LIGHT 3225 + +#define SPELL_SEAL_OF_JUSTICE 20164 +#define TIMER_SEAL_OF_JUSTICE 10000 + +#define SPELL_JUDGEMENT_OF_LIGHT 20271 +#define TIMER_JUDGEMENT_OF_LIGHT 10000 + +#define SPELL_SEAL_OF_COMMAND 20375 +#define TIMER_SEAL_OF_COMMAND 20000 + +#define OFFSET_NEXT_ATTACK 750 + +#define FACTION_HOSTILE 45 +#define FACTION_FRIENDLY 7 + +#define TEXT_SECOND_TRIAL_1 -1645006 +#define TEXT_SECOND_TRIAL_2 -1645007 +#define TEXT_SECOND_TRIAL_3 -1645008 +#define TEXT_SECOND_TRIAL_4 -1645009 + +struct Locations +{ + float x, y, z, o; +}; + +static Locations SpawnPosition[]= +{ + {5.3, -11.8, 0.361, 4.2}, + {11.2, -29.17, 0.361, 2.7}, + {-5.7, -34.85, 0.361, 1.09}, + {-11.9, -18, 0.361, 5.87} +}; + +static uint32 PaladinEntry[]= {CHAMPION_BLOODWRATH, CHAMPION_LIGHTREND, CHAMPION_SWIFTBLADE, CHAMPION_SUNSTRIKER}; + +/*###### +## npc_second_trial_paladin +######*/ + +struct TRINITY_DLL_DECL npc_secondTrialAI : public ScriptedAI +{ + npc_secondTrialAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 timer; + uint8 questPhase; + uint64 summonerGuid; + + bool spellFlashLight; + bool spellJustice; + bool spellJudLight; + bool spellCommand; + + uint32 timerFlashLight; + uint32 timerJustice; + uint32 timerJudLight; + uint32 timerCommand; + + + void Reset() { + + timer = 2000; + questPhase = 0; + summonerGuid = 0; + + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_KNEEL); + m_creature->setFaction(FACTION_FRIENDLY); + + spellFlashLight = false; + spellJustice = false; + spellJudLight = false; + spellCommand = false; + + switch(m_creature->GetEntry() ) { + case CHAMPION_BLOODWRATH : + spellFlashLight = true; + timerFlashLight = TIMER_FLASH_OF_LIGHT; + break; + case CHAMPION_LIGHTREND : + spellJustice = true; + timerJustice = 500; + break; + case CHAMPION_SWIFTBLADE : + spellJudLight = false; // Misses Script Effect // http://www.wowhead.com/?spell=20271 + timerJudLight = 500; + break; + case CHAMPION_SUNSTRIKER : + spellFlashLight = true; + spellJudLight = false; // Misses Script Effect // http://www.wowhead.com/?spell=20271 + spellCommand = false; // Misses Dummy // http://www.wowhead.com/?spell=20375 + timerFlashLight = TIMER_FLASH_OF_LIGHT; + timerJudLight = 500; + timerCommand = 1500; + break; + } + } + + void Aggro(Unit *who) { } + + void UpdateAI(const uint32 diff) + { + if ( questPhase == 1 ) { + + if ( timer < diff ) { + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_NONE); + m_creature->setFaction(FACTION_HOSTILE); + questPhase = 0; + + Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target && target->GetTypeId() == TYPEID_PLAYER) // only on players. + { + m_creature->AddThreat(target, 5000000.0f); + AttackStart(target); + } + } + else timer -= diff; + } + + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + // healer + if ( spellFlashLight ) { + if ( m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 70 ){ + if ( timerFlashLight < diff ) { + DoCast(m_creature, SPELL_FLASH_OF_LIGHT); + timerFlashLight = TIMER_FLASH_OF_LIGHT + rand()%( TIMER_FLASH_OF_LIGHT ); + } + else + timerFlashLight -= diff; + } + } + + if ( spellJustice ) { + if ( timerJustice < diff ) + { + DoCast(m_creature, SPELL_SEAL_OF_JUSTICE); + timerJustice = TIMER_SEAL_OF_JUSTICE + rand()%( TIMER_SEAL_OF_JUSTICE ); + } + else + timerJustice -= diff; + } + + if ( spellJudLight ) { + if ( timerJudLight < diff ) { + DoCast(m_creature, SPELL_JUDGEMENT_OF_LIGHT); + timerJudLight = TIMER_JUDGEMENT_OF_LIGHT + rand()%( TIMER_JUDGEMENT_OF_LIGHT ); + } + else + timerJudLight -= diff; + } + + if ( spellCommand ) { + if ( timerCommand < diff ) { + DoCast(m_creature, TIMER_SEAL_OF_COMMAND); + timerCommand = TIMER_SEAL_OF_COMMAND + rand()%( TIMER_SEAL_OF_COMMAND ); + } + else + timerCommand -= diff; + } + + DoMeleeAttackIfReady(); + } + + void Activate(uint64 summonerguid); + void KilledUnit(Unit* Killed); + void JustDied(Unit* Killer); + +}; + +/*###### +## npc_second_trial_controller +######*/ + +struct TRINITY_DLL_DECL master_kelerun_bloodmournAI : public ScriptedAI +{ + master_kelerun_bloodmournAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint8 questPhase; + uint8 paladinPhase; + uint32 timer; + + uint64 paladinGuid[4]; + + void Reset() { + + questPhase = 0; + timer = 60000; + paladinPhase = 0; + uint64 paladinGuid[] = {0,0,0,0}; + + } + + void Aggro(Unit *who) {} + + void UpdateAI(const uint32 diff) + { + // Quest accepted but object not activated, object despawned (if in sync 1 minute! ) + if ( questPhase == 1 ) { + if ( timer < diff ) Reset(); + else timer -= diff; + } + // fight the 4 paladin mobs phase + else if ( questPhase == 2 ) { + + if ( timer < diff ) { + + Creature* paladinSpawn; + paladinSpawn = ((Creature*)Unit::GetUnit((*m_creature), paladinGuid[paladinPhase])); + if ( paladinSpawn ) { + ((npc_secondTrialAI*)paladinSpawn->AI())->Activate(m_creature->GetGUID()); + + switch(paladinPhase) { + case 0: + DoScriptText(TEXT_SECOND_TRIAL_1,m_creature); + break; + case 1: + DoScriptText(TEXT_SECOND_TRIAL_2,m_creature); + break; + case 2: + DoScriptText(TEXT_SECOND_TRIAL_3,m_creature); + break; + case 3: + DoScriptText(TEXT_SECOND_TRIAL_4,m_creature); + break; + } + } + else + Reset(); + + questPhase=4; + timer = OFFSET_NEXT_ATTACK; + } + else timer -= diff; + } + + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void StartEvent() + { + + if ( questPhase == 1 ) { // no player check, quest can be finished as group, so no complex playerguid/group search code + + for (int i = 0; i<4; i++) { + Creature* Summoned; + Summoned = DoSpawnCreature(PaladinEntry[i], SpawnPosition[i].x, SpawnPosition[i].y, SpawnPosition[i].z, SpawnPosition[i].o, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 180000); + + if(Summoned) + paladinGuid[i] = Summoned->GetGUID(); + } + + timer = OFFSET_NEXT_ATTACK; + questPhase = 2; + } + } + + void SecondTrialKill(); + void SummonedCreatureDespawn(Creature* c) {Reset();} +}; + + +bool GossipHello_master_kelerun_bloodmourn(Player *player, Creature *_Creature) +{ + // quest only available if not already started + // Quest_template flag is set to : QUEST_FLAGS_EVENT + // Escort quests or any other event-driven quests. If player in party, all players that can accept this quest will receive confirmation box to accept quest. + // !not sure if this really works! + + if ( ((master_kelerun_bloodmournAI*)_Creature->AI())->questPhase == 0 ) { + player->PrepareQuestMenu(_Creature->GetGUID()); + player->SendPreparedQuest(_Creature->GetGUID()); + } + + player->SEND_GOSSIP_MENU(_Creature->GetEntry(), _Creature->GetGUID()); + return true; +} + +bool QuestAccept_master_kelerun_bloodmourn(Player *player, Creature *creature, Quest const *quest ) +{ + // One Player exclusive quest, wait for user go activation + if(quest->GetQuestId() == QUEST_SECOND_TRIAL ) + ((master_kelerun_bloodmournAI*)creature->AI())->questPhase = 1; + + return true; +} + +void master_kelerun_bloodmournAI::SecondTrialKill() { + + if ( questPhase > 0 ) { + + ++paladinPhase; + + if ( paladinPhase < 4 ) + questPhase=2; + else + Reset(); // Quest Complete, QuestComplete handler is in npc_secondTrialAI::JustDied + } + } + +void npc_secondTrialAI::JustDied(Unit* Killer) { + + if (Killer->GetTypeId() == TYPEID_PLAYER) + { + Creature* Summoner; + Summoner = ((Creature*)Unit::GetUnit((*m_creature), summonerGuid)); + + if ( Summoner ) + ((master_kelerun_bloodmournAI*)Summoner->AI())->SecondTrialKill(); + + // last kill quest complete for group + if ( m_creature->GetEntry() == CHAMPION_SUNSTRIKER ) { + + if( Group *pGroup = ((Player*)Killer)->GetGroup() ) + { + for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *pGroupGuy = itr->getSource(); + + // for any leave or dead (with not released body) group member at appropriate distance + if( pGroupGuy && pGroupGuy->IsAtGroupRewardDistance(m_creature) && !pGroupGuy->GetCorpse() && pGroupGuy->GetQuestStatus( QUEST_SECOND_TRIAL ) == QUEST_STATUS_INCOMPLETE ) + pGroupGuy->CompleteQuest( QUEST_SECOND_TRIAL ); + } + } + else { + if ( ((Player*)Killer)->GetQuestStatus( QUEST_SECOND_TRIAL ) == QUEST_STATUS_INCOMPLETE ) + ((Player*)Killer)->CompleteQuest( QUEST_SECOND_TRIAL ); + } + } + } + } + +void npc_secondTrialAI::KilledUnit(Unit* Killed) { + + if ( Killed->GetTypeId() == TYPEID_PLAYER ) { + + if ( ((Player*)Killed)->GetQuestStatus(QUEST_SECOND_TRIAL) == QUEST_STATUS_INCOMPLETE ) + ((Player*)Killed)->FailQuest(QUEST_SECOND_TRIAL); + } +} + +void npc_secondTrialAI::Activate(uint64 summonerguid) { + + questPhase=1; + summonerGuid = summonerguid; + } + +CreatureAI* GetAI_master_kelerun_bloodmourn(Creature *_Creature) +{ + return new master_kelerun_bloodmournAI (_Creature); +} + +CreatureAI* GetAI_npc_secondTrial(Creature *_Creature) +{ + return new npc_secondTrialAI (_Creature); +} + +/*###### +## go_second_trial +######*/ + +bool GOHello_go_second_trial(Player *player, GameObject* _GO) +{ + // find spawn :: master_kelerun_bloodmourn + CellPair p(Trinity::ComputeCellPair(_GO->GetPositionX(), _GO->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + CellLock<GridReadGuard> cell_lock(cell, p); + + Creature* event_controller = NULL; + Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*_GO, MASTER_KELERUN_BLOODMOURN, true, 30); + Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(event_controller, u_check); + TypeContainerVisitor<Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher); + //cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(_GO->GetMap(), _GO)); + cell_lock->Visit(cell_lock, grid_unit_searcher, *(_GO->GetMap())); + + if ( event_controller ) + ((master_kelerun_bloodmournAI*)event_controller->AI())->StartEvent(); + + return true; +} + void AddSC_eversong_woods() { Script *newscript; @@ -160,4 +562,21 @@ void AddSC_eversong_woods() newscript->pGossipHello = &GossipHello_npc_prospector_anvilward; newscript->pGossipSelect = &GossipSelect_npc_prospector_anvilward; newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="npc_second_trial_controller"; + newscript->GetAI = GetAI_master_kelerun_bloodmourn; + newscript->pGossipHello = &GossipHello_master_kelerun_bloodmourn; + newscript->pQuestAccept = &QuestAccept_master_kelerun_bloodmourn; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="npc_second_trial_paladin"; + newscript->GetAI = GetAI_npc_secondTrial; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="go_second_trial"; + newscript->pGOHello = &GOHello_go_second_trial; + newscript->RegisterSelf(); } |