/*
* 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: Zulfarrak
SD%Complete: 50
SDComment: Consider it temporary, no instance script made for this instance yet.
SDCategory: Zul'Farrak
EndScriptData */
/* ContentData
npc_sergeant_bly
npc_weegli_blastfuse
EndContentData */
#include "ScriptMgr.h"
#include "GameObject.h"
#include "GameObjectAI.h"
#include "InstanceScript.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "zulfarrak.h"
/*######
## npc_sergeant_bly
######*/
enum blySays
{
SAY_1 = 0,
SAY_2 = 1
};
enum blySpells
{
SPELL_SHIELD_BASH = 11972,
SPELL_REVENGE = 12170,
};
enum blygossip
{
GOSSIP_BLY_MID = 941, //That's it! I'm tired of helping you out. It's time we settled things on the battlefield!
GOSSIP_BLY_OID = 1
};
class npc_sergeant_bly : public CreatureScript
{
public:
npc_sergeant_bly() : CreatureScript("npc_sergeant_bly") { }
struct npc_sergeant_blyAI : public ScriptedAI
{
npc_sergeant_blyAI(Creature* creature) : ScriptedAI(creature)
{
Initialize();
instance = creature->GetInstanceScript();
postGossipStep = 0;
Text_Timer = 0;
}
void Initialize()
{
ShieldBash_Timer = 5000;
Revenge_Timer = 8000;
}
InstanceScript* instance;
uint32 postGossipStep;
uint32 Text_Timer;
uint32 ShieldBash_Timer;
uint32 Revenge_Timer; //this is wrong, spell should never be used unless me->GetVictim() dodge, parry or block attack. Trinity support required.
ObjectGuid PlayerGUID;
void Reset() override
{
Initialize();
me->SetFaction(FACTION_FRIENDLY);
}
void UpdateAI(uint32 diff) override
{
if (postGossipStep>0 && postGossipStep<4)
{
if (Text_TimerGetGuidData(ENTRY_WEEGLI)))
pWeegli->AI()->DoAction(0);
Talk(SAY_1);
Text_Timer = 5000;
break;
case 2:
Talk(SAY_2);
Text_Timer = 5000;
break;
case 3:
me->SetFaction(FACTION_MONSTER);
if (Player* target = ObjectAccessor::GetPlayer(*me, PlayerGUID))
AttackStart(target);
switchFactionIfAlive(ENTRY_RAVEN);
switchFactionIfAlive(ENTRY_ORO);
switchFactionIfAlive(ENTRY_MURTA);
}
postGossipStep++;
}
else Text_Timer -= diff;
}
if (!UpdateVictim())
return;
if (ShieldBash_Timer <= diff)
{
DoCastVictim(SPELL_SHIELD_BASH);
ShieldBash_Timer = 15000;
}
else
ShieldBash_Timer -= diff;
if (Revenge_Timer <= diff)
{
DoCastVictim(SPELL_REVENGE);
Revenge_Timer = 10000;
}
else
Revenge_Timer -= diff;
}
void DoAction(int32 /*param*/) override
{
postGossipStep=1;
Text_Timer = 0;
}
void switchFactionIfAlive(uint32 entry)
{
if (Creature* crew = ObjectAccessor::GetCreature(*me, instance->GetGuidData(entry)))
if (crew->IsAlive())
crew->SetFaction(FACTION_MONSTER);
}
bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
{
uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
ClearGossipMenuFor(player);
if (action == GOSSIP_ACTION_INFO_DEF + 1)
{
CloseGossipMenuFor(player);
PlayerGUID = player->GetGUID();
DoAction(0);
}
return true;
}
bool OnGossipHello(Player* player) override
{
InitGossipMenuFor(player, GOSSIP_BLY_MID);
if (instance->GetData(EVENT_PYRAMID) == PYRAMID_KILLED_ALL_TROLLS)
{
AddGossipItemFor(player, GOSSIP_BLY_MID, GOSSIP_BLY_OID, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
SendGossipMenuFor(player, 1517, me->GetGUID());
}
else
if (instance->GetData(EVENT_PYRAMID) == PYRAMID_NOT_STARTED)
SendGossipMenuFor(player, 1515, me->GetGUID());
else
SendGossipMenuFor(player, 1516, me->GetGUID());
return true;
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetZulFarrakAI(creature);
}
};
/*######
+## go_troll_cage
+######*/
class go_troll_cage : public GameObjectScript
{
public:
go_troll_cage() : GameObjectScript("go_troll_cage") { }
struct go_troll_cageAI : public GameObjectAI
{
go_troll_cageAI(GameObject* go) : GameObjectAI(go), instance(go->GetInstanceScript()) { }
InstanceScript* instance;
bool OnGossipHello(Player* /*player*/) override
{
instance->SetData(EVENT_PYRAMID, PYRAMID_CAGES_OPEN);
//set bly & co to aggressive & start moving to top of stairs
initBlyCrewMember(ENTRY_BLY, 1884.99f, 1263, 41.52f);
initBlyCrewMember(ENTRY_RAVEN, 1882.5f, 1263, 41.52f);
initBlyCrewMember(ENTRY_ORO, 1886.47f, 1270.68f, 41.68f);
initBlyCrewMember(ENTRY_WEEGLI, 1890, 1263, 41.52f);
initBlyCrewMember(ENTRY_MURTA, 1891.19f, 1272.03f, 41.60f);
return false;
}
private:
void initBlyCrewMember(uint32 entry, float x, float y, float z)
{
if (Creature* crew = ObjectAccessor::GetCreature(*me, instance->GetGuidData(entry)))
{
crew->SetReactState(REACT_AGGRESSIVE);
crew->SetWalk(true);
crew->SetHomePosition(x, y, z, 0);
crew->GetMotionMaster()->MovePoint(1, x, y, z);
crew->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_ACTIVE);
}
}
};
GameObjectAI* GetAI(GameObject* go) const override
{
return GetZulFarrakAI(go);
}
};
/*######
## npc_weegli_blastfuse
######*/
enum weegliSpells
{
SPELL_BOMB = 8858,
SPELL_GOBLIN_LAND_MINE = 21688,
SPELL_SHOOT = 6660,
SPELL_WEEGLIS_BARREL = 10772
};
enum weegliSays
{
SAY_WEEGLI_OHNO = 0,
SAY_WEEGLI_OK_I_GO = 1
};
enum weegligossip
{
GOSSIP_WEEGLI_MID = 940, // Will you blow up that door now?
GOSSIP_WEEGLI_OID = 0
};
class npc_weegli_blastfuse : public CreatureScript
{
public:
npc_weegli_blastfuse() : CreatureScript("npc_weegli_blastfuse") { }
struct npc_weegli_blastfuseAI : public ScriptedAI
{
npc_weegli_blastfuseAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
destroyingDoor = false;
Bomb_Timer = 10000;
LandMine_Timer = 30000;
}
uint32 Bomb_Timer;
uint32 LandMine_Timer;
bool destroyingDoor;
InstanceScript* instance;
void Reset() override
{
/*instance->SetData(0, NOT_STARTED);*/
}
void AttackStart(Unit* victim) override
{
AttackStartCaster(victim, 10);//keep back & toss bombs/shoot
}
void JustDied(Unit* /*killer*/) override
{
/*instance->SetData(0, DONE);*/
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (Bomb_Timer < diff)
{
DoCastVictim(SPELL_BOMB);
Bomb_Timer = 10000;
}
else
Bomb_Timer -= diff;
if (me->isAttackReady() && !me->IsWithinMeleeRange(me->GetVictim()))
{
DoCastVictim(SPELL_SHOOT);
me->SetSheath(SHEATH_STATE_RANGED);
}
else
{
me->SetSheath(SHEATH_STATE_MELEE);
}
}
void MovementInform(uint32 /*type*/, uint32 /*id*/) override
{
if (instance->GetData(EVENT_PYRAMID) == PYRAMID_CAGES_OPEN)
{
instance->SetData(EVENT_PYRAMID, PYRAMID_ARRIVED_AT_STAIR);
Talk(SAY_WEEGLI_OHNO);
me->SetHomePosition(1882.69f, 1272.28f, 41.87f, 0);
}
else
if (destroyingDoor)
{
instance->DoUseDoorOrButton(instance->GetGuidData(GO_END_DOOR));
/// @todo leave the area...
me->DespawnOrUnsummon();
};
}
void DestroyDoor()
{
if (me->IsAlive())
{
me->SetFaction(FACTION_FRIENDLY);
me->GetMotionMaster()->MovePoint(0, 1858.57f, 1146.35f, 14.745f);
me->SetHomePosition(1858.57f, 1146.35f, 14.745f, 3.85f); // in case he gets interrupted
Talk(SAY_WEEGLI_OK_I_GO);
destroyingDoor = true;
}
}
bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
{
uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
ClearGossipMenuFor(player);
if (action == GOSSIP_ACTION_INFO_DEF + 1)
{
CloseGossipMenuFor(player);
//here we make him run to door, set the charge and run away off to nowhere
DestroyDoor();
}
return true;
}
bool OnGossipHello(Player* player) override
{
InitGossipMenuFor(player, GOSSIP_WEEGLI_MID);
switch (instance->GetData(EVENT_PYRAMID))
{
case PYRAMID_KILLED_ALL_TROLLS:
AddGossipItemFor(player, GOSSIP_WEEGLI_MID, GOSSIP_WEEGLI_OID, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
SendGossipMenuFor(player, 1514, me->GetGUID()); //if event can proceed to end
break;
case PYRAMID_NOT_STARTED:
SendGossipMenuFor(player, 1511, me->GetGUID()); //if event not started
break;
default:
SendGossipMenuFor(player, 1513, me->GetGUID()); //if event are in progress
}
return true;
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetZulFarrakAI(creature);
}
};
/*######
## go_shallow_grave
######*/
enum ShallowGrave
{
NPC_ZOMBIE = 7286,
NPC_DEAD_HERO = 7276,
CHANCE_ZOMBIE = 65,
CHANCE_DEAD_HERO = 10
};
class go_shallow_grave : public GameObjectScript
{
public:
go_shallow_grave() : GameObjectScript("go_shallow_grave") { }
struct go_shallow_graveAI : public GameObjectAI
{
go_shallow_graveAI(GameObject* go) : GameObjectAI(go) { }
bool OnGossipHello(Player* /*player*/) override
{
// randomly summon a zombie or dead hero the first time a grave is used
if (me->GetUseCount() == 0)
{
uint32 randomchance = urand(0, 100);
if (randomchance < CHANCE_ZOMBIE)
me->SummonCreature(NPC_ZOMBIE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30s);
else
if ((randomchance - CHANCE_ZOMBIE) < CHANCE_DEAD_HERO)
me->SummonCreature(NPC_DEAD_HERO, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30s);
}
me->AddUse();
return false;
}
};
GameObjectAI* GetAI(GameObject* go) const override
{
return GetZulFarrakAI(go);
}
};
/*######
## at_zumrah
######*/
enum zumrahConsts
{
ZUMRAH_ID = 7271
};
class at_zumrah : public AreaTriggerScript
{
public:
at_zumrah() : AreaTriggerScript("at_zumrah") { }
bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
{
Creature* pZumrah = player->FindNearestCreature(ZUMRAH_ID, 30.0f);
if (!pZumrah)
return false;
pZumrah->SetFaction(FACTION_TROLL_FROSTMANE);
return true;
}
};
void AddSC_zulfarrak()
{
new npc_sergeant_bly();
new npc_weegli_blastfuse();
new go_shallow_grave();
new at_zumrah();
new go_troll_cage();
}