/* Copyright (C) 2006,2007 ScriptDev2
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* ScriptData
SDName: npcs_karazhan
SD%Complete: 75
SDComment: Barnes: Not fully complete. Support for Berthold.
SDCategory: Karazhan
EndScriptData */
#include "sc_creature.h"
#include "sc_gossip.h"
#include "def_karazhan.h"
#include "GameObject.h"
#include "Map.h"
#include "PointMovementGenerator.h"
/*######
# npc_barnesAI
######*/
#define GOSSIP_READY "I'm not an actor."
#define SAY_READY "Splendid, I'm going to get the audience ready. Break a leg!"
#define SAY_OZ_INTRO1 "Finally, everything is in place. Are you ready for your big stage debut?"
#define OZ_GOSSIP1 "I'm not an actor."
#define SAY_OZ_INTRO2 "Don't worry, you'll be fine. You look like a natural!"
#define OZ_GOSSIP2 "Ok, I'll give it a try, then."
#define SAY_RAJ_INTRO1 "The romantic plays are really tough, but you'll do better this time. You have TALENT. Ready?"
#define RAJ_GOSSIP1 "I've never been more ready."
struct Dialogue
{
char* text;
uint32 soundid, timer;
};
static Dialogue OzDialogue[]=
{
{"Welcome Ladies and Gentlemen, to this evening's presentation!", 9174, 6000},
{"Tonight we plumb the depths of the human soul as we join a lost, lonely girl trying desperately -- with the help of her loyal companions -- to find her way home!", 9338, 18000},
{"But she is pursued... by a wicked malevolent crone!", 9339, 9000},
{"Will she survive? Will she prevail? Only time will tell. And now ... on with the show!", 9340, 15000}
};
static Dialogue HoodDialogue[]=
{
{"Good evening, Ladies and Gentlemen! Welcome to this evening's presentation!", 9175, 6000},
{"Tonight, things are not what they seem. For tonight, your eyes may not be trusted", 9335, 10000},
{"Take for instance, this quiet, elderly woman, waiting for a visit from her granddaughter. Surely there is nothing to fear from this sweet, grey-haired, old lady.", 9336, 14000},
{"But don't let me pull the wool over your eyes. See for yourself what lies beneath those covers! And now... on with the show!", 9337, 15000}
};
static Dialogue RAJDialogue[]=
{
{"Welcome, Ladies and Gentlemen, to this evening's presentation!", 9176, 5000},
{"Tonight, we explore a tale of forbidden love!", 9341, 7000},
{"But beware, for not all love stories end happily, as you may find out. Sometimes, love pricks like a thorn.", 9342, 14000},
{"But don't take it from me, see for yourself what tragedy lies ahead when the paths of star-crossed lovers meet. And now...on with the show!", 9343, 14000}
};
float Spawns[7][2]=
{
{17535, -10896}, // Dorothee
{17546, -10891}, // Roar
{17547, -10884}, // Tinhead
{17543, -10902}, // Strawman
{17603, -10892}, // Grandmother
{17534, -10900}, // Julianne
{17533, -10855}, // Romulo
};
struct WayPoint
{
float x,y,o;
uint32 timer;
};
static WayPoint Forward[]=
{
{-10866.711, -1779.816, 2.989, 1000},
{-10894.917, -1775.467, 4.556, 14500},
{-10896.044, -1782.619, 4.556, 7000}
};
static WayPoint Backward[]=
{
{-10894.917, -1775.467, 4.556, 4000},
{-10866.711, -1779.816, 2.989, 14500},
{-10866.700, -1781.030, 2.989, 3000}
};
#define CREATURE_SPOTLIGHT 19525
#define SPELL_SPOTLIGHT 25824
#define SPELL_TUXEDO 32616
#define EVENT_OZ 0
#define EVENT_HOOD 1
#define EVENT_RAJ 2
#define SPAWN_Z 90.5
#define SPAWN_Y -1758
#define SPAWN_O 4.738
struct MANGOS_DLL_DECL npc_barnesAI : public ScriptedAI
{
npc_barnesAI(Creature* c) : ScriptedAI(c)
{
pInstance = ((ScriptedInstance*)c->GetInstanceData());
Reset();
}
ScriptedInstance* pInstance;
bool Prepared;
bool IsTalking;
bool IsWalking;
bool HasTalked;
bool IntroComplete;
bool RaidWiped;
uint32 TalkTimer;
uint32 WalkTimer;
uint32 WaitTimer;
uint32 WipeTimer;
uint32 WalkCount;
uint32 TalkCount;
uint32 Event; // 0 - OZ, 1 - HOOD, 2 - RAJ
uint64 PlayerGUID;
uint64 SpotlightGUID;
void Reset()
{
IsTalking = false;
IsWalking = false;
HasTalked = false;
Prepared = false;
IntroComplete = false;
RaidWiped = false;
TalkCount = 0;
TalkTimer = 0;
WalkCount = 0;
WalkTimer = 0;
WaitTimer = 10000;
WipeTimer = 5000;
Event = 4; // Set it to 4 so that it will not always default to Oz
PlayerGUID = 0;
SpotlightGUID = 0;
if(pInstance)
Event = pInstance->GetData(DATA_OPERA_PERFORMANCE); // Attempt to get the data now, will default to 4 if we can't
}
void Aggro(Unit* who)
{
}
void StartEvent(Player* target)
{
if(!pInstance)
return;
if(target)
PlayerGUID = target->GetGUID();
Event = pInstance->GetData(DATA_OPERA_PERFORMANCE);
GameObject* Door = GameObject::GetGameObject((*m_creature), pInstance->GetData64(DATA_GAMEOBJECT_STAGEDOOR));
if(Door)
Door->SetUInt32Value(GAMEOBJECT_STATE, 2);
IsTalking = false;
IsWalking = true;
HasTalked = false;
Prepared = false;
IntroComplete = false;
RaidWiped = false;
TalkCount = 0;
TalkTimer = 0;
WalkCount = 0;
WalkTimer = 0;
WaitTimer = 10000;
WipeTimer = 5000;
DoCast(m_creature, SPELL_TUXEDO, true);
m_creature->SetUInt32Value(UNIT_NPC_FLAGS, 0);
m_creature->GetMotionMaster()->Mutate(new PointMovementGenerator(0, Forward[0].x, Forward[0].y, m_creature->GetPositionZ()));
}
void Walk(uint32 count, WayPoint Points[3])
{
float x = 0;
float y = 0;
float o = 0;
if(Points[count].x)
x = Points[count].x;
if(Points[count].y)
y = Points[count].y;
if(Points[count].o)
o = Points[count].o;
if(Points[count].timer)
WalkTimer = Points[count].timer;
m_creature->GetMotionMaster()->Mutate(new PointMovementGenerator(count, x, y, m_creature->GetPositionZ()));
}
void MovementInform(uint32 type, uint32 id)
{
float x = 0;
float y = 0;
float o = 0;
uint32 nextPoint = 0;
if(!HasTalked)
{
nextPoint = id + 1;
if(Forward[nextPoint].x)
x = Forward[nextPoint].x;
if(Forward[nextPoint].y)
y = Forward[nextPoint].y;
if(Forward[nextPoint].o)
o = Forward[id].o;
}
else
{
if(id < 0)
return;
nextPoint = id - 1;
if(Backward[id].x)
x = Backward[id].x;
if(Backward[id].y)
y = Backward[id].y;
if(Backward[id].o)
o = Backward[id].o;
}
if((id > 2) && !IsTalking)
{
Creature* Spotlight = DoSpawnCreature(CREATURE_SPOTLIGHT, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 35000);
if(Spotlight)
{
Spotlight->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
SpotlightGUID = Spotlight->GetGUID();
Spotlight->CastSpell(Spotlight, SPELL_SPOTLIGHT, true);
}
IsTalking = true;
return;
}
m_creature->GetMotionMaster()->Mutate(new PointMovementGenerator(nextPoint, x, y, m_creature->GetPositionZ()));
}
void Talk(uint32 count)
{
if(count > 4)
return;
char* text = NULL;
uint32 sound = 0;
TalkTimer = 0;
switch(Event)
{
case EVENT_OZ:
if(OzDialogue[count].text)
text = OzDialogue[count].text;
if(OzDialogue[count].soundid)
sound = OzDialogue[count].soundid;
if(OzDialogue[count].timer)
TalkTimer = OzDialogue[count].timer;
break;
case EVENT_HOOD:
if(HoodDialogue[count].text)
text = HoodDialogue[count].text;
if(HoodDialogue[count].soundid)
sound = HoodDialogue[count].soundid;
if(HoodDialogue[count].timer)
TalkTimer = HoodDialogue[count].timer;
break;
case EVENT_RAJ:
if(RAJDialogue[count].text)
text = RAJDialogue[count].text;
if(RAJDialogue[count].soundid)
sound = RAJDialogue[count].soundid;
if(RAJDialogue[count].timer)
TalkTimer = RAJDialogue[count].timer;
break;
default:
error_log("ERROR: Invalid performance entry for Karazhan Opera Event. Please check your Instance Scriptname and scripts");
}
if(text)
DoYell(text, LANG_UNIVERSAL, NULL);
if(sound)
DoPlaySoundToSet(m_creature, sound);
m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_TALK);
}
void InitializeMovement(const uint32 diff)
{
if(WalkTimer < diff)
{
if(!HasTalked)
{
Walk(WalkCount, Forward);
WalkCount++;
if(WalkCount > 2)
{
Creature* Spotlight = DoSpawnCreature(CREATURE_SPOTLIGHT, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 35000);
if(Spotlight)
{
Spotlight->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
SpotlightGUID = Spotlight->GetGUID();
Spotlight->CastSpell(Spotlight, SPELL_SPOTLIGHT, true);
}
IsTalking = true;
}
}
else
{
if(WalkCount > 2)
{
if(pInstance)
{
GameObject* Door = GameObject::GetGameObject((*m_creature), pInstance->GetData64(DATA_GAMEOBJECT_STAGEDOOR));
if(Door)
{
Door->SetUInt32Value(GAMEOBJECT_STATE, 3);
Door->SetUInt32Value(GAMEOBJECT_STATE, 0);
}
}
m_creature->RemoveAurasDueToSpell(SPELL_TUXEDO);
IsWalking = false;
IntroComplete = true;
}
Walk(WalkCount, Backward);
WalkCount++;
}
}else WalkTimer -= diff;
}
void InitializeTalking(const uint32 diff)
{
if(TalkTimer < diff)
{
if(TalkCount > 4)
{
m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE);
if(SpotlightGUID)
{
Unit* Spotlight = Unit::GetUnit((*m_creature), SpotlightGUID);
if(Spotlight)
Spotlight->DealDamage(Spotlight, Spotlight->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
}
WalkCount = 0;
IsTalking = false;
HasTalked = true;
IsWalking = true;
}
Talk(TalkCount);
TalkCount++;
}else TalkTimer -= diff;
}
void PrepareEncounter()
{
uint8 index = 0;
uint8 count = 0;
switch(Event)
{
case EVENT_OZ:
index = 0;
count = 4;
break;
case EVENT_HOOD:
index = 4;
count = index+1;
break;
case EVENT_RAJ:
index = 5;
count = index+2;
break;
}
for( ; index < count; ++index)
{
uint32 entry = ((uint32)Spawns[index][0]);
float PosX = Spawns[index][1];
m_creature->SummonCreature(entry, PosX, SPAWN_Y, SPAWN_Z, SPAWN_O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 45000);
}
if(pInstance)
{
GameObject* Curtain = GameObject::GetGameObject((*m_creature), pInstance->GetData64(DATA_GAMEOBJECT_CURTAINS));
if(Curtain)
{
Curtain->SetUInt32Value(GAMEOBJECT_STATE, 2);
Curtain->SetUInt32Value(GAMEOBJECT_STATE, 4);
}
}
}
void UpdateAI(const uint32 diff)
{
if(IsWalking)
InitializeMovement(diff);
if(IsTalking)
InitializeTalking(diff);
if(IntroComplete && !Prepared)
{
if(WaitTimer < diff)
{
PrepareEncounter();
Prepared = true;
}
else WaitTimer -= diff;
}
if(!RaidWiped)
{
if(WipeTimer < diff)
{
std::list PlayerList = m_creature->GetMap()->GetPlayers();
if(PlayerList.empty())
return;
uint32 DeathCount = 0;
uint32 TotalCount = PlayerList.size();
for(std::list::iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr)
{
if(!(*itr)->isAlive())
DeathCount++;
}
if(DeathCount == TotalCount)
RaidWiped = true;
WipeTimer = 15000;
}else WipeTimer -= diff;
}
if(!m_creature->SelectHostilTarget() || !m_creature->getVictim())
return;
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI_npc_barnes(Creature* _Creature)
{
return new npc_barnesAI(_Creature);
}
bool GossipHello_npc_barnes(Player* player, Creature* _Creature)
{
// Check for death of Moroes. Uncomment when Moroes script is finished.
//ScriptedInstance* pInstance = ((ScriptedInstance*)_Creature->GetInstanceData());
//if(pInstance && (pInstance->GetData(DATA_MOROES_EVENT) >= 3))
//{
player->ADD_GOSSIP_ITEM(0, OZ_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
if(!((npc_barnesAI*)_Creature->AI())->RaidWiped)
player->SEND_GOSSIP_MENU(8970, _Creature->GetGUID());
else
player->SEND_GOSSIP_MENU(8975, _Creature->GetGUID());
//}
//else
// player->SEND_GOSSIP_MENU(8978, _Creature->GetGUID());
return true;
}
bool GossipSelect_npc_barnes(Player *player, Creature *_Creature, uint32 sender, uint32 action)
{
switch(action)
{
case GOSSIP_ACTION_INFO_DEF+1:
player->ADD_GOSSIP_ITEM(0, OZ_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
player->SEND_GOSSIP_MENU(8971, _Creature->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF+2:
player->CLOSE_GOSSIP_MENU();
((npc_barnesAI*)_Creature->AI())->StartEvent(player);
break;
}
return true;
}
/*###
# npc_berthold
####*/
#define SPELL_TELEPORT 39567
#define GOSSIP_ITEM_TELEPORT "Teleport me to the Guardian's Library"
bool GossipHello_npc_berthold(Player* player, Creature* _Creature)
{
ScriptedInstance* pInstance = ((ScriptedInstance*)_Creature->GetInstanceData());
if(pInstance && (pInstance->GetData(DATA_SHADEOFARAN_EVENT) >= 3)) // Check if Shade of Aran is dead or not
player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM_TELEPORT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
player->PlayerTalkClass->SendGossipMenu(_Creature->GetNpcTextId(), _Creature->GetGUID());
return true;
}
bool GossipSelect_npc_berthold(Player* player, Creature* _Creature, uint32 sender, uint32 action)
{
if(action == GOSSIP_ACTION_INFO_DEF + 1)
player->CastSpell(player, SPELL_TELEPORT, true);
return true;
}
void AddSC_npcs_karazhan()
{
Script* newscript;
newscript = new Script;
newscript->GetAI = GetAI_npc_barnes;
newscript->Name = "npc_barnes";
newscript->pGossipHello = GossipHello_npc_barnes;
newscript->pGossipSelect = GossipSelect_npc_barnes;
m_scripts[nrscripts++] = newscript;
newscript = new Script;
newscript->Name = "npc_berthold";
newscript->pGossipHello = GossipHello_npc_berthold;
newscript->pGossipSelect = GossipSelect_npc_berthold;
m_scripts[nrscripts++] = newscript;
}