/*
* This file is part of the TrinityCore 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
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*/
/* ScriptData
SDName: Stratholme
SD%Complete: 100
SDComment: Misc mobs for instance. go-script to apply aura and start event for quest 8945
SDCategory: Stratholme
EndScriptData */
/* ContentData
go_gauntlet_gate
npc_freed_soul
npc_restless_soul
npc_spectral_ghostly_citizen
EndContentData */
#include "ScriptMgr.h"
#include "GameObject.h"
#include "GameObjectAI.h"
#include "Group.h"
#include "ScenarioMgr.h"
#include "InstanceScript.h"
#include "Map.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "SpellInfo.h"
#include "SpellScript.h"
#include "SpellAuraEffects.h"
#include "stratholme.h"
/*######
## go_gauntlet_gate (this is the _first_ of the gauntlet gates, two exist)
######*/
class go_gauntlet_gate : public GameObjectScript
{
public:
go_gauntlet_gate() : GameObjectScript("go_gauntlet_gate") { }
struct go_gauntlet_gateAI : public GameObjectAI
{
go_gauntlet_gateAI(GameObject* go) : GameObjectAI(go), instance(go->GetInstanceScript()) { }
InstanceScript* instance;
bool OnGossipHello(Player* player) override
{
if (instance->GetData(TYPE_BARON_RUN) != NOT_STARTED)
return false;
if (Group* group = player->GetGroup())
{
for (GroupReference const& itr : group->GetMembers())
{
Player* pGroupie = itr.GetSource();
if (!pGroupie->IsInMap(player))
continue;
if (pGroupie->GetQuestStatus(QUEST_DEAD_MAN_PLEA) == QUEST_STATUS_INCOMPLETE &&
!pGroupie->HasAura(SPELL_BARON_ULTIMATUM) &&
pGroupie->GetMap() == me->GetMap())
pGroupie->CastSpell(pGroupie, SPELL_BARON_ULTIMATUM, true);
}
}
else if (player->GetQuestStatus(QUEST_DEAD_MAN_PLEA) == QUEST_STATUS_INCOMPLETE &&
!player->HasAura(SPELL_BARON_ULTIMATUM) &&
player->GetMap() == me->GetMap())
player->CastSpell(player, SPELL_BARON_ULTIMATUM, true);
instance->SetData(TYPE_BARON_RUN, IN_PROGRESS);
return false;
}
};
GameObjectAI* GetAI(GameObject* go) const override
{
return GetStratholmeAI(go);
}
};
/*######
## npc_restless_soul
######*/
enum RestlessSoul
{
// Spells
SPELL_EGAN_BLASTER = 17368,
SPELL_SOUL_FREED = 17370,
// Quest
QUEST_RESTLESS_SOUL = 5282,
// Creatures
NPC_RESTLESS = 11122,
NPC_FREED = 11136
};
class npc_restless_soul : public CreatureScript
{
public:
npc_restless_soul() : CreatureScript("npc_restless_soul") { }
CreatureAI* GetAI(Creature* creature) const override
{
return GetStratholmeAI(creature);
}
struct npc_restless_soulAI : public ScriptedAI
{
npc_restless_soulAI(Creature* creature) : ScriptedAI(creature)
{
Initialize();
}
void Initialize()
{
Tagger.Clear();
Die_Timer = 5000;
Tagged = false;
}
ObjectGuid Tagger;
uint32 Die_Timer;
bool Tagged;
void Reset() override
{
Initialize();
}
void JustEngagedWith(Unit* /*who*/) override { }
void SpellHit(WorldObject* caster, SpellInfo const* spellInfo) override
{
if (Tagged || spellInfo->Id != SPELL_EGAN_BLASTER)
return;
Player* player = caster->ToPlayer();
if (!player || player->GetQuestStatus(QUEST_RESTLESS_SOUL) != QUEST_STATUS_INCOMPLETE)
return;
Tagged = true;
Tagger = caster->GetGUID();
}
void JustSummoned(Creature* summoned) override
{
summoned->CastSpell(summoned, SPELL_SOUL_FREED, false);
if (Player* player = ObjectAccessor::GetPlayer(*me, Tagger))
summoned->GetMotionMaster()->MoveFollow(player, 0.0f, 0.0f);
}
void JustDied(Unit* /*killer*/) override
{
if (Tagged)
me->SummonCreature(NPC_FREED, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, 5min);
}
void UpdateAI(uint32 diff) override
{
if (Tagged)
{
if (Die_Timer <= diff)
{
if (Unit* temp = ObjectAccessor::GetUnit(*me, Tagger))
{
if (Player* player = temp->ToPlayer())
player->KilledMonsterCredit(NPC_RESTLESS, me->GetGUID());
me->KillSelf();
}
}
else
Die_Timer -= diff;
}
}
};
};
/*######
## npc_spectral_ghostly_citizen
######*/
enum GhostlyCitizenSpells
{
SPELL_HAUNTING_PHANTOM = 16336,
SPELL_DEBILITATING_TOUCH = 16333,
SPELL_SLAP = 6754
};
class npc_spectral_ghostly_citizen : public CreatureScript
{
public:
npc_spectral_ghostly_citizen() : CreatureScript("npc_spectral_ghostly_citizen") { }
CreatureAI* GetAI(Creature* creature) const override
{
return GetStratholmeAI(creature);
}
struct npc_spectral_ghostly_citizenAI : public ScriptedAI
{
npc_spectral_ghostly_citizenAI(Creature* creature) : ScriptedAI(creature)
{
Initialize();
}
void Initialize()
{
Die_Timer = 5000;
HauntingTimer = 8000;
TouchTimer = 2000;
Tagged = false;
}
uint32 Die_Timer;
uint32 HauntingTimer;
uint32 TouchTimer;
bool Tagged;
void Reset() override
{
Initialize();
}
void JustEngagedWith(Unit* /*who*/) override { }
void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
{
if (!Tagged && spellInfo->Id == SPELL_EGAN_BLASTER)
Tagged = true;
}
void JustDied(Unit* /*killer*/) override
{
if (Tagged)
{
for (uint32 i = 1; i <= 4; ++i)
{
//100%, 50%, 33%, 25% chance to spawn
if (urand(1, i) == 1)
DoSummon(NPC_RESTLESS, me, 20.0f, 10min);
}
}
}
void UpdateAI(uint32 diff) override
{
if (Tagged)
{
if (Die_Timer <= diff)
me->KillSelf();
else Die_Timer -= diff;
}
if (!UpdateVictim())
return;
//HauntingTimer
if (HauntingTimer <= diff)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
DoCast(target, SPELL_HAUNTING_PHANTOM);
HauntingTimer = 11000;
}
else HauntingTimer -= diff;
//TouchTimer
if (TouchTimer <= diff)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
DoCast(target, SPELL_DEBILITATING_TOUCH);
TouchTimer = 7000;
}
else TouchTimer -= diff;
}
void ReceiveEmote(Player* player, uint32 emote) override
{
switch (emote)
{
case TEXT_EMOTE_DANCE:
EnterEvadeMode();
break;
case TEXT_EMOTE_RUDE:
if (me->IsWithinDistInMap(player, 5))
DoCast(player, SPELL_SLAP, false);
else
me->HandleEmoteCommand(EMOTE_ONESHOT_RUDE);
break;
case TEXT_EMOTE_WAVE:
me->HandleEmoteCommand(EMOTE_ONESHOT_WAVE);
break;
case TEXT_EMOTE_BOW:
me->HandleEmoteCommand(EMOTE_ONESHOT_BOW);
break;
case TEXT_EMOTE_KISS:
me->HandleEmoteCommand(EMOTE_ONESHOT_FLEX);
break;
}
}
};
};
// 31912 - Ysida Saved Credit Trigger
class spell_ysida_saved_credit : public SpellScript
{
bool Validate(SpellInfo const* /*spell*/) override
{
return ValidateSpellInfo({ SPELL_YSIDA_SAVED });
}
void FilterTargets(std::list& targets)
{
targets.remove_if([](WorldObject* obj)
{
return obj->GetTypeId() != TYPEID_PLAYER;
});
}
void HandleScript(SpellEffIndex /*effIndex*/)
{
if (Player* player = GetHitUnit()->ToPlayer())
{
player->AreaExploredOrEventHappens(QUEST_DEAD_MAN_PLEA);
player->KilledMonsterCredit(NPC_YSIDA);
}
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ysida_saved_credit::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
OnEffectHitTarget += SpellEffectFn(spell_ysida_saved_credit::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
enum HauntingPhantoms
{
SPELL_SUMMON_SPITEFUL_PHANTOM = 16334,
SPELL_SUMMON_WRATH_PHANTOM = 16335
};
// 16336 - Haunting Phantoms
class spell_stratholme_haunting_phantoms : public AuraScript
{
void CalcPeriodic(AuraEffect const* /*aurEff*/, bool& isPeriodic, int32& amplitude)
{
isPeriodic = true;
amplitude = irand(30, 90) * IN_MILLISECONDS;
}
void HandleDummyTick(AuraEffect const* /*aurEff*/)
{
if (roll_chance_i(50))
GetTarget()->CastSpell(nullptr, SPELL_SUMMON_SPITEFUL_PHANTOM, true);
else
GetTarget()->CastSpell(nullptr, SPELL_SUMMON_WRATH_PHANTOM, true);
}
void HandleUpdatePeriodic(AuraEffect* aurEff)
{
aurEff->CalculatePeriodic(GetCaster());
}
void Register() override
{
DoEffectCalcPeriodic += AuraEffectCalcPeriodicFn(spell_stratholme_haunting_phantoms::CalcPeriodic, EFFECT_0, SPELL_AURA_DUMMY);
OnEffectPeriodic += AuraEffectPeriodicFn(spell_stratholme_haunting_phantoms::HandleDummyTick, EFFECT_0, SPELL_AURA_DUMMY);
OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_stratholme_haunting_phantoms::HandleUpdatePeriodic, EFFECT_0, SPELL_AURA_DUMMY);
}
};
static constexpr uint32 StratholmeLfgDungeonServiceEntrance = 274;
static constexpr uint32 StratholmeScenarioServiceEntrance = 637;
// 10107 - Areatrigger
class at_stratholme_service_entrance : public OnlyOnceAreaTriggerScript
{
public:
at_stratholme_service_entrance() : OnlyOnceAreaTriggerScript("at_stratholme_service_entrance") { }
bool TryHandleOnce(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
{
if (InstanceMap* map = player->GetMap()->ToInstanceMap())
if (map->GetLfgDungeonsId() == StratholmeLfgDungeonServiceEntrance)
map->SetInstanceScenario(sScenarioMgr->CreateInstanceScenario(map, StratholmeScenarioServiceEntrance));
return true;
}
};
void AddSC_stratholme()
{
new go_gauntlet_gate();
new npc_restless_soul();
new npc_spectral_ghostly_citizen();
RegisterSpellScript(spell_ysida_saved_credit);
RegisterSpellScript(spell_stratholme_haunting_phantoms);
new at_stratholme_service_entrance();
}