*Update to Trinity 759.
--HG-- branch : trunk
This commit is contained in:
@@ -1,3 +1,3 @@
|
|||||||
update creature_template set scriptname='npc_infused_crystal', flags_extra=0 where entry=16364;
|
update creature_template set scriptname='npc_infused_crystal', flags_extra=0 where entry=16364;
|
||||||
update quest_template set specialflags=2, reqcreatureorgoid1=1, reqcreatureorgocount1=1 where entry=8490;
|
update quest_template set specialflags=2, reqcreatureorgoid1=0, reqcreatureorgocount1=0 where entry=8490;
|
||||||
delete from creature where id=17086;
|
delete from creature where id=17086;
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
delete from creature_template_addon where entry = 17225;
|
||||||
|
update creature_template set scriptname = 'boss_nightbane', unit_flags=0 where entry = 17225;
|
||||||
|
delete from event_scripts where id = 10951;
|
||||||
|
insert into event_scripts values
|
||||||
|
(10951,0,10,17651,180000,0,-11159,-1907.22,91.48,0);
|
||||||
@@ -342,6 +342,7 @@ extern void AddSC_boss_moroes();
|
|||||||
extern void AddSC_bosses_opera();
|
extern void AddSC_bosses_opera();
|
||||||
extern void AddSC_instance_karazhan();
|
extern void AddSC_instance_karazhan();
|
||||||
extern void AddSC_karazhan();
|
extern void AddSC_karazhan();
|
||||||
|
extern void AddSC_boss_nightbane();
|
||||||
|
|
||||||
//Loch Modan
|
//Loch Modan
|
||||||
extern void AddSC_loch_modan();
|
extern void AddSC_loch_modan();
|
||||||
@@ -1547,6 +1548,7 @@ void ScriptsInit()
|
|||||||
AddSC_bosses_opera();
|
AddSC_bosses_opera();
|
||||||
AddSC_instance_karazhan();
|
AddSC_instance_karazhan();
|
||||||
AddSC_karazhan();
|
AddSC_karazhan();
|
||||||
|
AddSC_boss_nightbane();
|
||||||
|
|
||||||
//Loch Modan
|
//Loch Modan
|
||||||
AddSC_loch_modan();
|
AddSC_loch_modan();
|
||||||
|
|||||||
@@ -740,55 +740,24 @@ void ScriptedAI::DoTeleportAll(float x, float y, float z, float o)
|
|||||||
i_pl->TeleportTo(m_creature->GetMapId(), x, y, z, o, TELE_TO_NOT_LEAVE_COMBAT);
|
i_pl->TeleportTo(m_creature->GetMapId(), x, y, z, o, TELE_TO_NOT_LEAVE_COMBAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
Unit* ScriptedAI::FindCreature(uint32 entry, uint32 range, uint32 district)
|
Unit* ScriptedAI::FindCreature(uint32 entry, float range)
|
||||||
{
|
{
|
||||||
CellPair pair(Trinity::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY()));
|
Creature* target = NULL;
|
||||||
Cell cell(pair);
|
|
||||||
cell.data.Part.reserved = district;
|
|
||||||
cell.SetNoCreate();
|
|
||||||
|
|
||||||
std::list<Creature*> NPCList;
|
|
||||||
|
|
||||||
Trinity::AllCreaturesOfEntryInRange check(m_creature, entry, range);
|
Trinity::AllCreaturesOfEntryInRange check(m_creature, entry, range);
|
||||||
Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(NPCList, check);
|
Trinity::CreatureSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(target, check);
|
||||||
TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange>, GridTypeMapContainer> visitor(searcher);
|
m_creature->VisitNearbyGridObject(range, searcher);
|
||||||
|
if(!target) error_log("SD2 ERROR: Entry: %u not found!", entry);
|
||||||
CellLock<GridReadGuard> cell_lock(cell, pair);
|
return target;
|
||||||
cell_lock->Visit(cell_lock, visitor, *(m_creature->GetMap()));
|
|
||||||
|
|
||||||
if (!NPCList.empty())
|
|
||||||
{
|
|
||||||
for(std::list<Creature*>::iterator itr = NPCList.begin(); itr != NPCList.end(); ++itr)
|
|
||||||
{
|
|
||||||
return Creature::GetUnit((*m_creature), (*itr)->GetGUID());
|
|
||||||
}
|
|
||||||
}else error_log("SD2 ERROR: Entry: %u not found!", entry); return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GameObject* ScriptedAI::FindGameObject(uint32 entry, uint32 district)
|
GameObject* ScriptedAI::FindGameObject(uint32 entry, float range)
|
||||||
{
|
{
|
||||||
CellPair pair(Trinity::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY()));
|
GameObject* target = NULL;
|
||||||
Cell cell(pair);
|
Trinity::AllGameObjectsWithEntryInGrid go_check(entry);
|
||||||
cell.data.Part.reserved = district;
|
Trinity::GameObjectSearcher<Trinity::AllGameObjectsWithEntryInGrid> searcher(target, go_check);
|
||||||
cell.SetNoCreate();
|
m_creature->VisitNearbyGridObject(range, searcher);
|
||||||
|
if(!target) error_log("SD2 ERROR: Entry: %u not found!", entry);
|
||||||
std::list<GameObject*> GOList;
|
return target;
|
||||||
|
|
||||||
Trinity::AllGameObjectsWithEntryInGrid go_check(entry);
|
|
||||||
Trinity::GameObjectListSearcher<Trinity::AllGameObjectsWithEntryInGrid> go_search(GOList, go_check);
|
|
||||||
TypeContainerVisitor
|
|
||||||
<Trinity::GameObjectListSearcher<Trinity::AllGameObjectsWithEntryInGrid>, GridTypeMapContainer> go_visit(go_search);
|
|
||||||
CellLock<GridReadGuard> cell_lock(cell, pair);
|
|
||||||
cell_lock->Visit(cell_lock, go_visit, *(m_creature->GetMap()));
|
|
||||||
|
|
||||||
if (!GOList.empty())
|
|
||||||
{
|
|
||||||
for(std::list<GameObject*>::iterator itr = GOList.begin(); itr != GOList.end(); ++itr)
|
|
||||||
{
|
|
||||||
return (*itr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else error_log("SD2 ERROR: GameObject Entry: %u not found!", entry); return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Unit* ScriptedAI::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff)
|
Unit* ScriptedAI::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff)
|
||||||
|
|||||||
@@ -149,10 +149,10 @@ struct TRINITY_DLL_DECL ScriptedAI : public CreatureAI
|
|||||||
void DoTeleportAll(float x, float y, float z, float o);
|
void DoTeleportAll(float x, float y, float z, float o);
|
||||||
|
|
||||||
//Get a single creature of given entry
|
//Get a single creature of given entry
|
||||||
Unit* FindCreature(uint32 entry, uint32 range, uint32 district = ALL_DISTRICT);
|
Unit* FindCreature(uint32 entry, float range);
|
||||||
|
|
||||||
//Get a single gameobject of given entry
|
//Get a single gameobject of given entry
|
||||||
GameObject* FindGameObject(uint32 entry, uint32 district = ALL_DISTRICT);
|
GameObject* FindGameObject(uint32 entry, float range);
|
||||||
|
|
||||||
//Returns friendly unit with the most amount of hp missing from max hp
|
//Returns friendly unit with the most amount of hp missing from max hp
|
||||||
Unit* DoSelectLowestHpFriendly(float range, uint32 MinHPDiff = 1);
|
Unit* DoSelectLowestHpFriendly(float range, uint32 MinHPDiff = 1);
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ EndContentData */
|
|||||||
|
|
||||||
#define SAY_PROGRESS_1 "Ok, $N. Follow me to the cave where I'll attempt to harness the power of the rune stone into these goggles."
|
#define SAY_PROGRESS_1 "Ok, $N. Follow me to the cave where I'll attempt to harness the power of the rune stone into these goggles."
|
||||||
#define SAY_PROGRESS_2 "I discovered this cave on our first day here. I believe the energy in the stone can be used to our advantage."
|
#define SAY_PROGRESS_2 "I discovered this cave on our first day here. I believe the energy in the stone can be used to our advantage."
|
||||||
#define SAY_PROGRESS_3 "I'll begin drawing energy from the stone. Your job, $N, i to defend me. This place is cursed... trust me."
|
#define SAY_PROGRESS_3 "I'll begin drawing energy from the stone. Your job, $N, is to defend me. This place is cursed... trust me."
|
||||||
#define EMOTE_PROGRESS_4 "begins tinkering with the goggles before the stone."
|
#define EMOTE_PROGRESS_4 "begins tinkering with the goggles before the stone."
|
||||||
#define SAY_AGGRO "Help!!! Get these things off me so I can get my work done!"
|
#define SAY_AGGRO "Help!!! Get these things off me so I can get my work done!"
|
||||||
#define SAY_PROGRESS_5 "Almost done! Just a little longer!"
|
#define SAY_PROGRESS_5 "Almost done! Just a little longer!"
|
||||||
@@ -61,10 +61,8 @@ struct TRINITY_DLL_DECL npc_professor_phizzlethorpeAI : public npc_escortAI
|
|||||||
case 8:DoTextEmote(EMOTE_PROGRESS_4, NULL);break;
|
case 8:DoTextEmote(EMOTE_PROGRESS_4, NULL);break;
|
||||||
case 9:
|
case 9:
|
||||||
{
|
{
|
||||||
Creature* sum1 = m_creature->SummonCreature(MOB_VENGEFUL_SURGE, -2052.96, -2142.49, 20.15, 1.0f, TEMPSUMMON_DEAD_DESPAWN, 0);
|
m_creature->SummonCreature(MOB_VENGEFUL_SURGE, -2052.96, -2142.49, 20.15, 1.0f, TEMPSUMMON_CORPSE_DESPAWN, 0);
|
||||||
Creature* sum2 = m_creature->SummonCreature(MOB_VENGEFUL_SURGE, -2052.96, -2142.49, 20.15, 1.0f, TEMPSUMMON_DEAD_DESPAWN, 0);
|
m_creature->SummonCreature(MOB_VENGEFUL_SURGE, -2052.96, -2142.49, 20.15, 1.0f, TEMPSUMMON_CORPSE_DESPAWN, 0);
|
||||||
sum1->Attack(m_creature, true);
|
|
||||||
sum2->Attack(m_creature, true);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 10:DoSay(SAY_PROGRESS_5, LANG_UNIVERSAL, player, true);break;
|
case 10:DoSay(SAY_PROGRESS_5, LANG_UNIVERSAL, player, true);break;
|
||||||
@@ -73,11 +71,17 @@ struct TRINITY_DLL_DECL npc_professor_phizzlethorpeAI : public npc_escortAI
|
|||||||
case 20:
|
case 20:
|
||||||
DoTextEmote(EMOTE_PROGRESS_8, NULL);
|
DoTextEmote(EMOTE_PROGRESS_8, NULL);
|
||||||
DoSay(SAY_PROGRESS_9, LANG_UNIVERSAL, player, true);
|
DoSay(SAY_PROGRESS_9, LANG_UNIVERSAL, player, true);
|
||||||
|
if(player)
|
||||||
((Player*)player)->GroupEventHappens(QUEST_SUNKEN_TREASURE, m_creature);
|
((Player*)player)->GroupEventHappens(QUEST_SUNKEN_TREASURE, m_creature);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JustSummoned(Creature *summoned)
|
||||||
|
{
|
||||||
|
summoned->AI()->AttackStart(m_creature);
|
||||||
|
}
|
||||||
|
|
||||||
void Reset(){}
|
void Reset(){}
|
||||||
|
|
||||||
void Aggro(Unit* who)
|
void Aggro(Unit* who)
|
||||||
|
|||||||
@@ -1879,7 +1879,7 @@ void boss_illidan_stormrageAI::JustSummoned(Creature* summon)
|
|||||||
Unit *target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0, 999, true);
|
Unit *target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0, 999, true);
|
||||||
if(!target || target->HasAura(SPELL_PARASITIC_SHADOWFIEND, 0)
|
if(!target || target->HasAura(SPELL_PARASITIC_SHADOWFIEND, 0)
|
||||||
|| target->HasAura(SPELL_PARASITIC_SHADOWFIEND2, 0))
|
|| target->HasAura(SPELL_PARASITIC_SHADOWFIEND2, 0))
|
||||||
target = SelectUnit(SELECT_TARGET_RANDOM, 0, 999, true);
|
target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0, 999, true);
|
||||||
if(target)
|
if(target)
|
||||||
summon->AI()->AttackStart(target);
|
summon->AI()->AttackStart(target);
|
||||||
}break;
|
}break;
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ struct TRINITY_DLL_DECL npc_ranger_lilathaAI : public npc_escortAI
|
|||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
|
m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
|
||||||
GameObject* Cage = FindGameObject(GO_CAGE);
|
GameObject* Cage = FindGameObject(GO_CAGE, 99);
|
||||||
if(Cage)
|
if(Cage)
|
||||||
Cage->SetGoState(0);
|
Cage->SetGoState(0);
|
||||||
DoScriptText(SAY_START, m_creature, player);
|
DoScriptText(SAY_START, m_creature, player);
|
||||||
@@ -212,7 +212,7 @@ struct TRINITY_DLL_DECL npc_ranger_lilathaAI : public npc_escortAI
|
|||||||
if (!IsBeingEscorted)
|
if (!IsBeingEscorted)
|
||||||
m_creature->setFaction(1602);
|
m_creature->setFaction(1602);
|
||||||
|
|
||||||
GameObject* Cage = FindGameObject(GO_CAGE);
|
GameObject* Cage = FindGameObject(GO_CAGE, 99);
|
||||||
if(Cage)
|
if(Cage)
|
||||||
Cage->SetGoState(1);
|
Cage->SetGoState(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,18 +16,389 @@
|
|||||||
|
|
||||||
/* ScriptData
|
/* ScriptData
|
||||||
SDName: Boss_Nightbane
|
SDName: Boss_Nightbane
|
||||||
SD%Complete: 0
|
SD%Complete: 50
|
||||||
SDComment: Place holder
|
SDComment: skelleton adds, optimice some "if"s, timers, rain of bones applied self(!?)
|
||||||
SDCategory: Karazhan
|
SDCategory: Karazhan
|
||||||
EndScriptData */
|
EndScriptData */
|
||||||
|
|
||||||
#include "precompiled.h"
|
#include "precompiled.h"
|
||||||
|
#include "def_karazhan.h"
|
||||||
|
|
||||||
|
//phase 1
|
||||||
#define SPELL_BELLOWING_ROAR 39427
|
#define SPELL_BELLOWING_ROAR 39427
|
||||||
#define SPELL_CHARRED_EARTH 30129 //Also 30209 (Target Charred Earth) triggers this
|
#define SPELL_CHARRED_EARTH 30129 //Also 30209 (Target Charred Earth) triggers this
|
||||||
#define SPELL_DISTRACTING_ASH 30130
|
#define SPELL_DISTRACTING_ASH 30130
|
||||||
#define SPELL_SMOLDERING_BREATH 30210
|
#define SPELL_SMOLDERING_BREATH 30210
|
||||||
#define SPELL_TAIL_SWEEP 25653
|
#define SPELL_TAIL_SWEEP 25653
|
||||||
|
//phase 2
|
||||||
#define SPELL_RAIN_OF_BONES 37098
|
#define SPELL_RAIN_OF_BONES 37098
|
||||||
#define SPELL_SMOKING_BLAST 37057
|
#define SPELL_SMOKING_BLAST 37057
|
||||||
#define SPELL_FIREBALL_BARRAGE 30282
|
#define SPELL_FIREBALL_BARRAGE 30282
|
||||||
|
#define SPELL_SEARING_CINDERS 30127
|
||||||
|
|
||||||
|
float IntroWay[8][3] =
|
||||||
|
{
|
||||||
|
{-11053.37,-1794.48,149},
|
||||||
|
{-11141.07,-1841.40,125},
|
||||||
|
{-11187.28,-1890.23,125},
|
||||||
|
{-11189.20,-1931.25,125},
|
||||||
|
{-11153.76,-1948.93,125},
|
||||||
|
{-11128.73,-1929.75,125},
|
||||||
|
{-11140 , -1915 ,122},
|
||||||
|
{-11163 , -1903 ,91.473}
|
||||||
|
};
|
||||||
|
|
||||||
|
//float IntroWay[5][3] =
|
||||||
|
//{
|
||||||
|
// {-11000.00, -1765.75, 140.40},
|
||||||
|
// {-11000.00, -1765.75, 171.00},
|
||||||
|
// {-11173.67, -1832.26, 117.76},
|
||||||
|
// {-11142.75, -1916.78, 119.769},
|
||||||
|
// {-11161.91, -1911.148, 91.473}
|
||||||
|
//};
|
||||||
|
|
||||||
|
struct TRINITY_DLL_DECL boss_nightbaneAI : public ScriptedAI
|
||||||
|
{
|
||||||
|
boss_nightbaneAI(Creature* c) : ScriptedAI(c)
|
||||||
|
{
|
||||||
|
pInstance = ((ScriptedInstance*)c->GetInstanceData());
|
||||||
|
intro = true;
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptedInstance* pInstance;
|
||||||
|
|
||||||
|
uint32 phase;
|
||||||
|
|
||||||
|
bool rainbones;
|
||||||
|
|
||||||
|
uint32 bellowingroar_timer;
|
||||||
|
uint32 charredearth_timer;
|
||||||
|
uint32 distractingash_timer;
|
||||||
|
uint32 smolderingbreath_timer;
|
||||||
|
uint32 tailsweep_timer;
|
||||||
|
uint32 rainofbones_timer;
|
||||||
|
uint32 smokingblast_timer;
|
||||||
|
uint32 fireballbarrage_timer;
|
||||||
|
uint32 searingcinders_timer;
|
||||||
|
|
||||||
|
uint32 fly_count;
|
||||||
|
uint32 fly_timer;
|
||||||
|
|
||||||
|
bool intro;
|
||||||
|
bool flying;
|
||||||
|
uint32 wait_timer;
|
||||||
|
uint32 MovePhase;
|
||||||
|
|
||||||
|
void Reset()
|
||||||
|
{
|
||||||
|
phase =1;
|
||||||
|
bellowingroar_timer = 30000;
|
||||||
|
charredearth_timer = 15000;
|
||||||
|
distractingash_timer = 20000;
|
||||||
|
smolderingbreath_timer = 10000;
|
||||||
|
tailsweep_timer = 12000;
|
||||||
|
rainofbones_timer = 10000;
|
||||||
|
smokingblast_timer = 20000;
|
||||||
|
fireballbarrage_timer = 13000;
|
||||||
|
searingcinders_timer = 14000;
|
||||||
|
|
||||||
|
fly_count = 0;
|
||||||
|
|
||||||
|
m_creature->SetSpeed(MOVE_RUN,2);
|
||||||
|
m_creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING);
|
||||||
|
m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||||
|
m_creature->setActive(true);
|
||||||
|
wait_timer = 1000;
|
||||||
|
MovePhase = 0;
|
||||||
|
|
||||||
|
if(pInstance)
|
||||||
|
pInstance->SetData(DATA_NIGHTBANE_EVENT, NOT_STARTED);
|
||||||
|
|
||||||
|
flying = false;
|
||||||
|
|
||||||
|
if(!intro)
|
||||||
|
{
|
||||||
|
m_creature->SetHomePosition(IntroWay[7][0],IntroWay[7][1],IntroWay[7][2],0);
|
||||||
|
m_creature->GetMotionMaster()->MoveTargetedHome();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Aggro(Unit *who)
|
||||||
|
{
|
||||||
|
if(pInstance)
|
||||||
|
pInstance->SetData(DATA_NIGHTBANE_EVENT, IN_PROGRESS);
|
||||||
|
}
|
||||||
|
void AttackStart(Unit* who)
|
||||||
|
{
|
||||||
|
if(!intro && !flying)
|
||||||
|
ScriptedAI::AttackStart(who);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JustDied(Unit* killer)
|
||||||
|
{
|
||||||
|
if(pInstance)
|
||||||
|
pInstance->SetData(DATA_NIGHTBANE_EVENT, DONE);
|
||||||
|
}
|
||||||
|
void MoveInLineOfSight(Unit *who)
|
||||||
|
{
|
||||||
|
if(!intro && !flying)
|
||||||
|
{
|
||||||
|
if(!m_creature->getVictim() && m_creature->canStartAttack(who))
|
||||||
|
ScriptedAI::AttackStart(who);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovementInform(uint32 type, uint32 id)
|
||||||
|
{
|
||||||
|
if(type != POINT_MOTION_TYPE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(intro)
|
||||||
|
{
|
||||||
|
if(id >= 8)
|
||||||
|
{
|
||||||
|
intro = false;
|
||||||
|
m_creature->SetHomePosition(IntroWay[7][0],IntroWay[7][1],IntroWay[7][2],0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_timer = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(flying)
|
||||||
|
{
|
||||||
|
if(id == 0)
|
||||||
|
{
|
||||||
|
flying = false;
|
||||||
|
phase = 2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(id == 3)
|
||||||
|
{
|
||||||
|
MovePhase = 4;
|
||||||
|
wait_timer = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(id == 8)
|
||||||
|
{
|
||||||
|
flying = false;
|
||||||
|
phase = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_timer = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAI(const uint32 diff)
|
||||||
|
{
|
||||||
|
if(wait_timer)
|
||||||
|
if(wait_timer < diff)
|
||||||
|
{
|
||||||
|
if(intro)
|
||||||
|
{
|
||||||
|
if(MovePhase >= 7)
|
||||||
|
{
|
||||||
|
m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING);
|
||||||
|
m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
|
||||||
|
m_creature->GetMotionMaster()->MovePoint(8,IntroWay[7][0],IntroWay[7][1],IntroWay[7][2]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_creature->GetMotionMaster()->MovePoint(MovePhase,IntroWay[MovePhase][0],IntroWay[MovePhase][1],IntroWay[MovePhase][2]);
|
||||||
|
MovePhase++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(flying)
|
||||||
|
{
|
||||||
|
if(MovePhase >= 7)
|
||||||
|
{
|
||||||
|
m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING);
|
||||||
|
m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
|
||||||
|
m_creature->GetMotionMaster()->MovePoint(8,IntroWay[7][0],IntroWay[7][1],IntroWay[7][2]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_creature->GetMotionMaster()->MovePoint(MovePhase,IntroWay[MovePhase][0],IntroWay[MovePhase][1],IntroWay[MovePhase][2]);
|
||||||
|
MovePhase++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_timer = 0;
|
||||||
|
}else wait_timer -= diff;
|
||||||
|
|
||||||
|
if(!m_creature->SelectHostilTarget())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(flying)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Phase 1 "GROUND FIGHT"
|
||||||
|
if(phase == 1)
|
||||||
|
{
|
||||||
|
m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
|
||||||
|
if (bellowingroar_timer < diff)
|
||||||
|
{
|
||||||
|
DoCast(m_creature->getVictim(),SPELL_BELLOWING_ROAR);
|
||||||
|
bellowingroar_timer = 30000+rand()%10000 ; //Timer
|
||||||
|
}else bellowingroar_timer -= diff;
|
||||||
|
|
||||||
|
if (smolderingbreath_timer < diff)
|
||||||
|
{
|
||||||
|
DoCast(m_creature->getVictim(),SPELL_SMOLDERING_BREATH);
|
||||||
|
smolderingbreath_timer = 20000;//timer
|
||||||
|
|
||||||
|
}else smolderingbreath_timer -= diff;
|
||||||
|
|
||||||
|
if (charredearth_timer < diff)
|
||||||
|
{
|
||||||
|
Unit* target = NULL;
|
||||||
|
target = SelectUnit(SELECT_TARGET_RANDOM,0);
|
||||||
|
DoCast(target,SPELL_CHARRED_EARTH);
|
||||||
|
charredearth_timer = 20000; //timer
|
||||||
|
}else charredearth_timer -= diff;
|
||||||
|
|
||||||
|
if (tailsweep_timer < diff)
|
||||||
|
{
|
||||||
|
Unit* target = NULL;
|
||||||
|
target = SelectUnit(SELECT_TARGET_RANDOM,0);
|
||||||
|
|
||||||
|
if (!m_creature->HasInArc( M_PI, target))
|
||||||
|
DoCast(target,SPELL_TAIL_SWEEP);
|
||||||
|
tailsweep_timer = 15000;//timer
|
||||||
|
}else tailsweep_timer -= diff;
|
||||||
|
|
||||||
|
if (searingcinders_timer < diff)
|
||||||
|
{
|
||||||
|
Unit* target = NULL;
|
||||||
|
target = SelectUnit(SELECT_TARGET_RANDOM,0);
|
||||||
|
|
||||||
|
DoCast(target,SPELL_SEARING_CINDERS);
|
||||||
|
searingcinders_timer = 10000; //timer
|
||||||
|
}else searingcinders_timer -= diff;
|
||||||
|
|
||||||
|
uint32 prozent;
|
||||||
|
prozent = (m_creature->GetHealth()*100) / m_creature->GetMaxHealth();
|
||||||
|
|
||||||
|
if (prozent < 75 && fly_count == 0) // first take off 75%
|
||||||
|
{
|
||||||
|
m_creature->InterruptSpell(CURRENT_GENERIC_SPELL);
|
||||||
|
m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
|
||||||
|
m_creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING);
|
||||||
|
(*m_creature).GetMotionMaster()->Clear(false);
|
||||||
|
(*m_creature).GetMotionMaster()->MovePoint(0,IntroWay[2][0],IntroWay[2][1],IntroWay[2][2]);
|
||||||
|
flying = true;
|
||||||
|
|
||||||
|
fly_timer = 45000+rand()%15000;
|
||||||
|
fly_count++;
|
||||||
|
|
||||||
|
rainofbones_timer = 5000;
|
||||||
|
rainbones = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prozent < 50 && fly_count == 1) // secound take off 50%
|
||||||
|
{
|
||||||
|
m_creature->InterruptSpell(CURRENT_GENERIC_SPELL);
|
||||||
|
m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
|
||||||
|
m_creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING);
|
||||||
|
(*m_creature).GetMotionMaster()->Clear(false);
|
||||||
|
(*m_creature).GetMotionMaster()->MovePoint(0,IntroWay[2][0],IntroWay[2][1],IntroWay[2][2]);
|
||||||
|
|
||||||
|
flying = true;
|
||||||
|
fly_timer = 45000+rand()%15000;
|
||||||
|
fly_count++;
|
||||||
|
|
||||||
|
rainofbones_timer = 5000;
|
||||||
|
rainbones = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prozent < 25 && fly_count == 2) // third take off 25%
|
||||||
|
{
|
||||||
|
m_creature->InterruptSpell(CURRENT_GENERIC_SPELL);
|
||||||
|
m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
|
||||||
|
m_creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING);
|
||||||
|
(*m_creature).GetMotionMaster()->Clear(false);
|
||||||
|
(*m_creature).GetMotionMaster()->MovePoint(0,IntroWay[2][0],IntroWay[2][1],IntroWay[2][2]);
|
||||||
|
|
||||||
|
flying = true;
|
||||||
|
//phase = 2;
|
||||||
|
fly_timer = 45000+rand()%15000;
|
||||||
|
fly_count++;
|
||||||
|
|
||||||
|
rainofbones_timer = 5000;
|
||||||
|
rainbones = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Phase 2 "FLYING FIGHT"
|
||||||
|
if (phase == 2)
|
||||||
|
{
|
||||||
|
if (!rainbones)
|
||||||
|
{
|
||||||
|
if (rainofbones_timer < diff && !rainbones) // only once at the beginning of phase 2
|
||||||
|
{
|
||||||
|
DoCast(m_creature->getVictim(),SPELL_RAIN_OF_BONES);
|
||||||
|
rainbones = true;
|
||||||
|
smokingblast_timer = 20000;
|
||||||
|
}else rainofbones_timer -= diff;
|
||||||
|
|
||||||
|
if (distractingash_timer < diff)
|
||||||
|
{
|
||||||
|
Unit* target = NULL;
|
||||||
|
target = SelectUnit(SELECT_TARGET_RANDOM,0);
|
||||||
|
|
||||||
|
DoCast(target,SPELL_DISTRACTING_ASH);
|
||||||
|
distractingash_timer = 2000;//timer wrong
|
||||||
|
}else distractingash_timer -= diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rainbones)
|
||||||
|
{
|
||||||
|
if (smokingblast_timer < diff)
|
||||||
|
{
|
||||||
|
DoCast(m_creature->getVictim(),SPELL_SMOKING_BLAST);
|
||||||
|
smokingblast_timer = 1500 ; //timer wrong
|
||||||
|
}else smokingblast_timer -= diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fireballbarrage_timer < diff)
|
||||||
|
{
|
||||||
|
Unit* target = NULL;
|
||||||
|
target = SelectUnit(SELECT_TARGET_FARTHEST,0);
|
||||||
|
|
||||||
|
DoCast(target,SPELL_FIREBALL_BARRAGE);
|
||||||
|
fireballbarrage_timer = 20000; //Timer
|
||||||
|
}else fireballbarrage_timer -= diff;
|
||||||
|
|
||||||
|
if (fly_timer < diff) //landing
|
||||||
|
{
|
||||||
|
//m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
|
||||||
|
//m_creature->SetHover(false);
|
||||||
|
(*m_creature).GetMotionMaster()->Clear(false);
|
||||||
|
m_creature->GetMotionMaster()->MovePoint(3,IntroWay[3][0],IntroWay[3][1],IntroWay[3][2]);
|
||||||
|
flying = true;
|
||||||
|
//wait_timer = 1;
|
||||||
|
//phase = 1;
|
||||||
|
}else fly_timer -= diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CreatureAI* GetAI_boss_nightbane(Creature *_Creature)
|
||||||
|
{
|
||||||
|
return new boss_nightbaneAI (_Creature);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddSC_boss_nightbane()
|
||||||
|
{
|
||||||
|
Script *newscript;
|
||||||
|
newscript = new Script;
|
||||||
|
newscript->Name="boss_nightbane";
|
||||||
|
newscript->GetAI = GetAI_boss_nightbane;
|
||||||
|
newscript->RegisterSelf();
|
||||||
|
}
|
||||||
@@ -59,7 +59,8 @@ struct TRINITY_DLL_DECL instance_karazhan : public ScriptedInstance
|
|||||||
uint64 MassiveDoor; // Door at Netherspite
|
uint64 MassiveDoor; // Door at Netherspite
|
||||||
uint64 GamesmansDoor; // Door before Chess
|
uint64 GamesmansDoor; // Door before Chess
|
||||||
uint64 GamesmansExitDoor; // Door after Chess
|
uint64 GamesmansExitDoor; // Door after Chess
|
||||||
uint64 NetherspaceDoor; // Door at Malchezaar
|
uint64 NetherspaceDoor; // Door at Malchezaar
|
||||||
|
uint64 MastersTerraceDoor[2];
|
||||||
|
|
||||||
uint64 ImageGUID;
|
uint64 ImageGUID;
|
||||||
|
|
||||||
@@ -84,6 +85,8 @@ struct TRINITY_DLL_DECL instance_karazhan : public ScriptedInstance
|
|||||||
GamesmansDoor = 0;
|
GamesmansDoor = 0;
|
||||||
GamesmansExitDoor = 0;
|
GamesmansExitDoor = 0;
|
||||||
NetherspaceDoor = 0;
|
NetherspaceDoor = 0;
|
||||||
|
MastersTerraceDoor[0]= 0;
|
||||||
|
MastersTerraceDoor[1]= 0;
|
||||||
|
|
||||||
ImageGUID = 0;
|
ImageGUID = 0;
|
||||||
}
|
}
|
||||||
@@ -199,6 +202,8 @@ struct TRINITY_DLL_DECL instance_karazhan : public ScriptedInstance
|
|||||||
case 184276: GamesmansDoor = go->GetGUID(); break;
|
case 184276: GamesmansDoor = go->GetGUID(); break;
|
||||||
case 184277: GamesmansExitDoor = go->GetGUID(); break;
|
case 184277: GamesmansExitDoor = go->GetGUID(); break;
|
||||||
case 185134: NetherspaceDoor = go->GetGUID(); break;
|
case 185134: NetherspaceDoor = go->GetGUID(); break;
|
||||||
|
case 184274: MastersTerraceDoor[0] = go->GetGUID(); break;
|
||||||
|
case 184280: MastersTerraceDoor[1] = go->GetGUID(); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(OperaEvent)
|
switch(OperaEvent)
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ ChatCommand * ChatHandler::getCommandTable()
|
|||||||
static ChatCommand serverSetCommandTable[] =
|
static ChatCommand serverSetCommandTable[] =
|
||||||
{
|
{
|
||||||
{ "loglevel", SEC_CONSOLE, true, &ChatHandler::HandleServerSetLogLevelCommand, "", NULL },
|
{ "loglevel", SEC_CONSOLE, true, &ChatHandler::HandleServerSetLogLevelCommand, "", NULL },
|
||||||
|
{ "difftime", SEC_CONSOLE, true, &ChatHandler::HandleServerSetDiffTimeCommand, "", NULL },
|
||||||
{ "motd", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerSetMotdCommand, "", NULL },
|
{ "motd", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerSetMotdCommand, "", NULL },
|
||||||
{ NULL, 0, false, NULL, "", NULL }
|
{ NULL, 0, false, NULL, "", NULL }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -288,6 +288,7 @@ class ChatHandler
|
|||||||
bool HandleServerRestartCommand(const char* args);
|
bool HandleServerRestartCommand(const char* args);
|
||||||
bool HandleServerSetMotdCommand(const char* args);
|
bool HandleServerSetMotdCommand(const char* args);
|
||||||
bool HandleServerSetLogLevelCommand(const char* args);
|
bool HandleServerSetLogLevelCommand(const char* args);
|
||||||
|
bool HandleServerSetDiffTimeCommand(const char* args);
|
||||||
bool HandleServerShutDownCommand(const char* args);
|
bool HandleServerShutDownCommand(const char* args);
|
||||||
bool HandleServerShutDownCancelCommand(const char* args);
|
bool HandleServerShutDownCancelCommand(const char* args);
|
||||||
|
|
||||||
|
|||||||
@@ -778,8 +778,7 @@ LootStoreItem const * LootTemplate::LootGroup::Roll() const
|
|||||||
return &ExplicitlyChanced[i];
|
return &ExplicitlyChanced[i];
|
||||||
|
|
||||||
ItemPrototype const *pProto = objmgr.GetItemPrototype(ExplicitlyChanced[i].itemid);
|
ItemPrototype const *pProto = objmgr.GetItemPrototype(ExplicitlyChanced[i].itemid);
|
||||||
float qualityMultiplier = pProto ? sWorld.getRate(qualityToRate[pProto->Quality]) : 1.0f;
|
Roll -= ExplicitlyChanced[i].chance;
|
||||||
Roll -= ExplicitlyChanced[i].chance * qualityMultiplier;
|
|
||||||
if (Roll < 0)
|
if (Roll < 0)
|
||||||
return &ExplicitlyChanced[i];
|
return &ExplicitlyChanced[i];
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -1778,7 +1778,9 @@ bool InstanceMap::Add(Player *player)
|
|||||||
{
|
{
|
||||||
sLog.outError("InstanceMap::Add: player %s(%d) is being put in instance %d,%d,%d,%d,%d,%d but he is in group %d and is bound to instance %d,%d,%d,%d,%d,%d!", player->GetName(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), GUID_LOPART(pGroup->GetLeaderGUID()), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset());
|
sLog.outError("InstanceMap::Add: player %s(%d) is being put in instance %d,%d,%d,%d,%d,%d but he is in group %d and is bound to instance %d,%d,%d,%d,%d,%d!", player->GetName(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), GUID_LOPART(pGroup->GetLeaderGUID()), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset());
|
||||||
if(groupBind) sLog.outError("InstanceMap::Add: the group is bound to instance %d,%d,%d,%d,%d,%d", groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty(), groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount(), groupBind->save->CanReset());
|
if(groupBind) sLog.outError("InstanceMap::Add: the group is bound to instance %d,%d,%d,%d,%d,%d", groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty(), groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount(), groupBind->save->CanReset());
|
||||||
player->UnbindInstance(GetId(), GetSpawnMode());
|
sLog.outError("InstanceMap::Add: do not let player %s enter instance otherwise crash will happen", player->GetName());
|
||||||
|
return false;
|
||||||
|
//player->UnbindInstance(GetId(), GetSpawnMode());
|
||||||
//assert(false);
|
//assert(false);
|
||||||
}
|
}
|
||||||
// bind to the group or keep using the group save
|
// bind to the group or keep using the group save
|
||||||
|
|||||||
@@ -1004,6 +1004,11 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
|
|||||||
{
|
{
|
||||||
m_caster->CombatStart(unit);
|
m_caster->CombatStart(unit);
|
||||||
}
|
}
|
||||||
|
else if(spellmgr.GetSpellCustomAttr(m_spellInfo->Id) & SPELL_ATTR_CU_AURA_CC)
|
||||||
|
{
|
||||||
|
if(!unit->IsStandState())
|
||||||
|
unit->SetStandState(PLAYER_STATE_NONE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5956,6 +5956,13 @@ void Aura::PeriodicTick()
|
|||||||
int32 gain = pCaster->ModifyPower(power,gain_amount);
|
int32 gain = pCaster->ModifyPower(power,gain_amount);
|
||||||
m_target->AddThreat(pCaster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
|
m_target->AddThreat(pCaster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
|
||||||
}
|
}
|
||||||
|
// Mark of Kaz'rogal
|
||||||
|
if(GetId() == 31447 && m_target->GetPower(power) == 0)
|
||||||
|
{
|
||||||
|
m_target->CastSpell(m_target, 31463, true, 0, this);
|
||||||
|
// Remove aura
|
||||||
|
SetAuraDuration(0);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPELL_AURA_PERIODIC_ENERGIZE:
|
case SPELL_AURA_PERIODIC_ENERGIZE:
|
||||||
|
|||||||
+3
-2
@@ -7612,7 +7612,8 @@ uint32 Unit::SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount,
|
|||||||
if (spellProto->Id == 15290 || spellProto->Id == 39373 ||
|
if (spellProto->Id == 15290 || spellProto->Id == 39373 ||
|
||||||
spellProto->Id == 33778 || spellProto->Id == 379 ||
|
spellProto->Id == 33778 || spellProto->Id == 379 ||
|
||||||
spellProto->Id == 38395 || spellProto->Id == 40972 ||
|
spellProto->Id == 38395 || spellProto->Id == 40972 ||
|
||||||
spellProto->Id == 22845 || spellProto->Id == 33504)
|
spellProto->Id == 22845 || spellProto->Id == 33504 ||
|
||||||
|
spellProto->Id == 34299)
|
||||||
return healamount;
|
return healamount;
|
||||||
|
|
||||||
int32 AdvertisedBenefit = SpellBaseHealingBonus(GetSpellSchoolMask(spellProto));
|
int32 AdvertisedBenefit = SpellBaseHealingBonus(GetSpellSchoolMask(spellProto));
|
||||||
@@ -8238,7 +8239,7 @@ void Unit::SetInCombatWith(Unit* enemy)
|
|||||||
|
|
||||||
void Unit::CombatStart(Unit* target)
|
void Unit::CombatStart(Unit* target)
|
||||||
{
|
{
|
||||||
if(!target->IsStandState() && !target->hasUnitState(UNIT_STAT_STUNNED))
|
if(!target->IsStandState()/* && !target->hasUnitState(UNIT_STAT_STUNNED)*/)
|
||||||
target->SetStandState(PLAYER_STATE_NONE);
|
target->SetStandState(PLAYER_STATE_NONE);
|
||||||
|
|
||||||
//Call creature group update
|
//Call creature group update
|
||||||
|
|||||||
@@ -422,6 +422,7 @@ class World
|
|||||||
uint32 GetUptime() const { return uint32(m_gameTime - m_startTime); }
|
uint32 GetUptime() const { return uint32(m_gameTime - m_startTime); }
|
||||||
/// Update time
|
/// Update time
|
||||||
uint32 GetUpdateTime() const { return m_updateTime; }
|
uint32 GetUpdateTime() const { return m_updateTime; }
|
||||||
|
void SetRecordDiffInterval(int32 t) { if(t >= 0) m_configs[CONFIG_INTERVAL_LOG_UPDATE] = (uint32)t; }
|
||||||
|
|
||||||
/// Get the maximum skill level a player can reach
|
/// Get the maximum skill level a player can reach
|
||||||
uint16 GetConfigMaxSkillValue() const
|
uint16 GetConfigMaxSkillValue() const
|
||||||
|
|||||||
@@ -0,0 +1,375 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// \addtogroup Trinityd
|
||||||
|
/// @{
|
||||||
|
/// \file
|
||||||
|
|
||||||
|
#include "Common.h"
|
||||||
|
#include "Language.h"
|
||||||
|
#include "Log.h"
|
||||||
|
#include "World.h"
|
||||||
|
#include "ScriptCalls.h"
|
||||||
|
#include "ObjectMgr.h"
|
||||||
|
#include "WorldSession.h"
|
||||||
|
#include "Config/ConfigEnv.h"
|
||||||
|
#include "Util.h"
|
||||||
|
#include "AccountMgr.h"
|
||||||
|
#include "CliRunnable.h"
|
||||||
|
#include "MapManager.h"
|
||||||
|
#include "Player.h"
|
||||||
|
#include "Chat.h"
|
||||||
|
|
||||||
|
void utf8print(const char* str)
|
||||||
|
{
|
||||||
|
#if PLATFORM == PLATFORM_WINDOWS
|
||||||
|
wchar_t wtemp_buf[6000];
|
||||||
|
size_t wtemp_len = 6000-1;
|
||||||
|
if(!Utf8toWStr(str,strlen(str),wtemp_buf,wtemp_len))
|
||||||
|
return;
|
||||||
|
|
||||||
|
char temp_buf[6000];
|
||||||
|
CharToOemBuffW(&wtemp_buf[0],&temp_buf[0],wtemp_len+1);
|
||||||
|
printf(temp_buf);
|
||||||
|
#else
|
||||||
|
printf(str);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Delete a user account and all associated characters in this realm
|
||||||
|
/// \todo This function has to be enhanced to respect the login/realm split (delete char, delete account chars in realm, delete account chars in realm then delete account
|
||||||
|
bool ChatHandler::HandleAccountDeleteCommand(const char* args)
|
||||||
|
{
|
||||||
|
if(!*args)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
///- Get the account name from the command line
|
||||||
|
char *account_name_str=strtok ((char*)args," ");
|
||||||
|
if (!account_name_str)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::string account_name = account_name_str;
|
||||||
|
if(!AccountMgr::normilizeString(account_name))
|
||||||
|
{
|
||||||
|
PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str());
|
||||||
|
SetSentErrorMessage(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 account_id = accmgr.GetId(account_name);
|
||||||
|
if(!account_id)
|
||||||
|
{
|
||||||
|
PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str());
|
||||||
|
SetSentErrorMessage(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Commands not recommended call from chat, but support anyway
|
||||||
|
if(m_session)
|
||||||
|
{
|
||||||
|
uint32 targetSecurity = accmgr.GetSecurity(account_id);
|
||||||
|
|
||||||
|
/// can delete only for account with less security
|
||||||
|
/// This is also reject self apply in fact
|
||||||
|
if (targetSecurity >= m_session->GetSecurity())
|
||||||
|
{
|
||||||
|
SendSysMessage (LANG_YOURS_SECURITY_IS_LOW);
|
||||||
|
SetSentErrorMessage (true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountOpResult result = accmgr.DeleteAccount(account_id);
|
||||||
|
switch(result)
|
||||||
|
{
|
||||||
|
case AOR_OK:
|
||||||
|
PSendSysMessage(LANG_ACCOUNT_DELETED,account_name.c_str());
|
||||||
|
break;
|
||||||
|
case AOR_NAME_NOT_EXIST:
|
||||||
|
PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str());
|
||||||
|
SetSentErrorMessage(true);
|
||||||
|
return false;
|
||||||
|
case AOR_DB_INTERNAL_ERROR:
|
||||||
|
PSendSysMessage(LANG_ACCOUNT_NOT_DELETED_SQL_ERROR,account_name.c_str());
|
||||||
|
SetSentErrorMessage(true);
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
PSendSysMessage(LANG_ACCOUNT_NOT_DELETED,account_name.c_str());
|
||||||
|
SetSentErrorMessage(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ChatHandler::HandleCharacterDeleteCommand(const char* args)
|
||||||
|
{
|
||||||
|
if(!*args)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
char *character_name_str = strtok((char*)args," ");
|
||||||
|
if(!character_name_str)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::string character_name = character_name_str;
|
||||||
|
if(!normalizePlayerName(character_name))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint64 character_guid;
|
||||||
|
uint32 account_id;
|
||||||
|
|
||||||
|
Player *player = objmgr.GetPlayer(character_name.c_str());
|
||||||
|
if(player)
|
||||||
|
{
|
||||||
|
character_guid = player->GetGUID();
|
||||||
|
account_id = player->GetSession()->GetAccountId();
|
||||||
|
player->GetSession()->KickPlayer();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
character_guid = objmgr.GetPlayerGUIDByName(character_name);
|
||||||
|
if(!character_guid)
|
||||||
|
{
|
||||||
|
PSendSysMessage(LANG_NO_PLAYER,character_name.c_str());
|
||||||
|
SetSentErrorMessage(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
account_id = objmgr.GetPlayerAccountIdByGUID(character_guid);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string account_name;
|
||||||
|
accmgr.GetName (account_id,account_name);
|
||||||
|
|
||||||
|
Player::DeleteFromDB(character_guid, account_id, true);
|
||||||
|
PSendSysMessage(LANG_CHARACTER_DELETED,character_name.c_str(),GUID_LOPART(character_guid),account_name.c_str(), account_id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Exit the realm
|
||||||
|
bool ChatHandler::HandleServerExitCommand(const char* args)
|
||||||
|
{
|
||||||
|
SendSysMessage(LANG_COMMAND_EXIT);
|
||||||
|
World::StopNow(SHUTDOWN_EXIT_CODE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Display info on users currently in the realm
|
||||||
|
bool ChatHandler::HandleAccountOnlineListCommand(const char* args)
|
||||||
|
{
|
||||||
|
///- Get the list of accounts ID logged to the realm
|
||||||
|
QueryResult *resultDB = CharacterDatabase.Query("SELECT name,account FROM characters WHERE online > 0");
|
||||||
|
if (!resultDB)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
///- Display the list of account/characters online
|
||||||
|
SendSysMessage("=====================================================================");
|
||||||
|
SendSysMessage(LANG_ACCOUNT_LIST_HEADER);
|
||||||
|
SendSysMessage("=====================================================================");
|
||||||
|
|
||||||
|
///- Circle through accounts
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Field *fieldsDB = resultDB->Fetch();
|
||||||
|
std::string name = fieldsDB[0].GetCppString();
|
||||||
|
uint32 account = fieldsDB[1].GetUInt32();
|
||||||
|
|
||||||
|
///- Get the username, last IP and GM level of each account
|
||||||
|
// No SQL injection. account is uint32.
|
||||||
|
// 0 1 2 3
|
||||||
|
QueryResult *resultLogin = loginDatabase.PQuery("SELECT username, last_ip, gmlevel, expansion FROM account WHERE id = '%u'",account);
|
||||||
|
|
||||||
|
if(resultLogin)
|
||||||
|
{
|
||||||
|
Field *fieldsLogin = resultLogin->Fetch();
|
||||||
|
PSendSysMessage("|%15s| %20s | %15s |%4d|%5d|",
|
||||||
|
fieldsLogin[0].GetString(),name.c_str(),fieldsLogin[1].GetString(),fieldsLogin[2].GetUInt32(),fieldsLogin[3].GetUInt32());
|
||||||
|
|
||||||
|
delete resultLogin;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
PSendSysMessage(LANG_ACCOUNT_LIST_ERROR,name.c_str());
|
||||||
|
|
||||||
|
}while(resultDB->NextRow());
|
||||||
|
|
||||||
|
delete resultDB;
|
||||||
|
|
||||||
|
SendSysMessage("=====================================================================");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create an account
|
||||||
|
bool ChatHandler::HandleAccountCreateCommand(const char* args)
|
||||||
|
{
|
||||||
|
if(!*args)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
///- %Parse the command line arguments
|
||||||
|
char *szAcc = strtok((char*)args, " ");
|
||||||
|
char *szPassword = strtok(NULL, " ");
|
||||||
|
if(!szAcc || !szPassword)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// normilized in accmgr.CreateAccount
|
||||||
|
std::string account_name = szAcc;
|
||||||
|
std::string password = szPassword;
|
||||||
|
|
||||||
|
AccountOpResult result = accmgr.CreateAccount(account_name, password);
|
||||||
|
switch(result)
|
||||||
|
{
|
||||||
|
case AOR_OK:
|
||||||
|
PSendSysMessage(LANG_ACCOUNT_CREATED,account_name.c_str());
|
||||||
|
break;
|
||||||
|
case AOR_NAME_TOO_LONG:
|
||||||
|
SendSysMessage(LANG_ACCOUNT_TOO_LONG);
|
||||||
|
SetSentErrorMessage(true);
|
||||||
|
return false;
|
||||||
|
case AOR_NAME_ALREDY_EXIST:
|
||||||
|
SendSysMessage(LANG_ACCOUNT_ALREADY_EXIST);
|
||||||
|
SetSentErrorMessage(true);
|
||||||
|
return false;
|
||||||
|
case AOR_DB_INTERNAL_ERROR:
|
||||||
|
PSendSysMessage(LANG_ACCOUNT_NOT_CREATED_SQL_ERROR,account_name.c_str());
|
||||||
|
SetSentErrorMessage(true);
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
PSendSysMessage(LANG_ACCOUNT_NOT_CREATED,account_name.c_str());
|
||||||
|
SetSentErrorMessage(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the level of logging
|
||||||
|
bool ChatHandler::HandleServerSetLogLevelCommand(const char *args)
|
||||||
|
{
|
||||||
|
if(!*args)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
char *NewLevel = strtok((char*)args, " ");
|
||||||
|
if (!NewLevel)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
sLog.SetLogLevel(NewLevel);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// set diff time record interval
|
||||||
|
bool ChatHandler::HandleServerSetDiffTimeCommand(const char *args)
|
||||||
|
{
|
||||||
|
if(!*args)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
char *NewTimeStr = strtok((char*)args, " ");
|
||||||
|
if(!NewTimeStr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int32 NewTime =atoi(NewTimeStr);
|
||||||
|
if(NewTime < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
sWorld.SetRecordDiffInterval(NewTime);
|
||||||
|
printf( "Record diff every %u ms\n", NewTime);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
#ifdef linux
|
||||||
|
// Non-blocking keypress detector, when return pressed, return 1, else always return 0
|
||||||
|
int kb_hit_return()
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
fd_set fds;
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(STDIN_FILENO, &fds);
|
||||||
|
select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
|
||||||
|
return FD_ISSET(STDIN_FILENO, &fds);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// %Thread start
|
||||||
|
void CliRunnable::run()
|
||||||
|
{
|
||||||
|
///- Init new SQL thread for the world database (one connection call enough)
|
||||||
|
WorldDatabase.ThreadStart(); // let thread do safe mySQL requests
|
||||||
|
|
||||||
|
char commandbuf[256];
|
||||||
|
|
||||||
|
///- Display the list of available CLI functions then beep
|
||||||
|
sLog.outString();
|
||||||
|
|
||||||
|
if(sConfig.GetBoolDefault("BeepAtStart", true))
|
||||||
|
printf("\a"); // \a = Alert
|
||||||
|
|
||||||
|
// print this here the first time
|
||||||
|
// later it will be printed after command queue updates
|
||||||
|
printf("TC>");
|
||||||
|
|
||||||
|
///- As long as the World is running (no World::m_stopEvent), get the command line and handle it
|
||||||
|
while (!World::IsStopped())
|
||||||
|
{
|
||||||
|
fflush(stdout);
|
||||||
|
#ifdef linux
|
||||||
|
while (!kb_hit_return() && !World::IsStopped())
|
||||||
|
// With this, we limit CLI to 10commands/second
|
||||||
|
usleep(100);
|
||||||
|
if (World::IsStopped())
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
char *command_str = fgets(commandbuf,sizeof(commandbuf),stdin);
|
||||||
|
if (command_str != NULL)
|
||||||
|
{
|
||||||
|
for(int x=0;command_str[x];x++)
|
||||||
|
if(command_str[x]=='\r'||command_str[x]=='\n')
|
||||||
|
{
|
||||||
|
command_str[x]=0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(!*command_str)
|
||||||
|
{
|
||||||
|
printf("TC>");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string command;
|
||||||
|
if(!consoleToUtf8(command_str,command)) // convert from console encoding to utf8
|
||||||
|
{
|
||||||
|
printf("TC>");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sWorld.QueueCliCommand(&utf8print,command.c_str());
|
||||||
|
}
|
||||||
|
else if (feof(stdin))
|
||||||
|
{
|
||||||
|
World::StopNow(SHUTDOWN_EXIT_CODE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///- End the database thread
|
||||||
|
WorldDatabase.ThreadEnd(); // free mySQL thread resources
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user