*Merge with Trinity 783.
--HG-- branch : trunk
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
Update quest_template set SpecialFlags=2 where entry=4770;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_swiftmountain' WHERE `entry` = 10427;
|
||||
DELETE FROM `script_texts` WHERE `entry` BETWEEN -1000149 AND -1000147;
|
||||
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
|
||||
(-1000147, 'Lets go $N. I am ready to start to Whitereach Post.', NULL, NULL, 'Gehen wir $N.Ich bin bereit,mich zum Weissgipfelposten aufzumachen.', NULL, NULL, NULL, NULL, NULL, 0, 0, 0, NULL),
|
||||
(-1000148, 'This seems to me trusted. If we move to the east, we are probably... Aah! Wyvern attack !', NULL, NULL, 'Das kommt mir vertraut vor.Wenn wir nach Osten ziehen,können wir wahrscheinlich...Aah!Flügeldrachen im Angriff!', NULL, NULL, NULL, NULL, NULL, 0, 0, 0, NULL),
|
||||
(-1000149, 'Thanks so much... From here I find the way back to the Whitereach Post. Speak with Motega Firemane, maybe you can persuade him to send me home.', NULL, NULL, 'Tausend Dank...Von hier aus finde ich den Rückweg zum Weissgipfelposten.Sprecht unbedingt mit Motega Feuermähne,vielleicht könnt ihr ihn überreden,mich nach Hause zu schicken.', NULL, NULL, NULL, NULL, NULL, 0, 0, 0, NULL);
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE `gm_tickets` CHANGE `guid` `guid` int(10) NOT NULL AUTO_INCREMENT;
|
||||
ALTER TABLE `gm_tickets` CHANGE `closed` `closed` int(10) NOT NULL;
|
||||
@@ -375,6 +375,7 @@ scripts/zone/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp \
|
||||
scripts/zone/terokkar_forest/terokkar_forest.cpp \
|
||||
scripts/zone/thunder_bluff/thunder_bluff.cpp \
|
||||
scripts/zone/tirisfal_glades/tirisfal_glades.cpp \
|
||||
scripts/zone/thousand_needles/thousand_needles.cpp \
|
||||
scripts/zone/uldaman/boss_archaedas.cpp \
|
||||
scripts/zone/uldaman/instance_uldaman.cpp \
|
||||
scripts/zone/uldaman/boss_ironaya.cpp \
|
||||
|
||||
@@ -545,6 +545,8 @@ extern void AddSC_instance_temple_of_ahnqiraj();
|
||||
extern void AddSC_terokkar_forest();
|
||||
|
||||
//Thousand Needles
|
||||
extern void AddSC_thousand_needles();
|
||||
|
||||
//Thunder Bluff
|
||||
extern void AddSC_thunder_bluff();
|
||||
|
||||
@@ -1749,6 +1751,8 @@ void ScriptsInit()
|
||||
AddSC_terokkar_forest();
|
||||
|
||||
//Thousand Needles
|
||||
AddSC_thousand_needles();
|
||||
|
||||
//Thunder Bluff
|
||||
AddSC_thunder_bluff();
|
||||
|
||||
|
||||
@@ -1072,6 +1072,10 @@
|
||||
<Filter
|
||||
Name="Thousand Needles"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\scripts\zone\thousand_needles\thousand_needles.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Silithus"
|
||||
|
||||
@@ -1334,6 +1334,10 @@
|
||||
<Filter
|
||||
Name="Thousand Needles"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\scripts\zone\thousand_needles\thousand_needles.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Silithus"
|
||||
|
||||
@@ -1354,6 +1354,10 @@
|
||||
<Filter
|
||||
Name="Thousand Needles"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\scripts\zone\thousand_needles\thousand_needles.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Silithus"
|
||||
|
||||
@@ -432,7 +432,7 @@ void ScriptedAI::SelectUnitList(std::list<Unit*> &targetList, uint32 num, Select
|
||||
std::list<HostilReference*> m_threatlist = m_creature->getThreatManager().getThreatList();
|
||||
std::list<HostilReference*>::iterator i;
|
||||
Unit *target;
|
||||
while(m_threatlist.size())
|
||||
while(m_threatlist.size() && num)
|
||||
{
|
||||
if(targetType == SELECT_TARGET_BOTTOMAGGRO)
|
||||
{
|
||||
@@ -455,6 +455,7 @@ void ScriptedAI::SelectUnitList(std::list<Unit*> &targetList, uint32 num, Select
|
||||
continue;
|
||||
}
|
||||
targetList.push_back(target);
|
||||
--num;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+152
-198
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2006 - 2008 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
|
||||
/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
|
||||
* 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
|
||||
@@ -36,22 +36,20 @@ EndScriptData */
|
||||
#define SPELL_RAIN_OF_FIRE 33617
|
||||
#define H_SPELL_RAIN_OF_FIRE 39363
|
||||
|
||||
#define SPELL_DRAWN_SHADOWS 33563
|
||||
#define SPELL_DRAW_SHADOWS 33563
|
||||
#define SPELL_SHADOWBOLT_VOLLEY 33841
|
||||
#define SPELL_BANISH 38791
|
||||
|
||||
#define MOB_VOID_TRAVELER 19226
|
||||
#define SPELL_SACRIFICE 33587
|
||||
#define SPELL_SHADOW_NOVA 33846
|
||||
#define SPELL_HEALVORPIL 33783
|
||||
#define H_SPELL_HEALVORPIL 39364
|
||||
#define SPELL_EMPOWERING_SHADOWS 33783
|
||||
#define H_SPELL_EMPOWERING_SHADOWS 39364
|
||||
|
||||
#define MOB_VOID_PORTAL 19224
|
||||
#define SPELL_VOID_PORTAL_VISUAL 33569
|
||||
|
||||
float VorpilPosition[1][3] =
|
||||
{
|
||||
{-252.8820,-264.3030,17.1}
|
||||
};
|
||||
float VorpilPosition[3] = {-252.8820,-264.3030,17.1};
|
||||
|
||||
float VoidPortalCoords[5][3] =
|
||||
{
|
||||
@@ -62,76 +60,154 @@ float VoidPortalCoords[5][3] =
|
||||
{-261.4533, -297.3298, 17.1}
|
||||
};
|
||||
|
||||
class EmpoweringShadowsAura: public Aura
|
||||
{
|
||||
public:
|
||||
EmpoweringShadowsAura(SpellEntry *spell, uint32 eff, int32 *bp, Unit *target, Unit *caster) : Aura(spell, eff, bp, target, caster, NULL) {}
|
||||
};
|
||||
|
||||
struct TRINITY_DLL_DECL mob_voidtravelerAI : public ScriptedAI
|
||||
{
|
||||
mob_voidtravelerAI(Creature *c) : ScriptedAI(c)
|
||||
{
|
||||
HeroicMode = m_creature->GetMap()->IsHeroic();
|
||||
Reset();
|
||||
}
|
||||
|
||||
bool HeroicMode;
|
||||
Unit *Vorpil;
|
||||
uint32 move;
|
||||
bool sacrificed;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
Vorpil = NULL;
|
||||
move = 0;
|
||||
sacrificed = false;
|
||||
}
|
||||
|
||||
void Aggro(Unit *who){}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if(!Vorpil)
|
||||
{
|
||||
m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
|
||||
return;
|
||||
}
|
||||
if(move < diff)
|
||||
{
|
||||
if(sacrificed)
|
||||
{
|
||||
SpellEntry *spell = (SpellEntry *)GetSpellStore()->LookupEntry(HeroicMode?H_SPELL_EMPOWERING_SHADOWS:SPELL_EMPOWERING_SHADOWS);
|
||||
if( spell )
|
||||
Vorpil->AddAura(new EmpoweringShadowsAura(spell, 0, NULL, Vorpil, m_creature));
|
||||
Vorpil->SetHealth(Vorpil->GetHealth()+Vorpil->GetMaxHealth()/25);
|
||||
DoCast(m_creature, SPELL_SHADOW_NOVA, true);
|
||||
m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
|
||||
return;
|
||||
}
|
||||
m_creature->GetMotionMaster()->MoveFollow(Vorpil,0,0);
|
||||
if(m_creature->GetDistance(Vorpil) < 3)
|
||||
{
|
||||
DoCast(m_creature, SPELL_SACRIFICE, false);
|
||||
sacrificed = true;
|
||||
move = 500;
|
||||
return;
|
||||
}
|
||||
if(!Vorpil->isInCombat() || Vorpil->isDead())
|
||||
{
|
||||
m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
|
||||
return;
|
||||
}
|
||||
move = 1000;
|
||||
}else move -= diff;
|
||||
}
|
||||
};
|
||||
CreatureAI* GetAI_mob_voidtraveler(Creature *_Creature)
|
||||
{
|
||||
return new mob_voidtravelerAI (_Creature);
|
||||
}
|
||||
|
||||
struct TRINITY_DLL_DECL boss_grandmaster_vorpilAI : public ScriptedAI
|
||||
{
|
||||
boss_grandmaster_vorpilAI(Creature *c) : ScriptedAI(c)
|
||||
{
|
||||
pInstance = ((ScriptedInstance*)c->GetInstanceData());
|
||||
HeroicMode = m_creature->GetMap()->IsHeroic();
|
||||
Intro = false;
|
||||
Reset();
|
||||
}
|
||||
|
||||
ScriptedInstance *pInstance;
|
||||
bool Intro;
|
||||
bool Intro, HelpYell;
|
||||
bool sumportals;
|
||||
bool HeroicMode;
|
||||
|
||||
uint32 ShadowBoltVolley_Timer;
|
||||
uint32 DrawnShadows_Timer;
|
||||
uint32 sumportals_Timer;
|
||||
uint32 DrawShadows_Timer;
|
||||
uint32 summonTraveler_Timer;
|
||||
uint64 PortalsGuid[5];
|
||||
uint32 banish_Timer;
|
||||
uint64 PortalsGuid[5];
|
||||
|
||||
void Reset()
|
||||
{
|
||||
ShadowBoltVolley_Timer = 15000;
|
||||
DrawShadows_Timer = 45000;
|
||||
summonTraveler_Timer = 90000;
|
||||
banish_Timer = 17000;
|
||||
HelpYell = false;
|
||||
destroyPortals();
|
||||
if(pInstance)
|
||||
pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, NOT_STARTED);
|
||||
}
|
||||
|
||||
void summonPortals()
|
||||
{
|
||||
for (int i = 0;i<5;i++)
|
||||
if(!sumportals)
|
||||
{
|
||||
Creature *Portal = NULL;
|
||||
Portal = m_creature->SummonCreature(MOB_VOID_PORTAL,VoidPortalCoords[i][0],VoidPortalCoords[i][1],VoidPortalCoords[i][2],0,TEMPSUMMON_CORPSE_DESPAWN,3000000);
|
||||
PortalsGuid[i] = Portal->GetGUID();
|
||||
Portal->CastSpell(Portal,SPELL_VOID_PORTAL_VISUAL,false);
|
||||
for (int i = 0;i<5;i++)
|
||||
{
|
||||
Creature *Portal = NULL;
|
||||
Portal = m_creature->SummonCreature(MOB_VOID_PORTAL,VoidPortalCoords[i][0],VoidPortalCoords[i][1],VoidPortalCoords[i][2],0,TEMPSUMMON_CORPSE_DESPAWN,3000000);
|
||||
PortalsGuid[i] = Portal->GetGUID();
|
||||
Portal->CastSpell(Portal,SPELL_VOID_PORTAL_VISUAL,false);
|
||||
}
|
||||
sumportals = true;
|
||||
summonTraveler_Timer = 5000;
|
||||
}
|
||||
sumportals = true;
|
||||
summonTraveler_Timer = 5000;
|
||||
}
|
||||
|
||||
void destroyPortals()
|
||||
{
|
||||
for (int i = 0;i < 5; i ++)
|
||||
if(sumportals)
|
||||
{
|
||||
Unit *Portal = Unit::GetUnit((*m_creature), PortalsGuid[i]);
|
||||
if (Portal)
|
||||
if (Portal->isAlive())
|
||||
for (int i = 0;i < 5; i ++)
|
||||
{
|
||||
Unit *Portal = Unit::GetUnit((*m_creature), PortalsGuid[i]);
|
||||
if (Portal && Portal->isAlive())
|
||||
Portal->DealDamage(Portal, Portal->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
|
||||
PortalsGuid[i] = 0;
|
||||
}
|
||||
PortalsGuid[i] = 0;
|
||||
}
|
||||
sumportals = false;
|
||||
}
|
||||
}
|
||||
|
||||
void spawnVoidTraveler()
|
||||
{
|
||||
srand( (unsigned) time(NULL) ) ;
|
||||
int pos = rand()%5;
|
||||
Creature *traveler;
|
||||
traveler = m_creature->SummonCreature(MOB_VOID_TRAVELER,VoidPortalCoords[pos][0],VoidPortalCoords[pos][1],VoidPortalCoords[pos][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,10000);
|
||||
m_creature->SummonCreature(MOB_VOID_TRAVELER,VoidPortalCoords[pos][0],VoidPortalCoords[pos][1],VoidPortalCoords[pos][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,5000);
|
||||
if(!HelpYell)
|
||||
{
|
||||
DoScriptText(SAY_HELP, m_creature);
|
||||
HelpYell = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Reset()
|
||||
void JustSummoned(Creature *summoned)
|
||||
{
|
||||
HeroicMode = m_creature->GetMap()->IsHeroic();
|
||||
if( HeroicMode )
|
||||
debug_log("SD2: creature %u is in heroic mode",m_creature->GetEntry());
|
||||
|
||||
ShadowBoltVolley_Timer = 15000;
|
||||
DrawnShadows_Timer = 45000;
|
||||
sumportals_Timer = 10000;
|
||||
summonTraveler_Timer = 90000;
|
||||
|
||||
InCombat = false;
|
||||
sumportals = false;
|
||||
destroyPortals();
|
||||
|
||||
if(pInstance)
|
||||
pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, NOT_STARTED);
|
||||
if (summoned && summoned->GetEntry() == MOB_VOID_TRAVELER)
|
||||
((mob_voidtravelerAI*)summoned->AI())->Vorpil = m_creature;
|
||||
}
|
||||
|
||||
void KilledUnit(Unit *victim)
|
||||
@@ -151,7 +227,7 @@ struct TRINITY_DLL_DECL boss_grandmaster_vorpilAI : public ScriptedAI
|
||||
pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, DONE);
|
||||
}
|
||||
|
||||
void StartEvent()
|
||||
void Aggro(Unit *who)
|
||||
{
|
||||
switch(rand()%3)
|
||||
{
|
||||
@@ -159,55 +235,27 @@ struct TRINITY_DLL_DECL boss_grandmaster_vorpilAI : public ScriptedAI
|
||||
case 1: DoScriptText(SAY_AGGRO2, m_creature); break;
|
||||
case 2: DoScriptText(SAY_AGGRO3, m_creature); break;
|
||||
}
|
||||
|
||||
summonPortals();
|
||||
if(pInstance)
|
||||
pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, IN_PROGRESS);
|
||||
}
|
||||
|
||||
void Aggro(Unit *who)
|
||||
{
|
||||
if(!InCombat)
|
||||
{
|
||||
InCombat = true;
|
||||
StartEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit *who)
|
||||
{
|
||||
if (!who || m_creature->getVictim())
|
||||
return;
|
||||
|
||||
if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(m_creature) && m_creature->IsHostileTo(who))
|
||||
{
|
||||
float attackRadius = m_creature->GetAttackDistance(who);
|
||||
if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who))
|
||||
{
|
||||
AttackStart(who);
|
||||
}
|
||||
}
|
||||
else if (!Intro && m_creature->IsWithinLOSInMap(who)&& m_creature->IsWithinDistInMap(who, 100) ) //not sure about right radius
|
||||
if(who && !m_creature->getVictim() && m_creature->canStartAttack(who))
|
||||
AttackStart(who);
|
||||
if (!Intro && who && m_creature->IsWithinLOSInMap(who)&& m_creature->IsWithinDistInMap(who, 100) && m_creature->IsHostileTo(who))
|
||||
{
|
||||
DoScriptText(SAY_INTRO, m_creature);
|
||||
Intro = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
|
||||
if (!m_creature->SelectHostilTarget() || !m_creature->getVictim())
|
||||
return;
|
||||
|
||||
if (!sumportals)
|
||||
if (sumportals_Timer < diff)
|
||||
{
|
||||
DoScriptText(SAY_HELP, m_creature);
|
||||
summonPortals();
|
||||
sumportals_Timer = 1000000;
|
||||
|
||||
}else sumportals_Timer -= diff;
|
||||
|
||||
if (ShadowBoltVolley_Timer < diff)
|
||||
{
|
||||
@@ -215,23 +263,41 @@ struct TRINITY_DLL_DECL boss_grandmaster_vorpilAI : public ScriptedAI
|
||||
ShadowBoltVolley_Timer = 15000;
|
||||
}else ShadowBoltVolley_Timer -= diff;
|
||||
|
||||
if ( DrawnShadows_Timer < diff)
|
||||
if (HeroicMode && banish_Timer < diff)
|
||||
{
|
||||
DoTeleportAll(VorpilPosition[0][0],VorpilPosition[0][1],VorpilPosition[0][2],0);
|
||||
m_creature->Relocate(VorpilPosition[0][0],VorpilPosition[0][1],VorpilPosition[0][2],0);
|
||||
DoCast(m_creature,SPELL_DRAWN_SHADOWS,true);
|
||||
Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0,30,false);
|
||||
if (target)
|
||||
{
|
||||
DoCast(target,SPELL_BANISH);
|
||||
banish_Timer = 16000;
|
||||
}
|
||||
}else banish_Timer -= diff;
|
||||
|
||||
if(!HeroicMode) DoCast(m_creature,SPELL_RAIN_OF_FIRE);
|
||||
else DoCast(m_creature,H_SPELL_RAIN_OF_FIRE);
|
||||
if ( DrawShadows_Timer < diff)
|
||||
{
|
||||
Map *map = m_creature->GetMap();
|
||||
Map::PlayerList const &PlayerList = map->GetPlayers();
|
||||
for(Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
|
||||
if (Player* i_pl = i->getSource())
|
||||
if (i_pl->isAlive() && !i_pl->HasAura(SPELL_BANISH,0))
|
||||
i_pl->TeleportTo(m_creature->GetMapId(), VorpilPosition[0],VorpilPosition[1],VorpilPosition[2], 0, TELE_TO_NOT_LEAVE_COMBAT);
|
||||
|
||||
m_creature->Relocate(VorpilPosition[0],VorpilPosition[1],VorpilPosition[2]);
|
||||
DoCast(m_creature,SPELL_DRAW_SHADOWS,true);
|
||||
|
||||
DoCast(m_creature,HeroicMode?H_SPELL_RAIN_OF_FIRE:SPELL_RAIN_OF_FIRE);
|
||||
|
||||
ShadowBoltVolley_Timer = 6000;
|
||||
DrawnShadows_Timer = 45000;
|
||||
}else DrawnShadows_Timer -= diff;
|
||||
DrawShadows_Timer = 30000;
|
||||
}else DrawShadows_Timer -= diff;
|
||||
|
||||
if ( summonTraveler_Timer < diff)
|
||||
{
|
||||
spawnVoidTraveler();
|
||||
summonTraveler_Timer = 10000;
|
||||
//enrage at 20%
|
||||
if((m_creature->GetHealth()*5) < m_creature->GetMaxHealth())
|
||||
summonTraveler_Timer = 5000;
|
||||
}else summonTraveler_Timer -=diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
@@ -242,118 +308,6 @@ CreatureAI* GetAI_boss_grandmaster_vorpil(Creature *_Creature)
|
||||
return new boss_grandmaster_vorpilAI (_Creature);
|
||||
}
|
||||
|
||||
struct TRINITY_DLL_DECL mob_voidtravelerAI : public ScriptedAI
|
||||
{
|
||||
mob_voidtravelerAI(Creature *c) : ScriptedAI(c)
|
||||
{
|
||||
pInstance = ((ScriptedInstance*)c->GetInstanceData());
|
||||
Reset();
|
||||
}
|
||||
|
||||
ScriptedInstance *pInstance;
|
||||
uint32 VorpilCheck_Timer;
|
||||
uint32 eventCheck_Timer;
|
||||
bool sacrifice;
|
||||
bool sacrificed;
|
||||
bool oneTarget;
|
||||
bool HeroicMode;
|
||||
|
||||
uint32 target_timer;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
HeroicMode = m_creature->GetMap()->IsHeroic();
|
||||
if( HeroicMode )
|
||||
debug_log("SD2: creature %u is in heroic mode",m_creature->GetEntry());
|
||||
|
||||
VorpilCheck_Timer = 5000;
|
||||
eventCheck_Timer = 1000;
|
||||
target_timer = 2000;
|
||||
oneTarget = false;
|
||||
sacrificed = false;
|
||||
sacrifice = false;
|
||||
}
|
||||
void EnterEvadeMode(){}
|
||||
void Aggro(Unit *who) {}
|
||||
void AttackStart(Unit *who){}
|
||||
void MoveInLineOfSight(Unit *who){}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (eventCheck_Timer < diff)
|
||||
{
|
||||
if(pInstance)
|
||||
{
|
||||
Unit *Vorpil = Unit::GetUnit((*m_creature),pInstance->GetData64(DATA_GRANDMASTERVORPIL));
|
||||
if (Vorpil)
|
||||
{
|
||||
if (Vorpil->isDead())
|
||||
{
|
||||
m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
|
||||
}
|
||||
|
||||
if (Vorpil->getVictim())
|
||||
{
|
||||
if((*m_creature).GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE)
|
||||
(*m_creature).GetMotionMaster()->MoveFollow(Vorpil,1,0);
|
||||
}
|
||||
}
|
||||
if(pInstance->GetData(DATA_GRANDMASTERVORPILEVENT) != IN_PROGRESS)
|
||||
{
|
||||
m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
|
||||
}
|
||||
}
|
||||
eventCheck_Timer = 5000;
|
||||
}else eventCheck_Timer -=diff;
|
||||
|
||||
if (VorpilCheck_Timer < diff)
|
||||
{
|
||||
if (pInstance)
|
||||
{
|
||||
if (!sacrificed)
|
||||
{
|
||||
if (!sacrifice)
|
||||
{
|
||||
Unit *Vorpil = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_GRANDMASTERVORPIL));
|
||||
if (Vorpil)
|
||||
if (Vorpil->isAlive())
|
||||
{
|
||||
if (m_creature->IsWithinDistInMap(Vorpil, 2))
|
||||
{
|
||||
sacrifice = true;
|
||||
DoCast(m_creature,SPELL_SACRIFICE);
|
||||
VorpilCheck_Timer = 2000;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sacrifice)
|
||||
VorpilCheck_Timer = 3000;
|
||||
}
|
||||
else
|
||||
{
|
||||
Unit *Vorpil = Unit::GetUnit((*m_creature),pInstance->GetData64(DATA_GRANDMASTERVORPIL));
|
||||
if (Vorpil)
|
||||
if (Vorpil->isAlive())
|
||||
{
|
||||
if(!HeroicMode) Vorpil->CastSpell(Vorpil,SPELL_HEALVORPIL,true);
|
||||
else Vorpil->CastSpell(Vorpil,H_SPELL_HEALVORPIL,true);
|
||||
};
|
||||
DoCast(m_creature,SPELL_SHADOW_NOVA);
|
||||
sacrificed = true;
|
||||
m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
|
||||
VorpilCheck_Timer = 100000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}else VorpilCheck_Timer -= diff;
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI_mob_voidtraveler(Creature *_Creature)
|
||||
{
|
||||
return new mob_voidtravelerAI (_Creature);
|
||||
}
|
||||
|
||||
void AddSC_boss_grandmaster_vorpil()
|
||||
{
|
||||
Script *newscript;
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
/* Copyright (C) 2006 - 2008 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
|
||||
* 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: Thousand Needles
|
||||
SD%Complete: 100
|
||||
SDComment: Support for Quest: 4770
|
||||
SDCategory: Thousand Needles
|
||||
EndScriptData */
|
||||
|
||||
/* ContentData
|
||||
npc_swiftmountain
|
||||
EndContentData */
|
||||
|
||||
#include "precompiled.h"
|
||||
#include "../../npc/npc_escortAI.h"
|
||||
|
||||
#define SAY_READY -1000147
|
||||
#define SAY_AGGRO -1000148
|
||||
#define SAY_FINISH -1000149
|
||||
|
||||
#define QUEST_HOMEWARD_BOUND 4770
|
||||
#define ENTRY_WYVERN 4107
|
||||
|
||||
|
||||
|
||||
struct TRINITY_DLL_DECL npc_swiftmountainAI : public npc_escortAI
|
||||
{
|
||||
npc_swiftmountainAI(Creature *c) : npc_escortAI(c) {Reset();}
|
||||
|
||||
void WaypointReached(uint32 i)
|
||||
{
|
||||
Unit* player = Unit::GetUnit((*m_creature), PlayerGUID);
|
||||
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 46:
|
||||
DoScriptText(SAY_AGGRO, m_creature, player);
|
||||
break;
|
||||
case 47:
|
||||
m_creature->SummonCreature(ENTRY_WYVERN, -5016.45, -935.01, -5.46, 5.36,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000);
|
||||
m_creature->SummonCreature(ENTRY_WYVERN, -5001.98, -934.96, -5.55, 3.18,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000);
|
||||
m_creature->SummonCreature(ENTRY_WYVERN, -4999.06, -949.61, -5.42, 2.04,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000);
|
||||
break;
|
||||
case 70:
|
||||
DoScriptText(SAY_FINISH, m_creature, player);
|
||||
if (player && player->GetTypeId() == TYPEID_PLAYER)
|
||||
((Player*)player)->GroupEventHappens(QUEST_HOMEWARD_BOUND,m_creature);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Aggro(Unit* who)
|
||||
{}
|
||||
|
||||
void JustSummoned(Creature* summoned)
|
||||
{
|
||||
summoned->AI()->AttackStart(m_creature);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer)
|
||||
{
|
||||
if (PlayerGUID)
|
||||
{
|
||||
if (Unit* player = Unit::GetUnit((*m_creature), PlayerGUID))
|
||||
((Player*)player)->FailQuest(QUEST_HOMEWARD_BOUND);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
npc_escortAI::UpdateAI(diff);
|
||||
}
|
||||
};
|
||||
|
||||
bool QuestAccept_npc_swiftmountain(Player* player, Creature* creature, Quest const* quest)
|
||||
{
|
||||
if (quest->GetQuestId() == QUEST_HOMEWARD_BOUND)
|
||||
{
|
||||
((npc_escortAI*)(creature->AI()))->Start(true, true, false, player->GetGUID());
|
||||
DoScriptText(SAY_READY, creature, player);
|
||||
// Change faction so mobs attack
|
||||
creature->setFaction(775);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CreatureAI* GetAI_npc_swiftmountain(Creature *_Creature)
|
||||
{
|
||||
npc_swiftmountainAI* thisAI = new npc_swiftmountainAI(_Creature);
|
||||
|
||||
thisAI->AddWaypoint(0, -5156.69, -1220.49, 48.78, 5000);
|
||||
thisAI->AddWaypoint(1, -5157.12, -1220.13, 48.67);
|
||||
thisAI->AddWaypoint(2, -5171.7, -1205.36, 47.43);
|
||||
thisAI->AddWaypoint(3, -5174.08, -1197.7, 46.90);
|
||||
thisAI->AddWaypoint(4, -5178.24, -1183.78, 45.97);
|
||||
thisAI->AddWaypoint(5, -5181.52, -1171.03, 45.29);
|
||||
thisAI->AddWaypoint(6, -5184.29, -1159.21, 44.62);
|
||||
thisAI->AddWaypoint(7, -5184.84, -1152.95, 44.84);
|
||||
thisAI->AddWaypoint(8, -5182.04, -1142.83, 44.07);
|
||||
thisAI->AddWaypoint(9, -5178.44, -1133.57, 43.91);
|
||||
thisAI->AddWaypoint(10, -5176.68, -1129.48, 43.81);
|
||||
thisAI->AddWaypoint(11, -5164.85, -1123.33, 43.99);
|
||||
thisAI->AddWaypoint(12, -5153.07, -1117.7, 43.66);
|
||||
thisAI->AddWaypoint(13, -5143.52, -1113.14, 43.78);
|
||||
thisAI->AddWaypoint(14, -5135.86, -1104.42, 47.23);
|
||||
thisAI->AddWaypoint(15, -5129.86, -1097.22, 49.52);
|
||||
thisAI->AddWaypoint(16, -5127.48, -1087.29, 49.03);
|
||||
thisAI->AddWaypoint(17, -5127.57, -1080.4, 46.64);
|
||||
thisAI->AddWaypoint(18, -5129.65, -1077.58, 45.29);
|
||||
thisAI->AddWaypoint(19, -5135.86, -1069.12, 39.53);
|
||||
thisAI->AddWaypoint(20, -5141.97, -1060.58, 32.70);
|
||||
thisAI->AddWaypoint(21, -5145.99, -1054.85, 28.98);
|
||||
thisAI->AddWaypoint(22, -5147.08, -1050.35, 26.36);
|
||||
thisAI->AddWaypoint(23, -5147.5, -1043.37, 21.84);
|
||||
thisAI->AddWaypoint(24, -5147.68, -1036.37, 17.05);
|
||||
thisAI->AddWaypoint(25, -5147.68, -1029.37, 14.59);
|
||||
thisAI->AddWaypoint(26, -5144.62, -1023.9, 11.67);
|
||||
thisAI->AddWaypoint(27, -5138.67, -1020.23, 7.81);
|
||||
thisAI->AddWaypoint(28, -5135.6, -1018.55, 6.19);
|
||||
thisAI->AddWaypoint(29, -5126.25, -1014.76, 1.08);
|
||||
thisAI->AddWaypoint(30, -5120.03, -1013.12, -1.11);
|
||||
thisAI->AddWaypoint(31, -5112.3, -1027.65, -5.39);
|
||||
thisAI->AddWaypoint(32, -5106.99, -1023.09, -5.10);
|
||||
thisAI->AddWaypoint(33, -5099.07, -1016.19, -4.92);
|
||||
thisAI->AddWaypoint(34, -5091.23, -1009.21, -5.22);
|
||||
thisAI->AddWaypoint(35, -5083.62, -1001.97, -5.22);
|
||||
thisAI->AddWaypoint(36, -5076.1, -994.652, -4.92);
|
||||
thisAI->AddWaypoint(37, -5066.71, -985.507, -4.97);
|
||||
thisAI->AddWaypoint(38, -5065.13, -978.689, -5.02);
|
||||
thisAI->AddWaypoint(39, -5062.33, -968.57, -5.08);
|
||||
thisAI->AddWaypoint(40, -5059.46, -958.469, -5.16);
|
||||
thisAI->AddWaypoint(41, -5056.59, -948.375, -5.10);
|
||||
thisAI->AddWaypoint(42, -5053.73, -938.274, -5.69);
|
||||
thisAI->AddWaypoint(43, -5043.06, -934.822, -5.35);
|
||||
thisAI->AddWaypoint(44, -5029.35, -932.007, -5.27);
|
||||
thisAI->AddWaypoint(45, -5024.58, -933.781, -5.40);
|
||||
thisAI->AddWaypoint(46, -5019.13, -938.172, -5.54);
|
||||
thisAI->AddWaypoint(47, -5011, -944.812, -5.47);
|
||||
thisAI->AddWaypoint(48, -5002.86, -951.455, -5.44);
|
||||
thisAI->AddWaypoint(49, -4994.73, -958.099, -5.41);
|
||||
thisAI->AddWaypoint(50, -4990.57, -963.782, -5.33);
|
||||
thisAI->AddWaypoint(51, -4987.43, -970.041, -5.17);
|
||||
thisAI->AddWaypoint(52, -4981.41, -982.678, -5.10);
|
||||
thisAI->AddWaypoint(53, -4977.03, -992.221, -4.97);
|
||||
thisAI->AddWaypoint(54, -4972.6, -1001.74, -5.24);
|
||||
thisAI->AddWaypoint(55, -4968.15, -1011.25, -5.49);
|
||||
thisAI->AddWaypoint(56, -4963.75, -1020.78, -5.07);
|
||||
thisAI->AddWaypoint(57, -4959.3, -1030.3, -5.28);
|
||||
thisAI->AddWaypoint(58, -4956.28, -1036.61, -5.84);
|
||||
thisAI->AddWaypoint(59, -4952.05, -1043.75, -9.04);
|
||||
thisAI->AddWaypoint(60, -4943.8, -1055.06, -17.91);
|
||||
thisAI->AddWaypoint(61, -4939.47, -1055.61, -20.73);
|
||||
thisAI->AddWaypoint(62, -4929.16, -1053.64, -25.65);
|
||||
thisAI->AddWaypoint(63, -4922.28, -1052.37, -28.72);
|
||||
thisAI->AddWaypoint(64, -4913.26, -1051.3, -31.80);
|
||||
thisAI->AddWaypoint(65, -4903.54, -1054.17, -33.48);
|
||||
thisAI->AddWaypoint(66, -4905.95, -1056.71, -33.68);
|
||||
thisAI->AddWaypoint(67, -4913.18, -1064.32, -39.46);
|
||||
thisAI->AddWaypoint(68, -4925.27, -1076.98, -47.39);
|
||||
thisAI->AddWaypoint(69, -4932.68, -1084.42, -51.00);
|
||||
thisAI->AddWaypoint(70, -4938.3, -1100.41, -50.71, 5000);
|
||||
thisAI->AddWaypoint(71, -4937.34, -1102.87, -49.82);
|
||||
|
||||
return (CreatureAI*)thisAI;
|
||||
}
|
||||
|
||||
void AddSC_thousand_needles()
|
||||
{
|
||||
Script *newscript;
|
||||
|
||||
newscript = new Script;
|
||||
newscript->Name = "npc_swiftmountain";
|
||||
newscript->GetAI = &GetAI_npc_swiftmountain;
|
||||
newscript->pQuestAccept = &QuestAccept_npc_swiftmountain;
|
||||
newscript->RegisterSelf();
|
||||
}
|
||||
+25
-25
@@ -26,9 +26,9 @@
|
||||
#include "Util.h"
|
||||
|
||||
#ifdef DO_POSTGRESQL
|
||||
extern DatabasePostgre loginDatabase;
|
||||
extern DatabasePostgre LoginDatabase;
|
||||
#else
|
||||
extern DatabaseMysql loginDatabase;
|
||||
extern DatabaseMysql LoginDatabase;
|
||||
#endif
|
||||
|
||||
INSTANTIATE_SINGLETON_1(AccountMgr);
|
||||
@@ -47,26 +47,26 @@ AccountOpResult AccountMgr::CreateAccount(std::string username, std::string pass
|
||||
normilizeString(username);
|
||||
normilizeString(password);
|
||||
|
||||
loginDatabase.escape_string(username);
|
||||
loginDatabase.escape_string(password);
|
||||
LoginDatabase.escape_string(username);
|
||||
LoginDatabase.escape_string(password);
|
||||
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE username = '%s'", username.c_str());
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE username = '%s'", username.c_str());
|
||||
if(result)
|
||||
{
|
||||
delete result;
|
||||
return AOR_NAME_ALREDY_EXIST; // username does already exist
|
||||
}
|
||||
|
||||
if(!loginDatabase.PExecute("INSERT INTO account(username,sha_pass_hash,joindate) VALUES('%s',SHA1(CONCAT('%s',':','%s')),NOW())", username.c_str(), username.c_str(), password.c_str()))
|
||||
if(!LoginDatabase.PExecute("INSERT INTO account(username,sha_pass_hash,joindate) VALUES('%s',SHA1(CONCAT('%s',':','%s')),NOW())", username.c_str(), username.c_str(), password.c_str()))
|
||||
return AOR_DB_INTERNAL_ERROR; // unexpected error
|
||||
loginDatabase.Execute("INSERT INTO realmcharacters (realmid, acctid, numchars) SELECT realmlist.id, account.id, 0 FROM realmlist,account LEFT JOIN realmcharacters ON acctid=account.id WHERE acctid IS NULL");
|
||||
LoginDatabase.Execute("INSERT INTO realmcharacters (realmid, acctid, numchars) SELECT realmlist.id, account.id, 0 FROM realmlist,account LEFT JOIN realmcharacters ON acctid=account.id WHERE acctid IS NULL");
|
||||
|
||||
return AOR_OK; // everything's fine
|
||||
}
|
||||
|
||||
AccountOpResult AccountMgr::DeleteAccount(uint32 accid)
|
||||
{
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid);
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid);
|
||||
if(!result)
|
||||
return AOR_NAME_NOT_EXIST; // account doesn't exist
|
||||
delete result;
|
||||
@@ -97,13 +97,13 @@ AccountOpResult AccountMgr::DeleteAccount(uint32 accid)
|
||||
// table realm specific but common for all characters of account for realm
|
||||
CharacterDatabase.PExecute("DELETE FROM character_tutorial WHERE account = '%u'",accid);
|
||||
|
||||
loginDatabase.BeginTransaction();
|
||||
LoginDatabase.BeginTransaction();
|
||||
|
||||
bool res =
|
||||
loginDatabase.PExecute("DELETE FROM account WHERE id='%d'", accid) &&
|
||||
loginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid='%d'", accid);
|
||||
LoginDatabase.PExecute("DELETE FROM account WHERE id='%d'", accid) &&
|
||||
LoginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid='%d'", accid);
|
||||
|
||||
loginDatabase.CommitTransaction();
|
||||
LoginDatabase.CommitTransaction();
|
||||
|
||||
if(!res)
|
||||
return AOR_DB_INTERNAL_ERROR; // unexpected error;
|
||||
@@ -113,7 +113,7 @@ AccountOpResult AccountMgr::DeleteAccount(uint32 accid)
|
||||
|
||||
AccountOpResult AccountMgr::ChangeUsername(uint32 accid, std::string new_uname, std::string new_passwd)
|
||||
{
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid);
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid);
|
||||
if(!result)
|
||||
return AOR_NAME_NOT_EXIST; // account doesn't exist
|
||||
delete result;
|
||||
@@ -127,9 +127,9 @@ AccountOpResult AccountMgr::ChangeUsername(uint32 accid, std::string new_uname,
|
||||
normilizeString(new_uname);
|
||||
normilizeString(new_passwd);
|
||||
|
||||
loginDatabase.escape_string(new_uname);
|
||||
loginDatabase.escape_string(new_passwd);
|
||||
if(!loginDatabase.PExecute("UPDATE account SET username='%s',sha_pass_hash=SHA1(CONCAT('%s',':','%s')) WHERE id='%d'", new_uname.c_str(), new_uname.c_str(), new_passwd.c_str(), accid))
|
||||
LoginDatabase.escape_string(new_uname);
|
||||
LoginDatabase.escape_string(new_passwd);
|
||||
if(!LoginDatabase.PExecute("UPDATE account SET username='%s',sha_pass_hash=SHA1(CONCAT('%s',':','%s')) WHERE id='%d'", new_uname.c_str(), new_uname.c_str(), new_passwd.c_str(), accid))
|
||||
return AOR_DB_INTERNAL_ERROR; // unexpected error
|
||||
|
||||
return AOR_OK;
|
||||
@@ -137,7 +137,7 @@ AccountOpResult AccountMgr::ChangeUsername(uint32 accid, std::string new_uname,
|
||||
|
||||
AccountOpResult AccountMgr::ChangePassword(uint32 accid, std::string new_passwd)
|
||||
{
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid);
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid);
|
||||
if(!result)
|
||||
return AOR_NAME_NOT_EXIST; // account doesn't exist
|
||||
delete result;
|
||||
@@ -147,8 +147,8 @@ AccountOpResult AccountMgr::ChangePassword(uint32 accid, std::string new_passwd)
|
||||
|
||||
normilizeString(new_passwd);
|
||||
|
||||
loginDatabase.escape_string(new_passwd);
|
||||
if(!loginDatabase.PExecute("UPDATE account SET sha_pass_hash=SHA1(CONCAT(username,':','%s')) WHERE id='%d'", new_passwd.c_str(), accid))
|
||||
LoginDatabase.escape_string(new_passwd);
|
||||
if(!LoginDatabase.PExecute("UPDATE account SET sha_pass_hash=SHA1(CONCAT(username,':','%s')) WHERE id='%d'", new_passwd.c_str(), accid))
|
||||
return AOR_DB_INTERNAL_ERROR; // unexpected error
|
||||
|
||||
return AOR_OK;
|
||||
@@ -156,8 +156,8 @@ AccountOpResult AccountMgr::ChangePassword(uint32 accid, std::string new_passwd)
|
||||
|
||||
uint32 AccountMgr::GetId(std::string username)
|
||||
{
|
||||
loginDatabase.escape_string(username);
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'", username.c_str());
|
||||
LoginDatabase.escape_string(username);
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'", username.c_str());
|
||||
if(!result)
|
||||
return 0;
|
||||
else
|
||||
@@ -170,7 +170,7 @@ uint32 AccountMgr::GetId(std::string username)
|
||||
|
||||
uint32 AccountMgr::GetSecurity(uint32 acc_id)
|
||||
{
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT gmlevel FROM account WHERE id = '%u'", acc_id);
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT gmlevel FROM account WHERE id = '%u'", acc_id);
|
||||
if(result)
|
||||
{
|
||||
uint32 sec = (*result)[0].GetUInt32();
|
||||
@@ -183,7 +183,7 @@ uint32 AccountMgr::GetSecurity(uint32 acc_id)
|
||||
|
||||
bool AccountMgr::GetName(uint32 acc_id, std::string &name)
|
||||
{
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT username FROM account WHERE id = '%u'", acc_id);
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT username FROM account WHERE id = '%u'", acc_id);
|
||||
if(result)
|
||||
{
|
||||
name = (*result)[0].GetCppString();
|
||||
@@ -197,9 +197,9 @@ bool AccountMgr::GetName(uint32 acc_id, std::string &name)
|
||||
bool AccountMgr::CheckPassword(uint32 accid, std::string passwd)
|
||||
{
|
||||
normilizeString(passwd);
|
||||
loginDatabase.escape_string(passwd);
|
||||
LoginDatabase.escape_string(passwd);
|
||||
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d' AND sha_pass_hash=SHA1(CONCAT(username,':','%s'))", accid, passwd.c_str());
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d' AND sha_pass_hash=SHA1(CONCAT(username,':','%s'))", accid, passwd.c_str());
|
||||
if (result)
|
||||
{
|
||||
delete result;
|
||||
|
||||
@@ -123,7 +123,7 @@ class CharacterHandler
|
||||
void WorldSession::HandleCharEnum(QueryResult * result)
|
||||
{
|
||||
// keys can be non cleared if player open realm list and close it by 'cancel'
|
||||
loginDatabase.PExecute("UPDATE account SET v = '0', s = '0' WHERE id = '%u'", GetAccountId());
|
||||
LoginDatabase.PExecute("UPDATE account SET v = '0', s = '0' WHERE id = '%u'", GetAccountId());
|
||||
|
||||
WorldPacket data(SMSG_CHAR_ENUM, 100); // we guess size
|
||||
|
||||
@@ -281,7 +281,7 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
|
||||
return;
|
||||
}
|
||||
|
||||
QueryResult *resultacct = loginDatabase.PQuery("SELECT SUM(numchars) FROM realmcharacters WHERE acctid = '%d'", GetAccountId());
|
||||
QueryResult *resultacct = LoginDatabase.PQuery("SELECT SUM(numchars) FROM realmcharacters WHERE acctid = '%d'", GetAccountId());
|
||||
if ( resultacct )
|
||||
{
|
||||
Field *fields=resultacct->Fetch();
|
||||
@@ -464,8 +464,8 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
|
||||
pNewChar->SaveToDB();
|
||||
charcount+=1;
|
||||
|
||||
loginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", GetAccountId(), realmID);
|
||||
loginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charcount, GetAccountId(), realmID);
|
||||
LoginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", GetAccountId(), realmID);
|
||||
LoginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charcount, GetAccountId(), realmID);
|
||||
|
||||
delete pNewChar; // created only to call SaveToDB()
|
||||
|
||||
@@ -742,7 +742,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
|
||||
pCurrChar->SendInitialPacketsAfterAddToMap();
|
||||
|
||||
CharacterDatabase.PExecute("UPDATE characters SET online = 1 WHERE guid = '%u'", pCurrChar->GetGUIDLow());
|
||||
loginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = '%u'", GetAccountId());
|
||||
LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = '%u'", GetAccountId());
|
||||
pCurrChar->SetInGameTime( getMSTime() );
|
||||
|
||||
// announce group about member online (must be after add to player list to receive announce to self)
|
||||
|
||||
+1
-1
@@ -304,7 +304,7 @@ ChatCommand * ChatHandler::getCommandTable()
|
||||
{ "locales_page_text", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesPageTextCommand, "", NULL },
|
||||
{ "locales_quest", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesQuestCommand, "", NULL },
|
||||
{ "waypoint_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadWpScriptsCommand, "", NULL },
|
||||
{ "tickets", SEC_ADMINISTRATOR, true, &ChatHandler::HandleGMTicketReloadCommand, "", NULL },
|
||||
{ "gm_tickets", SEC_ADMINISTRATOR, true, &ChatHandler::HandleGMTicketReloadCommand, "", NULL },
|
||||
|
||||
{ NULL, 0, false, NULL, "", NULL }
|
||||
};
|
||||
|
||||
+3
-3
@@ -197,7 +197,7 @@ bool ChatHandler::HandlePasswordCommand(const char* args)
|
||||
std::string password_new = new_pass;
|
||||
std::string password_new_c = new_pass_c;
|
||||
|
||||
if (password_new != password_new_c)
|
||||
if (strcmp(new_pass, new_pass_c) != 0)
|
||||
{
|
||||
SendSysMessage (LANG_NEW_PASSWORDS_NOT_MATCH);
|
||||
SetSentErrorMessage (true);
|
||||
@@ -243,14 +243,14 @@ bool ChatHandler::HandleLockAccountCommand(const char* args)
|
||||
std::string argstr = (char*)args;
|
||||
if (argstr == "on")
|
||||
{
|
||||
loginDatabase.PExecute( "UPDATE account SET locked = '1' WHERE id = '%d'",m_session->GetAccountId());
|
||||
LoginDatabase.PExecute( "UPDATE account SET locked = '1' WHERE id = '%d'",m_session->GetAccountId());
|
||||
PSendSysMessage(LANG_COMMAND_ACCLOCKLOCKED);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (argstr == "off")
|
||||
{
|
||||
loginDatabase.PExecute( "UPDATE account SET locked = '0' WHERE id = '%d'",m_session->GetAccountId());
|
||||
LoginDatabase.PExecute( "UPDATE account SET locked = '0' WHERE id = '%d'",m_session->GetAccountId());
|
||||
PSendSysMessage(LANG_COMMAND_ACCLOCKUNLOCKED);
|
||||
return true;
|
||||
}
|
||||
|
||||
+44
-38
@@ -275,19 +275,20 @@ bool ChatHandler::HandleGMTicketListCommand(const char* args)
|
||||
SendSysMessage(LANG_COMMAND_TICKETSHOWLIST);
|
||||
for(GmTicketList::iterator itr = ticketmgr.GM_TicketList.begin(); itr != ticketmgr.GM_TicketList.end(); ++itr)
|
||||
{
|
||||
if((*itr)->closed == 1)
|
||||
if((*itr)->closed != 0)
|
||||
continue;
|
||||
|
||||
std::stringstream message;
|
||||
message << "|cff00ff00Ticket|r: |cff00ccff" << (*itr)->guid;
|
||||
message << ".|r |cff00ff00created by:|r |cff00ccff" << (*itr)->name;
|
||||
message << ".|r |cff00ff00Last change:|r |cff00ccff " << secsToTimeString(time(NULL) - (*itr)->timestamp, true, false) << " ago.";
|
||||
if((*itr)->assignedToGM != 0 && objmgr.GetPlayer((*itr)->assignedToGM))
|
||||
if((*itr)->assignedToGM != 0)
|
||||
{
|
||||
std::string gmname = objmgr.GetPlayer((*itr)->assignedToGM)->GetName();
|
||||
std::string gmname;
|
||||
objmgr.GetPlayerNameByGUID((*itr)->assignedToGM, gmname);
|
||||
message << "|r |cff00ff00Assigned to:|r |cff00ccff " << gmname;
|
||||
}
|
||||
SendGlobalGMSysMessage(message.str().c_str());
|
||||
SendSysMessage(message.str().c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -298,7 +299,7 @@ bool ChatHandler::HandleGMTicketListOnlineCommand(const char* args)
|
||||
SendSysMessage(LANG_COMMAND_TICKETSHOWONLINELIST);
|
||||
for(GmTicketList::iterator itr = ticketmgr.GM_TicketList.begin(); itr != ticketmgr.GM_TicketList.end(); ++itr)
|
||||
{
|
||||
if((*itr)->closed == 1 || !objmgr.GetPlayer((*itr)->playerGuid))
|
||||
if((*itr)->closed != 0 || !objmgr.GetPlayer((*itr)->playerGuid))
|
||||
continue;
|
||||
|
||||
std::stringstream message;
|
||||
@@ -307,10 +308,11 @@ bool ChatHandler::HandleGMTicketListOnlineCommand(const char* args)
|
||||
message << ".|r |cff00ff00Last change:|r |cff00ccff " << secsToTimeString((time(NULL) - (*itr)->timestamp), true, false) << " ago.";
|
||||
if((*itr)->assignedToGM != 0 && objmgr.GetPlayer((*itr)->assignedToGM))
|
||||
{
|
||||
std::string gmname = objmgr.GetPlayer((*itr)->assignedToGM)->GetName();
|
||||
std::string gmname;
|
||||
objmgr.GetPlayerNameByGUID((*itr)->assignedToGM, gmname);
|
||||
message << "|r |cff00ff00Assigned to:|r |cff00ccff " << gmname;
|
||||
}
|
||||
SendGlobalGMSysMessage(message.str().c_str());
|
||||
SendSysMessage(message.str().c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -334,7 +336,8 @@ bool ChatHandler::HandleGMTicketGetByIdCommand(const char* args)
|
||||
message << ".|r |cff00ff00Last change:|r |cff00ccff " << secsToTimeString((time(NULL)-ticket->timestamp), true, false) << " ago.";
|
||||
if(ticket->assignedToGM != 0 && objmgr.GetPlayer(ticket->assignedToGM))
|
||||
{
|
||||
std::string gmname = objmgr.GetPlayer(ticket->assignedToGM)->GetName();
|
||||
std::string gmname;
|
||||
objmgr.GetPlayerNameByGUID(ticket->assignedToGM, gmname);
|
||||
message << "|r |cff00ff00Assigned to:|r |cff00ccff " << gmname;
|
||||
}
|
||||
message << "|r\n|cff00ff00Message:|r " << ticket->message;
|
||||
@@ -342,7 +345,7 @@ bool ChatHandler::HandleGMTicketGetByIdCommand(const char* args)
|
||||
{
|
||||
message << "|r |cff00ff00Comment:|r |cff00ccff " << ticket->comment;
|
||||
}
|
||||
PSendSysMessage(message.str().c_str());
|
||||
SendSysMessage(message.str().c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -364,7 +367,8 @@ bool ChatHandler::HandleGMTicketGetByNameCommand(const char* args)
|
||||
message << ".|r |cff00ff00Last change:|r |cff00ccff " << secsToTimeString((time(NULL)-ticket->timestamp), true, false) << " ago.";
|
||||
if(ticket->assignedToGM != 0 && objmgr.GetPlayer(ticket->assignedToGM))
|
||||
{
|
||||
std::string gmname = objmgr.GetPlayer(ticket->assignedToGM)->GetName();
|
||||
std::string gmname;
|
||||
objmgr.GetPlayerNameByGUID(ticket->assignedToGM, gmname);
|
||||
message << "|r |cff00ff00Assigned to:|r |cff00ccff " << gmname;
|
||||
}
|
||||
message << "|r\n|cff00ff00Message:|r " << ticket->message;
|
||||
@@ -372,7 +376,7 @@ bool ChatHandler::HandleGMTicketGetByNameCommand(const char* args)
|
||||
{
|
||||
message << "|r |cff00ff00Comment:|r |cff00ccff " << ticket->comment;
|
||||
}
|
||||
PSendSysMessage(message.str().c_str());
|
||||
SendSysMessage(message.str().c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -383,22 +387,22 @@ bool ChatHandler::HandleGMTicketCloseByIdCommand(const char* args)
|
||||
|
||||
uint64 tguid = atoi(args);
|
||||
GM_Ticket *ticket = ticketmgr.GetGMTicket(tguid);
|
||||
if(!ticket || ticket->closed == 1)
|
||||
if(!ticket || ticket->closed != 0)
|
||||
{
|
||||
SendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
if(ticket && ticket->assignedToGM != 0 && ticket->assignedToGM != m_session->GetPlayer()->GetGUID())
|
||||
{
|
||||
PSendSysMessage(LANG_COMMAND_TICKETCANNOTCLOSE, ticket->guid);
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
sWorld.SendGMText(LANG_COMMAND_TICKETCLOSED, ticket->name.c_str(), ticket->guid);
|
||||
ticketmgr.RemoveGMTicket(ticket->guid);
|
||||
sWorld.SendGMText(LANG_COMMAND_TICKETCLOSED, m_session->GetPlayer()->GetName(), ticket->guid);
|
||||
ticketmgr.RemoveGMTicket(ticket->guid, m_session->GetPlayer()->GetGUID());
|
||||
Player *plr = objmgr.GetPlayer(ticket->playerGuid);
|
||||
|
||||
if(!plr || !plr->IsInWorld())
|
||||
return false;
|
||||
return true;
|
||||
|
||||
// send abandon ticket
|
||||
WorldPacket data(SMSG_GMTICKET_DELETETICKET, 4);
|
||||
@@ -428,40 +432,38 @@ bool ChatHandler::HandleGMTicketAssignToCommand(const char* args)
|
||||
std::string gmname;
|
||||
GM_Ticket *ticket = ticketmgr.GetGMTicket(ticketGuid);
|
||||
|
||||
if(!ticket || ticket->closed == 1)
|
||||
if(!ticket || ticket->closed != 0)
|
||||
{
|
||||
SendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
|
||||
return true;
|
||||
}
|
||||
Player *plr = objmgr.GetPlayer(targm.c_str());
|
||||
if(!plr || !plr->IsInWorld() || plr->GetSession()->GetSecurity() < SEC_MODERATOR)
|
||||
uint64 tarGUID = objmgr.GetPlayerGUIDByName(targm.c_str());
|
||||
uint64 accid = objmgr.GetPlayerAccountIdByGUID(tarGUID);
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT `gmlevel` FROM `account` WHERE `id` = '%u'", accid);
|
||||
if(!tarGUID|| !result || result->Fetch()->GetUInt32() < SEC_MODERATOR)
|
||||
{
|
||||
SendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_A);
|
||||
return true;
|
||||
}
|
||||
if(ticket->assignedToGM == plr->GetGUID())
|
||||
if(ticket->assignedToGM == tarGUID)
|
||||
{
|
||||
PSendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_B, ticket->guid);
|
||||
return true;
|
||||
}
|
||||
objmgr.GetPlayerNameByGUID(tarGUID, gmname);
|
||||
if(ticket->assignedToGM != 0 && ticket->assignedToGM != cplr->GetGUID())
|
||||
{
|
||||
Player *aplr = objmgr.GetPlayer(ticket->assignedToGM);
|
||||
if(aplr && aplr->IsInWorld())
|
||||
{
|
||||
gmname = aplr->GetName();
|
||||
PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->guid, gmname.c_str());
|
||||
return true;
|
||||
}
|
||||
PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->guid, gmname.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
ticket->assignedToGM = plr->GetGUID();
|
||||
ticket->assignedToGM = tarGUID;
|
||||
ticketmgr.UpdateGMTicket(ticket);
|
||||
std::stringstream ss;
|
||||
ss << "|cff00ff00Ticket:|r ";
|
||||
ss << "|cffff00ff" << ticket->guid << ". " << cplr->GetName() << "|r";
|
||||
ss << "|cff00ff00 assigned to:|r ";
|
||||
ss << "|cffff00ff\"" << targetgm << "\".";
|
||||
ss << "|cffff00ff\"" << gmname << "\".";
|
||||
SendGlobalGMSysMessage(ss.str().c_str());
|
||||
return true;
|
||||
}
|
||||
@@ -475,19 +477,20 @@ bool ChatHandler::HandleGMTicketUnAssignCommand(const char* args)
|
||||
Player *cplr = m_session->GetPlayer();
|
||||
GM_Ticket *ticket = ticketmgr.GetGMTicket(ticketGuid);
|
||||
|
||||
if(!ticket|| ticket->closed)
|
||||
if(!ticket|| ticket->closed != 0)
|
||||
{
|
||||
SendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
|
||||
return true;
|
||||
}
|
||||
if(ticket->assignedToGM = 0)
|
||||
if(ticket->assignedToGM == 0)
|
||||
{
|
||||
SendSysMessage(LANG_COMMAND_TICKETNOTASSIGNED);
|
||||
return true;
|
||||
}
|
||||
|
||||
Player *plr = objmgr.GetPlayer(ticket->assignedToGM);
|
||||
|
||||
std::string gmname;
|
||||
objmgr.GetPlayerNameByGUID(ticket->assignedToGM, gmname);
|
||||
Player *plr = objmgr.GetPlayer(ticket->assignedToGM);
|
||||
if(plr && plr->IsInWorld() && plr->GetSession()->GetSecurity() > cplr->GetSession()->GetSecurity())
|
||||
{
|
||||
SendSysMessage(LANG_COMMAND_TICKETUNASSIGNSECURITY);
|
||||
@@ -519,7 +522,7 @@ bool ChatHandler::HandleGMTicketCommentCommand(const char* args)
|
||||
Player *cplr = m_session->GetPlayer();
|
||||
GM_Ticket *ticket = ticketmgr.GetGMTicket(ticketGuid);
|
||||
|
||||
if(!ticket || ticket->closed == 1)
|
||||
if(!ticket || ticket->closed != 0)
|
||||
{
|
||||
PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
|
||||
return true;
|
||||
@@ -553,14 +556,17 @@ bool ChatHandler::HandleGMTicketDeleteByIdCommand(const char* args)
|
||||
SendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
|
||||
return true;
|
||||
}
|
||||
if(!ticket->closed == 1)
|
||||
if(ticket->closed == 0)
|
||||
{
|
||||
SendSysMessage(LANG_COMMAND_TICKETCLOSEFIRST);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string gmname = m_session->GetPlayer()->GetName();
|
||||
sWorld.SendGMText(LANG_COMMAND_TICKETDELETED, ticket->guid, gmname.c_str());
|
||||
std::stringstream ss;
|
||||
ss << "|cff00ff00Ticket:|r ";
|
||||
ss << "|cffff00ff" << m_session->GetPlayer()->GetName() << "|r";
|
||||
ss << "|cff00ff00 deleted.|r";
|
||||
SendGlobalGMSysMessage(ss.str().c_str());
|
||||
Player *plr = objmgr.GetPlayer(ticket->playerGuid);
|
||||
ticketmgr.DeleteGMTicketPermanently(ticket->guid);
|
||||
if(plr && plr->IsInWorld())
|
||||
|
||||
+9
-9
@@ -115,7 +115,7 @@ bool ChatHandler::HandleMuteCommand(const char* args)
|
||||
if (chr)
|
||||
chr->GetSession()->m_muteTime = mutetime;
|
||||
|
||||
loginDatabase.PExecute("UPDATE account SET mutetime = " I64FMTD " WHERE id = '%u'",uint64(mutetime), account_id );
|
||||
LoginDatabase.PExecute("UPDATE account SET mutetime = " I64FMTD " WHERE id = '%u'",uint64(mutetime), account_id );
|
||||
|
||||
if(chr)
|
||||
ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notspeaktime);
|
||||
@@ -188,7 +188,7 @@ bool ChatHandler::HandleUnmuteCommand(const char* args)
|
||||
chr->GetSession()->m_muteTime = 0;
|
||||
}
|
||||
|
||||
loginDatabase.PExecute("UPDATE account SET mutetime = '0' WHERE id = '%u'", account_id );
|
||||
LoginDatabase.PExecute("UPDATE account SET mutetime = '0' WHERE id = '%u'", account_id );
|
||||
|
||||
if(chr)
|
||||
ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_ENABLED);
|
||||
@@ -1896,7 +1896,7 @@ bool ChatHandler::HandlePInfoCommand(const char* args)
|
||||
uint32 security = 0;
|
||||
std::string last_login = GetTrinityString(LANG_ERROR);
|
||||
|
||||
QueryResult* result = loginDatabase.PQuery("SELECT username,gmlevel,last_ip,last_login FROM account WHERE id = '%u'",accId);
|
||||
QueryResult* result = LoginDatabase.PQuery("SELECT username,gmlevel,last_ip,last_login FROM account WHERE id = '%u'",accId);
|
||||
if(result)
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
@@ -3870,9 +3870,9 @@ bool ChatHandler::HandleLookupPlayerIpCommand(const char* args)
|
||||
char* limit_str = strtok (NULL, " ");
|
||||
int32 limit = limit_str ? atoi (limit_str) : -1;
|
||||
|
||||
loginDatabase.escape_string (ip);
|
||||
LoginDatabase.escape_string (ip);
|
||||
|
||||
QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE last_ip = '%s'", ip.c_str ());
|
||||
QueryResult* result = LoginDatabase.PQuery ("SELECT id,username FROM account WHERE last_ip = '%s'", ip.c_str ());
|
||||
|
||||
return LookupPlayerSearchCommand (result,limit);
|
||||
}
|
||||
@@ -3889,9 +3889,9 @@ bool ChatHandler::HandleLookupPlayerAccountCommand(const char* args)
|
||||
if (!AccountMgr::normilizeString (account))
|
||||
return false;
|
||||
|
||||
loginDatabase.escape_string (account);
|
||||
LoginDatabase.escape_string (account);
|
||||
|
||||
QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE username = '%s'", account.c_str ());
|
||||
QueryResult* result = LoginDatabase.PQuery ("SELECT id,username FROM account WHERE username = '%s'", account.c_str ());
|
||||
|
||||
return LookupPlayerSearchCommand (result,limit);
|
||||
}
|
||||
@@ -3906,9 +3906,9 @@ bool ChatHandler::HandleLookupPlayerEmailCommand(const char* args)
|
||||
char* limit_str = strtok (NULL, " ");
|
||||
int32 limit = limit_str ? atoi (limit_str) : -1;
|
||||
|
||||
loginDatabase.escape_string (email);
|
||||
LoginDatabase.escape_string (email);
|
||||
|
||||
QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE email = '%s'", email.c_str ());
|
||||
QueryResult* result = LoginDatabase.PQuery ("SELECT id,username FROM account WHERE email = '%s'", email.c_str ());
|
||||
|
||||
return LookupPlayerSearchCommand (result,limit);
|
||||
}
|
||||
|
||||
+19
-19
@@ -764,7 +764,7 @@ bool ChatHandler::HandleAccountSetGmLevelCommand(const char* args)
|
||||
PSendSysMessage(LANG_YOURS_SECURITY_CHANGED, m_session->GetPlayer()->GetName(), gm);
|
||||
}
|
||||
|
||||
loginDatabase.PExecute("UPDATE account SET gmlevel = '%d' WHERE id = '%u'", gm, targetAccountId);
|
||||
LoginDatabase.PExecute("UPDATE account SET gmlevel = '%d' WHERE id = '%u'", gm, targetAccountId);
|
||||
return true;
|
||||
}else
|
||||
{
|
||||
@@ -805,7 +805,7 @@ bool ChatHandler::HandleAccountSetGmLevelCommand(const char* args)
|
||||
}
|
||||
|
||||
PSendSysMessage(LANG_YOU_CHANGE_SECURITY, targetAccountName.c_str(), gm);
|
||||
loginDatabase.PExecute("UPDATE account SET gmlevel = '%d' WHERE id = '%u'", gm, targetAccountId);
|
||||
LoginDatabase.PExecute("UPDATE account SET gmlevel = '%d' WHERE id = '%u'", gm, targetAccountId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -5213,7 +5213,7 @@ bool ChatHandler::HandleBanInfoCharacterCommand(const char* args)
|
||||
|
||||
bool ChatHandler::HandleBanInfoHelper(uint32 accountid, char const* accountname)
|
||||
{
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT FROM_UNIXTIME(bandate), unbandate-bandate, active, unbandate,banreason,bannedby FROM account_banned WHERE id = '%u' ORDER BY bandate ASC",accountid);
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT FROM_UNIXTIME(bandate), unbandate-bandate, active, unbandate,banreason,bannedby FROM account_banned WHERE id = '%u' ORDER BY bandate ASC",accountid);
|
||||
if(!result)
|
||||
{
|
||||
PSendSysMessage(LANG_BANINFO_NOACCOUNTBAN, accountname);
|
||||
@@ -5253,8 +5253,8 @@ bool ChatHandler::HandleBanInfoIPCommand(const char* args)
|
||||
|
||||
std::string IP = cIP;
|
||||
|
||||
loginDatabase.escape_string(IP);
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT ip, FROM_UNIXTIME(bandate), FROM_UNIXTIME(unbandate), unbandate-UNIX_TIMESTAMP(), banreason,bannedby,unbandate-bandate FROM ip_banned WHERE ip = '%s'",IP.c_str());
|
||||
LoginDatabase.escape_string(IP);
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT ip, FROM_UNIXTIME(bandate), FROM_UNIXTIME(unbandate), unbandate-UNIX_TIMESTAMP(), banreason,bannedby,unbandate-bandate FROM ip_banned WHERE ip = '%s'",IP.c_str());
|
||||
if(!result)
|
||||
{
|
||||
PSendSysMessage(LANG_BANINFO_NOIP);
|
||||
@@ -5272,14 +5272,14 @@ bool ChatHandler::HandleBanInfoIPCommand(const char* args)
|
||||
|
||||
bool ChatHandler::HandleBanListCharacterCommand(const char* args)
|
||||
{
|
||||
loginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||
LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||
|
||||
char* cFilter = strtok ((char*)args, " ");
|
||||
if(!cFilter)
|
||||
return false;
|
||||
|
||||
std::string filter = cFilter;
|
||||
loginDatabase.escape_string(filter);
|
||||
LoginDatabase.escape_string(filter);
|
||||
QueryResult* result = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"),filter.c_str());
|
||||
if (!result)
|
||||
{
|
||||
@@ -5292,22 +5292,22 @@ bool ChatHandler::HandleBanListCharacterCommand(const char* args)
|
||||
|
||||
bool ChatHandler::HandleBanListAccountCommand(const char* args)
|
||||
{
|
||||
loginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||
LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||
|
||||
char* cFilter = strtok((char*)args, " ");
|
||||
std::string filter = cFilter ? cFilter : "";
|
||||
loginDatabase.escape_string(filter);
|
||||
LoginDatabase.escape_string(filter);
|
||||
|
||||
QueryResult* result;
|
||||
|
||||
if(filter.empty())
|
||||
{
|
||||
result = loginDatabase.Query("SELECT account.id, username FROM account, account_banned"
|
||||
result = LoginDatabase.Query("SELECT account.id, username FROM account, account_banned"
|
||||
" WHERE account.id = account_banned.id AND active = 1 GROUP BY account.id");
|
||||
}
|
||||
else
|
||||
{
|
||||
result = loginDatabase.PQuery("SELECT account.id, username FROM account, account_banned"
|
||||
result = LoginDatabase.PQuery("SELECT account.id, username FROM account, account_banned"
|
||||
" WHERE account.id = account_banned.id AND active = 1 AND username "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")" GROUP BY account.id",
|
||||
filter.c_str());
|
||||
}
|
||||
@@ -5333,7 +5333,7 @@ bool ChatHandler::HandleBanListHelper(QueryResult* result)
|
||||
Field* fields = result->Fetch();
|
||||
uint32 accountid = fields[0].GetUInt32();
|
||||
|
||||
QueryResult* banresult = loginDatabase.PQuery("SELECT account.username FROM account,account_banned WHERE account_banned.id='%u' AND account_banned.id=account.id",accountid);
|
||||
QueryResult* banresult = LoginDatabase.PQuery("SELECT account.username FROM account,account_banned WHERE account_banned.id='%u' AND account_banned.id=account.id",accountid);
|
||||
if(banresult)
|
||||
{
|
||||
Field* fields2 = banresult->Fetch();
|
||||
@@ -5364,7 +5364,7 @@ bool ChatHandler::HandleBanListHelper(QueryResult* result)
|
||||
accmgr.GetName (account_id,account_name);
|
||||
|
||||
// No SQL injection. id is uint32.
|
||||
QueryResult *banInfo = loginDatabase.PQuery("SELECT bandate,unbandate,bannedby,banreason FROM account_banned WHERE id = %u ORDER BY unbandate", account_id);
|
||||
QueryResult *banInfo = LoginDatabase.PQuery("SELECT bandate,unbandate,bannedby,banreason FROM account_banned WHERE id = %u ORDER BY unbandate", account_id);
|
||||
if (banInfo)
|
||||
{
|
||||
Field *fields2 = banInfo->Fetch();
|
||||
@@ -5401,23 +5401,23 @@ bool ChatHandler::HandleBanListHelper(QueryResult* result)
|
||||
|
||||
bool ChatHandler::HandleBanListIPCommand(const char* args)
|
||||
{
|
||||
loginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||
LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||
|
||||
char* cFilter = strtok((char*)args, " ");
|
||||
std::string filter = cFilter ? cFilter : "";
|
||||
loginDatabase.escape_string(filter);
|
||||
LoginDatabase.escape_string(filter);
|
||||
|
||||
QueryResult* result;
|
||||
|
||||
if(filter.empty())
|
||||
{
|
||||
result = loginDatabase.Query ("SELECT ip,bandate,unbandate,bannedby,banreason FROM ip_banned"
|
||||
result = LoginDatabase.Query ("SELECT ip,bandate,unbandate,bannedby,banreason FROM ip_banned"
|
||||
" WHERE (bandate=unbandate OR unbandate>UNIX_TIMESTAMP())"
|
||||
" ORDER BY unbandate" );
|
||||
}
|
||||
else
|
||||
{
|
||||
result = loginDatabase.PQuery( "SELECT ip,bandate,unbandate,bannedby,banreason FROM ip_banned"
|
||||
result = LoginDatabase.PQuery( "SELECT ip,bandate,unbandate,bannedby,banreason FROM ip_banned"
|
||||
" WHERE (bandate=unbandate OR unbandate>UNIX_TIMESTAMP()) AND ip "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")
|
||||
" ORDER BY unbandate",filter.c_str() );
|
||||
}
|
||||
@@ -6205,7 +6205,7 @@ bool ChatHandler::HandleInstanceSaveDataCommand(const char * /*args*/)
|
||||
bool ChatHandler::HandleGMListFullCommand(const char* /*args*/)
|
||||
{
|
||||
///- Get the accounts with GM Level >0
|
||||
QueryResult *result = loginDatabase.Query( "SELECT username,gmlevel FROM account WHERE gmlevel > 0" );
|
||||
QueryResult *result = LoginDatabase.Query( "SELECT username,gmlevel FROM account WHERE gmlevel > 0" );
|
||||
if(result)
|
||||
{
|
||||
SendSysMessage(LANG_GMLIST);
|
||||
@@ -6284,7 +6284,7 @@ bool ChatHandler::HandleAccountSetAddonCommand(const char* args)
|
||||
return false;
|
||||
|
||||
// No SQL injection
|
||||
loginDatabase.PExecute("UPDATE account SET expansion = '%d' WHERE id = '%u'",lev,account_id);
|
||||
LoginDatabase.PExecute("UPDATE account SET expansion = '%d' WHERE id = '%u'",lev,account_id);
|
||||
PSendSysMessage(LANG_ACCOUNT_SETADDON,account_name.c_str(),account_id,lev);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1367,7 +1367,7 @@ void WorldSession::HandleWhoisOpcode(WorldPacket& recv_data)
|
||||
|
||||
uint32 accid = plr->GetSession()->GetAccountId();
|
||||
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT username,email,last_ip FROM account WHERE id=%u", accid);
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT username,email,last_ip FROM account WHERE id=%u", accid);
|
||||
if(!result)
|
||||
{
|
||||
SendNotification(LANG_ACCOUNT_FOR_PLAYER_NOT_FOUND, charname.c_str());
|
||||
|
||||
@@ -73,6 +73,9 @@ void PetAI::AttackStart(Unit *u)
|
||||
|
||||
if(i_pet.Attack(u,true))
|
||||
{
|
||||
i_pet.SetInCombatWith(u);
|
||||
u->SetInCombatWith(&i_pet);
|
||||
|
||||
i_pet.clearUnitState(UNIT_STAT_FOLLOW);
|
||||
// TMGs call CreatureRelocation which via MoveInLineOfSight can call this function
|
||||
// thus with the following clear the original TMG gets invalidated and crash, doh
|
||||
|
||||
+13
-7
@@ -3748,7 +3748,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
|
||||
CharacterDatabase.PExecute("DELETE FROM character_achievement_progress WHERE guid = '%u'",guid);
|
||||
CharacterDatabase.CommitTransaction();
|
||||
|
||||
//loginDatabase.PExecute("UPDATE realmcharacters SET numchars = numchars - 1 WHERE acctid = %d AND realmid = %d", accountId, realmID);
|
||||
//LoginDatabase.PExecute("UPDATE realmcharacters SET numchars = numchars - 1 WHERE acctid = %d AND realmid = %d", accountId, realmID);
|
||||
if(updateRealmChars) sWorld.UpdateRealmCharCount(accountId);
|
||||
}
|
||||
|
||||
@@ -3815,7 +3815,7 @@ void Player::BuildPlayerRepop()
|
||||
// BG - remove insignia related
|
||||
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
|
||||
|
||||
SendCorpseReclaimDelay();
|
||||
// SendCorpseReclaimDelay();
|
||||
|
||||
// to prevent cheating
|
||||
corpse->ResetGhostTime();
|
||||
@@ -3923,6 +3923,7 @@ void Player::KillPlayer()
|
||||
m_deathTimer = 6*MINUTE*1000;
|
||||
|
||||
UpdateCorpseReclaimDelay(); // dependent at use SetDeathPvP() call before kill
|
||||
SendCorpseReclaimDelay();
|
||||
|
||||
// don't create corpse at this moment, player might be falling
|
||||
|
||||
@@ -19283,7 +19284,8 @@ uint32 Player::GetCorpseReclaimDelay(bool pvp) const
|
||||
|
||||
time_t now = time(NULL);
|
||||
// 0..2 full period
|
||||
uint32 count = (now < m_deathExpireTime) ? (m_deathExpireTime - now)/DEATH_EXPIRE_STEP : 0;
|
||||
// should be ceil(x)-1 but not floor(x)
|
||||
uint32 count = (now < m_deathExpireTime - 1) ? (m_deathExpireTime - 1 - now)/DEATH_EXPIRE_STEP : 0;
|
||||
return copseReclaimDelay[count];
|
||||
}
|
||||
|
||||
@@ -19312,17 +19314,21 @@ void Player::UpdateCorpseReclaimDelay()
|
||||
void Player::SendCorpseReclaimDelay(bool load)
|
||||
{
|
||||
Corpse* corpse = GetCorpse();
|
||||
if(!corpse)
|
||||
if(load && !corpse)
|
||||
return;
|
||||
|
||||
bool pvp;
|
||||
if(corpse)
|
||||
pvp = (corpse->GetType() == CORPSE_RESURRECTABLE_PVP);
|
||||
else
|
||||
pvp = (m_ExtraFlags & PLAYER_EXTRA_PVP_DEATH);
|
||||
|
||||
uint32 delay;
|
||||
if(load)
|
||||
{
|
||||
if(corpse->GetGhostTime() > m_deathExpireTime)
|
||||
return;
|
||||
|
||||
bool pvp = corpse->GetType()==CORPSE_RESURRECTABLE_PVP;
|
||||
|
||||
uint32 count;
|
||||
if( pvp && sWorld.getConfig(CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP) ||
|
||||
!pvp && sWorld.getConfig(CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE) )
|
||||
@@ -19343,7 +19349,7 @@ void Player::SendCorpseReclaimDelay(bool load)
|
||||
delay = expected_time-now;
|
||||
}
|
||||
else
|
||||
delay = GetCorpseReclaimDelay(corpse->GetType()==CORPSE_RESURRECTABLE_PVP);
|
||||
delay = GetCorpseReclaimDelay(pvp);
|
||||
|
||||
//! corpse reclaim delay 30 * 1000ms or longer at often deaths
|
||||
WorldPacket data(SMSG_CORPSE_RECLAIM_DELAY, 4);
|
||||
|
||||
+16
-10
@@ -938,7 +938,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
|
||||
SpellNonMeleeDamage damageInfo(caster, unitTarget, m_spellInfo->Id, m_spellSchoolMask);
|
||||
|
||||
// Add bonuses and fill damageInfo struct
|
||||
caster->CalculateSpellDamage(&damageInfo, m_damage, m_spellInfo);
|
||||
caster->CalculateSpellDamageTaken(&damageInfo, m_damage, m_spellInfo);
|
||||
|
||||
// Send log damage message to client
|
||||
caster->SendSpellNonMeleeDamageLog(&damageInfo);
|
||||
@@ -5536,19 +5536,14 @@ void Spell::CalculateDamageDoneForAllTargets()
|
||||
|
||||
int32 Spell::CalculateDamageDone(Unit *unit, const uint32 effectMask, float *multiplier)
|
||||
{
|
||||
m_damage = 0;
|
||||
int32 damageDone = 0;
|
||||
unitTarget = unit;
|
||||
for(uint32 i = 0; i < 3; ++i)
|
||||
{
|
||||
if (effectMask & (1<<i))
|
||||
{
|
||||
if(m_applyMultiplierMask & (1 << i))
|
||||
{
|
||||
damage = CalculateDamage(i, NULL) * m_damageMultipliers[i];
|
||||
m_damageMultipliers[i] *= multiplier[i];
|
||||
}
|
||||
else
|
||||
damage = CalculateDamage(i, NULL);
|
||||
m_damage = 0;
|
||||
damage = CalculateDamage(i, NULL);
|
||||
|
||||
switch(m_spellInfo->Effect[i])
|
||||
{
|
||||
@@ -5565,7 +5560,18 @@ int32 Spell::CalculateDamageDone(Unit *unit, const uint32 effectMask, float *mul
|
||||
SpellDamageHeal(i);
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_damage > 0 && m_originalCaster)
|
||||
m_damage = m_originalCaster->SpellDamageBonus(unit, m_spellInfo, m_damage, SPELL_DIRECT_DAMAGE);
|
||||
if(m_applyMultiplierMask & (1 << i))
|
||||
{
|
||||
m_damage *= m_damageMultipliers[i];
|
||||
m_damageMultipliers[i] *= multiplier[i];
|
||||
}
|
||||
|
||||
damageDone += m_damage;
|
||||
}
|
||||
}
|
||||
return m_damage;
|
||||
|
||||
return damageDone;
|
||||
}
|
||||
|
||||
@@ -6033,7 +6033,8 @@ void Aura::PeriodicTick()
|
||||
SpellEntry const* spellProto = GetSpellProto();
|
||||
//maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG
|
||||
SpellNonMeleeDamage damageInfo(pCaster, m_target, spellProto->Id, spellProto->SchoolMask);
|
||||
pCaster->CalculateSpellDamage(&damageInfo, gain, spellProto);
|
||||
//no SpellDamageBonus for burn mana
|
||||
pCaster->CalculateSpellDamageTaken(&damageInfo, gain, spellProto);
|
||||
pCaster->SendSpellNonMeleeDamageLog(&damageInfo);
|
||||
|
||||
// Set trigger flag
|
||||
|
||||
@@ -36,8 +36,6 @@ void WorldSession::HandleGMTicketCreateOpcode( WorldPacket & recv_data )
|
||||
// always do a packet check
|
||||
CHECK_PACKET_SIZE(recv_data, 4*4+1+2*4);
|
||||
|
||||
uint32 map;
|
||||
float x, y, z;
|
||||
std::string ticketText = "";
|
||||
std::string ticketText2 = "";
|
||||
GM_Ticket *ticket = new GM_Ticket;
|
||||
@@ -45,13 +43,9 @@ void WorldSession::HandleGMTicketCreateOpcode( WorldPacket & recv_data )
|
||||
WorldPacket data(SMSG_GMTICKET_CREATE, 4);
|
||||
|
||||
// recv Data
|
||||
recv_data >> map;
|
||||
recv_data >> x;
|
||||
recv_data >> y;
|
||||
recv_data >> z;
|
||||
recv_data >> ticketText;
|
||||
|
||||
// get additional data
|
||||
// get additional data, rarely used
|
||||
recv_data >> ticketText2;
|
||||
|
||||
// assign values
|
||||
@@ -65,7 +59,7 @@ void WorldSession::HandleGMTicketCreateOpcode( WorldPacket & recv_data )
|
||||
ticket->comment = "";
|
||||
|
||||
// remove ticket by player, shouldn't happen
|
||||
ticketmgr.RemoveGMTicketByPlayer(GetPlayer()->GetGUID());
|
||||
ticketmgr.RemoveGMTicketByPlayer(GetPlayer()->GetGUID(), GetPlayer()->GetGUID());
|
||||
|
||||
// add ticket
|
||||
ticketmgr.AddGMTicket(ticket, false);
|
||||
@@ -140,7 +134,7 @@ void WorldSession::HandleGMTicketDeleteOpcode( WorldPacket & /*recv_data*/)
|
||||
SendPacket(&data);
|
||||
|
||||
sWorld.SendGMText(LANG_COMMAND_TICKETPLAYERABANDON, GetPlayer()->GetName(), ticket->guid );
|
||||
ticketmgr.RemoveGMTicketByPlayer(GetPlayer()->GetGUID());
|
||||
ticketmgr.RemoveGMTicketByPlayer(GetPlayer()->GetGUID(), GetPlayer()->GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+18
-22
@@ -24,13 +24,9 @@
|
||||
#include "ObjectMgr.h"
|
||||
#include "Language.h"
|
||||
#include "Player.h"
|
||||
INSTANTIATE_SINGLETON_1( TicketMgr );
|
||||
|
||||
#include "Common.h"
|
||||
//#include "Log.h"
|
||||
#include "ObjectAccessor.h"
|
||||
|
||||
|
||||
INSTANTIATE_SINGLETON_1( TicketMgr );
|
||||
|
||||
GM_Ticket* TicketMgr::GetGMTicket(uint64 ticketGuid)
|
||||
{
|
||||
@@ -106,7 +102,7 @@ void TicketMgr::DeleteGMTicketPermanently(uint64 ticketGuid)
|
||||
}
|
||||
|
||||
// delete database record
|
||||
CharacterDatabase.PExecute("DELETE FROM gm_tickets WHERE guid=%u", ticketGuid);
|
||||
CharacterDatabase.PExecute("DELETE FROM `gm_tickets` WHERE guid= '%u'", ticketGuid);
|
||||
}
|
||||
|
||||
|
||||
@@ -114,13 +110,13 @@ void TicketMgr::LoadGMTickets()
|
||||
{
|
||||
// Delete all out of object holder
|
||||
GM_TicketList.clear();
|
||||
QueryResult *result = CharacterDatabase.Query( "SELECT `guid`, `playerGuid`, `name`, `message`, `timestamp`, `closed`, `assignedto`, `comment` FROM gm_tickets WHERE closed = '0'" );
|
||||
QueryResult *result = CharacterDatabase.Query( "SELECT `guid`, `playerGuid`, `name`, `message`, `timestamp`, `closed`, `assignedto`, `comment` FROM `gm_tickets` WHERE `closed` = '0'" );
|
||||
GM_Ticket *ticket;
|
||||
|
||||
//ticket = NULL;
|
||||
if(!result)
|
||||
return;
|
||||
|
||||
// Assign values from SQL to the object holder
|
||||
do
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
@@ -143,13 +139,13 @@ void TicketMgr::LoadGMTickets()
|
||||
delete result;
|
||||
}
|
||||
|
||||
void TicketMgr::RemoveGMTicket(uint64 ticketGuid)
|
||||
void TicketMgr::RemoveGMTicket(uint64 ticketGuid, uint64 GMguid)
|
||||
{
|
||||
for(GmTicketList::iterator i = GM_TicketList.begin(); i != GM_TicketList.end();)
|
||||
{
|
||||
if((*i)->guid == ticketGuid && (*i)->closed == 0)
|
||||
{
|
||||
(*i)->closed = 1;
|
||||
(*i)->closed = GMguid;
|
||||
SaveGMTicket((*i));
|
||||
}
|
||||
++i;
|
||||
@@ -157,13 +153,13 @@ void TicketMgr::RemoveGMTicket(uint64 ticketGuid)
|
||||
}
|
||||
|
||||
|
||||
void TicketMgr::RemoveGMTicketByPlayer(uint64 playerGuid)
|
||||
void TicketMgr::RemoveGMTicketByPlayer(uint64 playerGuid, uint64 GMguid)
|
||||
{
|
||||
for(GmTicketList::iterator i = GM_TicketList.begin(); i != GM_TicketList.end();)
|
||||
{
|
||||
if((*i)->playerGuid == playerGuid && (*i)->closed == 0)
|
||||
{
|
||||
(*i)->closed = true;
|
||||
(*i)->closed = GMguid;
|
||||
SaveGMTicket((*i));
|
||||
}
|
||||
++i;
|
||||
@@ -173,15 +169,15 @@ void TicketMgr::RemoveGMTicketByPlayer(uint64 playerGuid)
|
||||
void TicketMgr::SaveGMTicket(GM_Ticket* ticket)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "REPLACE INTO gm_tickets (`guid`, `playerGuid`, `name`, `message`, `timestamp`, `closed`, `assignedto`, `comment`) VALUES(";
|
||||
ss << ticket->guid << ", ";
|
||||
ss << ticket->playerGuid << ", '";
|
||||
ss << ticket->name << "', '";
|
||||
ss << ticket->message << "', " ;
|
||||
ss << ticket->timestamp << ", ";
|
||||
ss << ticket->closed << ", '";
|
||||
ss << ticket->assignedToGM << "', '";
|
||||
ss << ticket->comment << "');";
|
||||
ss << "REPLACE INTO `gm_tickets` (`guid`, `playerGuid`, `name`, `message`, `timestamp`, `closed`, `assignedto`, `comment`) VALUES(\"";
|
||||
ss << ticket->guid << "\", \"";
|
||||
ss << ticket->playerGuid << "\", \"";
|
||||
ss << ticket->name << "\", \"";
|
||||
ss << ticket->message << "\", \"" ;
|
||||
ss << ticket->timestamp << "\", \"";
|
||||
ss << ticket->closed << "\", \"";
|
||||
ss << ticket->assignedToGM << "\", \"";
|
||||
ss << ticket->comment << "\");";
|
||||
|
||||
CharacterDatabase.BeginTransaction();
|
||||
CharacterDatabase.Execute(ss.str().c_str());
|
||||
@@ -203,5 +199,5 @@ uint64 TicketMgr::GenerateTicketID()
|
||||
delete result;
|
||||
}
|
||||
|
||||
return m_ticketid;
|
||||
return ++m_ticketid;
|
||||
}
|
||||
+3
-17
@@ -39,27 +39,13 @@ struct GM_Ticket
|
||||
std::string comment;
|
||||
};
|
||||
|
||||
enum GMticketType
|
||||
{
|
||||
GM_TICKET_TYPE_STUCK = 1,
|
||||
GM_TICKET_TYPE_BEHAVIOR_HARASSMENT = 2,
|
||||
GM_TICKET_TYPE_GUILD = 3,
|
||||
GM_TICKET_TYPE_ITEM = 4,
|
||||
GM_TICKET_TYPE_ENVIRONMENTAL = 5,
|
||||
GM_TICKET_TYPE_NON_QUEST_CREEP = 6,
|
||||
GM_TICKET_TYPE_QUEST_QUEST_NPC = 7,
|
||||
GM_TICKET_TYPE_TECHNICAL = 8,
|
||||
GM_TICKET_TYPE_ACCOUNT_BILLING = 9,
|
||||
GM_TICKET_TYPE_CHARACTER = 10
|
||||
};
|
||||
|
||||
// Map Typedef
|
||||
typedef std::list<GM_Ticket*> GmTicketList;
|
||||
|
||||
class TicketMgr
|
||||
{
|
||||
public:
|
||||
TicketMgr(){} //constructor
|
||||
TicketMgr(){m_ticketid = 1;} //constructor
|
||||
~TicketMgr(){} //destructor
|
||||
|
||||
// Object Holder
|
||||
@@ -69,8 +55,8 @@ class TicketMgr
|
||||
void DeleteAllRemovedGMTickets();
|
||||
void DeleteGMTicketPermanently(uint64 ticketGuid);
|
||||
void LoadGMTickets();
|
||||
void RemoveGMTicketByPlayer(uint64 playerGuid);
|
||||
void RemoveGMTicket(uint64 ticketGuid);
|
||||
void RemoveGMTicketByPlayer(uint64 playerGuid, uint64 GMguid);
|
||||
void RemoveGMTicket(uint64 ticketGuid, uint64 GMguid);
|
||||
void UpdateGMTicket(GM_Ticket *ticket);
|
||||
void SaveGMTicket(GM_Ticket* ticket);
|
||||
|
||||
|
||||
+35
-23
@@ -1150,13 +1150,14 @@ uint32 Unit::SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage
|
||||
{
|
||||
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID);
|
||||
SpellNonMeleeDamage damageInfo(this, pVictim, spellInfo->Id, spellInfo->SchoolMask);
|
||||
CalculateSpellDamage(&damageInfo, damage, spellInfo);
|
||||
damage = SpellDamageBonus(pVictim, spellInfo, damage, SPELL_DIRECT_DAMAGE);
|
||||
CalculateSpellDamageTaken(&damageInfo, damage, spellInfo);
|
||||
SendSpellNonMeleeDamageLog(&damageInfo);
|
||||
DealSpellDamage(&damageInfo, true);
|
||||
return damageInfo.damage;
|
||||
}
|
||||
|
||||
void Unit::CalculateSpellDamage(SpellNonMeleeDamage *damageInfo, int32 damage, SpellEntry const *spellInfo, WeaponAttackType attackType)
|
||||
void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 damage, SpellEntry const *spellInfo, WeaponAttackType attackType)
|
||||
{
|
||||
SpellSchoolMask damageSchoolMask = SpellSchoolMask(damageInfo->schoolMask);
|
||||
Unit *pVictim = damageInfo->target;
|
||||
@@ -1184,16 +1185,16 @@ void Unit::CalculateSpellDamage(SpellNonMeleeDamage *damageInfo, int32 damage, S
|
||||
if ( damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL )
|
||||
{
|
||||
//Calculate armor mitigation
|
||||
damage = CalcArmorReducedDamage(pVictim, damage);
|
||||
//damage = CalcArmorReducedDamage(pVictim, damage);
|
||||
// Get blocked status
|
||||
blocked = isSpellBlocked(pVictim, spellInfo, attackType);
|
||||
}
|
||||
// Magical Damage
|
||||
else
|
||||
/*else
|
||||
{
|
||||
// Calculate damage bonus
|
||||
damage = SpellDamageBonus(pVictim, spellInfo, damage, SPELL_DIRECT_DAMAGE);
|
||||
}
|
||||
}*/
|
||||
if (crit)
|
||||
{
|
||||
damageInfo->HitInfo|= SPELL_HIT_TYPE_CRIT;
|
||||
@@ -1239,7 +1240,7 @@ void Unit::CalculateSpellDamage(SpellNonMeleeDamage *damageInfo, int32 damage, S
|
||||
case SPELL_DAMAGE_CLASS_MAGIC:
|
||||
{
|
||||
// Calculate damage bonus
|
||||
damage = SpellDamageBonus(pVictim, spellInfo, damage, SPELL_DIRECT_DAMAGE);
|
||||
//damage = SpellDamageBonus(pVictim, spellInfo, damage, SPELL_DIRECT_DAMAGE);
|
||||
// If crit add critical bonus
|
||||
if (crit)
|
||||
{
|
||||
@@ -1253,6 +1254,9 @@ void Unit::CalculateSpellDamage(SpellNonMeleeDamage *damageInfo, int32 damage, S
|
||||
break;
|
||||
}
|
||||
|
||||
if( damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL )
|
||||
damage = CalcArmorReducedDamage(pVictim, damage);
|
||||
|
||||
// Calculate absorb resist
|
||||
if(damage > 0)
|
||||
{
|
||||
@@ -6713,7 +6717,6 @@ bool Unit::Attack(Unit *victim, bool meleeAttack)
|
||||
((WorldObject*)this)->SendMessageToSet(&data, true);
|
||||
|
||||
((Creature*)this)->CallAssistance();
|
||||
((Creature*)this)->SetHomePosition(GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
|
||||
}
|
||||
|
||||
// delay offhand weapon attack to next attack time
|
||||
@@ -7038,6 +7041,10 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
|
||||
if(!spellProto || !pVictim || damagetype==DIRECT_DAMAGE )
|
||||
return pdamage;
|
||||
|
||||
if(spellProto->SchoolMask == SPELL_SCHOOL_MASK_NORMAL)
|
||||
return pdamage;
|
||||
//damage = CalcArmorReducedDamage(pVictim, damage);
|
||||
|
||||
int32 BonusDamage = 0;
|
||||
if( GetTypeId()==TYPEID_UNIT )
|
||||
{
|
||||
@@ -8299,18 +8306,19 @@ void Unit::SetInCombatState(bool PvP)
|
||||
|
||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
|
||||
|
||||
if(isCharmed() || GetTypeId()!=TYPEID_PLAYER && ((Creature*)this)->isPet())
|
||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT);
|
||||
if(GetTypeId() != TYPEID_PLAYER)
|
||||
((Creature*)this)->SetHomePosition(GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
|
||||
|
||||
if(GetTypeId() == TYPEID_PLAYER && GetPetGUID())
|
||||
if(GetTypeId() != TYPEID_PLAYER && ((Creature*)this)->isPet())
|
||||
{
|
||||
if(Pet *pet = GetPet())
|
||||
{
|
||||
pet->UpdateSpeed(MOVE_RUN, true);
|
||||
pet->UpdateSpeed(MOVE_SWIM, true);
|
||||
pet->UpdateSpeed(MOVE_FLIGHT, true);
|
||||
}
|
||||
UpdateSpeed(MOVE_RUN, true);
|
||||
UpdateSpeed(MOVE_SWIM, true);
|
||||
UpdateSpeed(MOVE_FLIGHT, true);
|
||||
}
|
||||
else if(!isCharmed())
|
||||
return;
|
||||
|
||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT);
|
||||
}
|
||||
|
||||
void Unit::ClearInCombat()
|
||||
@@ -8318,19 +8326,22 @@ void Unit::ClearInCombat()
|
||||
m_CombatTimer = 0;
|
||||
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
|
||||
|
||||
if(isCharmed() || GetTypeId()!=TYPEID_PLAYER && ((Creature*)this)->isPet())
|
||||
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT);
|
||||
|
||||
// Player's state will be cleared in Player::UpdateContestedPvP
|
||||
if(GetTypeId()!=TYPEID_PLAYER)
|
||||
clearUnitState(UNIT_STAT_ATTACK_PLAYER);
|
||||
|
||||
if(GetTypeId() == TYPEID_PLAYER && GetPetGUID())
|
||||
if(GetTypeId() != TYPEID_PLAYER && ((Creature*)this)->isPet())
|
||||
{
|
||||
if(Pet *pet = GetPet())
|
||||
if(Unit *owner = GetOwner())
|
||||
{
|
||||
for(int i = 0; i < MAX_MOVE_TYPE; ++i)
|
||||
pet->SetSpeed(UnitMoveType(i), m_speed_rate[i], true);
|
||||
SetSpeed(UnitMoveType(i), owner->GetSpeedRate(UnitMoveType(i)), true);
|
||||
}
|
||||
}
|
||||
else if(!isCharmed())
|
||||
return;
|
||||
|
||||
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT);
|
||||
}
|
||||
|
||||
//TODO: remove this function
|
||||
@@ -10086,7 +10097,8 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
|
||||
{
|
||||
sLog.outDebug("ProcDamageAndSpell: doing %u damage from spell id %u (triggered by %s aura of spell %u)", auraModifier->m_amount, spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
|
||||
SpellNonMeleeDamage damageInfo(this, pTarget, spellInfo->Id, spellInfo->SchoolMask);
|
||||
CalculateSpellDamage(&damageInfo, auraModifier->m_amount, spellInfo);
|
||||
uint32 damage = SpellDamageBonus(pTarget, spellInfo, auraModifier->m_amount, SPELL_DIRECT_DAMAGE);
|
||||
CalculateSpellDamageTaken(&damageInfo, damage, spellInfo);
|
||||
SendSpellNonMeleeDamageLog(&damageInfo);
|
||||
DealSpellDamage(&damageInfo, true);
|
||||
break;
|
||||
|
||||
+1
-1
@@ -951,7 +951,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
|
||||
void CalculateMeleeDamage(Unit *pVictim, uint32 damage, CalcDamageInfo *damageInfo, WeaponAttackType attackType = BASE_ATTACK);
|
||||
void DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss);
|
||||
|
||||
void CalculateSpellDamage(SpellNonMeleeDamage *damageInfo, int32 damage, SpellEntry const *spellInfo, WeaponAttackType attackType = BASE_ATTACK);
|
||||
void CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 damage, SpellEntry const *spellInfo, WeaponAttackType attackType = BASE_ATTACK);
|
||||
void DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss);
|
||||
|
||||
float MeleeSpellMissChance(const Unit *pVictim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const;
|
||||
|
||||
+16
-16
@@ -267,7 +267,7 @@ World::AddSession_ (WorldSession* s)
|
||||
float popu = GetActiveSessionCount (); //updated number of users on the server
|
||||
popu /= pLimit;
|
||||
popu *= 2;
|
||||
loginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID);
|
||||
LoginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID);
|
||||
sLog.outDetail ("Server Population (%f).", popu);
|
||||
}
|
||||
}
|
||||
@@ -1085,7 +1085,7 @@ void World::SetInitialWorldSettings()
|
||||
// not send custom type REALM_FFA_PVP to realm list
|
||||
uint32 server_type = IsFFAPvPRealm() ? REALM_TYPE_PVP : getConfig(CONFIG_GAME_TYPE);
|
||||
uint32 realm_zone = getConfig(CONFIG_REALM_ZONE);
|
||||
loginDatabase.PExecute("UPDATE realmlist SET icon = %u, timezone = %u WHERE id = '%d'", server_type, realm_zone, realmID);
|
||||
LoginDatabase.PExecute("UPDATE realmlist SET icon = %u, timezone = %u WHERE id = '%d'", server_type, realm_zone, realmID);
|
||||
|
||||
///- Remove the bones after a restart
|
||||
CharacterDatabase.PExecute("DELETE FROM corpse WHERE corpse_type = '0'");
|
||||
@@ -1404,7 +1404,7 @@ void World::SetInitialWorldSettings()
|
||||
objmgr.LoadTransportEvents();
|
||||
|
||||
sLog.outString("Deleting expired bans..." );
|
||||
loginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||
LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||
|
||||
sLog.outString("Calculate next daily quest reset time..." );
|
||||
InitDailyQuestResetTime();
|
||||
@@ -2649,10 +2649,10 @@ bool World::KickPlayer(const std::string& playerName)
|
||||
/// Ban an account or ban an IP address, duration will be parsed using TimeStringToSecs if it is positive, otherwise permban
|
||||
BanReturn World::BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author)
|
||||
{
|
||||
loginDatabase.escape_string(nameOrIP);
|
||||
loginDatabase.escape_string(reason);
|
||||
LoginDatabase.escape_string(nameOrIP);
|
||||
LoginDatabase.escape_string(reason);
|
||||
std::string safe_author=author;
|
||||
loginDatabase.escape_string(safe_author);
|
||||
LoginDatabase.escape_string(safe_author);
|
||||
|
||||
uint32 duration_secs = TimeStringToSecs(duration);
|
||||
QueryResult *resultAccounts = NULL; //used for kicking
|
||||
@@ -2662,12 +2662,12 @@ BanReturn World::BanAccount(BanMode mode, std::string nameOrIP, std::string dura
|
||||
{
|
||||
case BAN_IP:
|
||||
//No SQL injection as strings are escaped
|
||||
resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE last_ip = '%s'",nameOrIP.c_str());
|
||||
loginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+%u,'%s','%s')",nameOrIP.c_str(),duration_secs,safe_author.c_str(),reason.c_str());
|
||||
resultAccounts = LoginDatabase.PQuery("SELECT id FROM account WHERE last_ip = '%s'",nameOrIP.c_str());
|
||||
LoginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+%u,'%s','%s')",nameOrIP.c_str(),duration_secs,safe_author.c_str(),reason.c_str());
|
||||
break;
|
||||
case BAN_ACCOUNT:
|
||||
//No SQL injection as string is escaped
|
||||
resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'",nameOrIP.c_str());
|
||||
resultAccounts = LoginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'",nameOrIP.c_str());
|
||||
break;
|
||||
case BAN_CHARACTER:
|
||||
//No SQL injection as string is escaped
|
||||
@@ -2694,7 +2694,7 @@ BanReturn World::BanAccount(BanMode mode, std::string nameOrIP, std::string dura
|
||||
if(mode!=BAN_IP)
|
||||
{
|
||||
//No SQL injection as strings are escaped
|
||||
loginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+%u, '%s', '%s', '1')",
|
||||
LoginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+%u, '%s', '%s', '1')",
|
||||
account,duration_secs,safe_author.c_str(),reason.c_str());
|
||||
}
|
||||
|
||||
@@ -2713,8 +2713,8 @@ bool World::RemoveBanAccount(BanMode mode, std::string nameOrIP)
|
||||
{
|
||||
if (mode == BAN_IP)
|
||||
{
|
||||
loginDatabase.escape_string(nameOrIP);
|
||||
loginDatabase.PExecute("DELETE FROM ip_banned WHERE ip = '%s'",nameOrIP.c_str());
|
||||
LoginDatabase.escape_string(nameOrIP);
|
||||
LoginDatabase.PExecute("DELETE FROM ip_banned WHERE ip = '%s'",nameOrIP.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2728,7 +2728,7 @@ bool World::RemoveBanAccount(BanMode mode, std::string nameOrIP)
|
||||
return false;
|
||||
|
||||
//NO SQL injection as account is uint32
|
||||
loginDatabase.PExecute("UPDATE account_banned SET active = '0' WHERE id = '%u'",account);
|
||||
LoginDatabase.PExecute("UPDATE account_banned SET active = '0' WHERE id = '%u'",account);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -2925,8 +2925,8 @@ void World::_UpdateRealmCharCount(QueryResult *resultCharCount, uint32 accountId
|
||||
Field *fields = resultCharCount->Fetch();
|
||||
uint32 charCount = fields[0].GetUInt32();
|
||||
delete resultCharCount;
|
||||
loginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", accountId, realmID);
|
||||
loginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charCount, accountId, realmID);
|
||||
LoginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", accountId, realmID);
|
||||
LoginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charCount, accountId, realmID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2989,7 +2989,7 @@ void World::SetPlayerLimit( int32 limit, bool needUpdate )
|
||||
m_playerLimit = limit;
|
||||
|
||||
if(db_update_need)
|
||||
loginDatabase.PExecute("UPDATE realmlist SET allowedSecurityLevel = '%u' WHERE id = '%d'",uint8(GetPlayerSecurityLimit()),realmID);
|
||||
LoginDatabase.PExecute("UPDATE realmlist SET allowedSecurityLevel = '%u' WHERE id = '%d'",uint8(GetPlayerSecurityLimit()),realmID);
|
||||
}
|
||||
|
||||
void World::UpdateMaxSessionCounters()
|
||||
|
||||
@@ -328,7 +328,7 @@ void WorldSession::LogoutPlayer(bool Save)
|
||||
///- Reset the online field in the account table
|
||||
// no point resetting online in character table here as Player::SaveToDB() will set it to 1 since player has not been removed from world at this stage
|
||||
//No SQL injection as AccountID is uint32
|
||||
loginDatabase.PExecute("UPDATE account SET online = 0 WHERE id = '%u'", GetAccountId());
|
||||
LoginDatabase.PExecute("UPDATE account SET online = 0 WHERE id = '%u'", GetAccountId());
|
||||
|
||||
///- If the player is in a guild, update the guild roster and broadcast a logout message to other guild members
|
||||
Guild *guild = objmgr.GetGuildById(_player->GetGuildId());
|
||||
|
||||
@@ -720,11 +720,11 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
|
||||
|
||||
// Get the account information from the realmd database
|
||||
std::string safe_account = account; // Duplicate, else will screw the SHA hash verification below
|
||||
loginDatabase.escape_string (safe_account);
|
||||
LoginDatabase.escape_string (safe_account);
|
||||
// No SQL injection, username escaped.
|
||||
|
||||
QueryResult *result =
|
||||
loginDatabase.PQuery ("SELECT "
|
||||
LoginDatabase.PQuery ("SELECT "
|
||||
"id, " //0
|
||||
"gmlevel, " //1
|
||||
"sessionkey, " //2
|
||||
@@ -789,7 +789,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
|
||||
vold,
|
||||
vStr);
|
||||
|
||||
loginDatabase.PExecute ("UPDATE account "
|
||||
LoginDatabase.PExecute ("UPDATE account "
|
||||
"SET "
|
||||
"v = '0', "
|
||||
"s = '0' "
|
||||
@@ -841,7 +841,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
|
||||
|
||||
// Re-check account ban (same check as in realmd)
|
||||
QueryResult *banresult =
|
||||
loginDatabase.PQuery ("SELECT "
|
||||
LoginDatabase.PQuery ("SELECT "
|
||||
"bandate, "
|
||||
"unbandate "
|
||||
"FROM account_banned "
|
||||
@@ -907,9 +907,9 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
|
||||
|
||||
// Update the last_ip in the database
|
||||
// No SQL injection, username escaped.
|
||||
loginDatabase.escape_string (address);
|
||||
LoginDatabase.escape_string (address);
|
||||
|
||||
loginDatabase.PExecute ("UPDATE account "
|
||||
LoginDatabase.PExecute ("UPDATE account "
|
||||
"SET last_ip = '%s' "
|
||||
"WHERE username = '%s'",
|
||||
address.c_str (),
|
||||
|
||||
@@ -53,6 +53,6 @@ typedef DatabaseMysql DatabaseType;
|
||||
|
||||
extern DatabaseType WorldDatabase;
|
||||
extern DatabaseType CharacterDatabase;
|
||||
extern DatabaseType loginDatabase;
|
||||
extern DatabaseType LoginDatabase;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -194,7 +194,7 @@ bool ChatHandler::HandleAccountOnlineListCommand(const char* args)
|
||||
///- 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);
|
||||
QueryResult *resultLogin = LoginDatabase.PQuery("SELECT username, last_ip, gmlevel, expansion FROM account WHERE id = '%u'",account);
|
||||
|
||||
if(resultLogin)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* 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 Trinity Daemon
|
||||
/// @{
|
||||
/// \file
|
||||
|
||||
#include "Common.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
#include "Config/ConfigEnv.h"
|
||||
#include "Log.h"
|
||||
#include "Master.h"
|
||||
|
||||
#ifndef _TRINITY_CORE_CONFIG
|
||||
# define _TRINITY_CORE_CONFIG "trinitycore.conf"
|
||||
#endif //_TRINITY_CORE_CONFIG
|
||||
|
||||
// Format is YYYYMMDDRR where RR is the change in the conf file
|
||||
// for that day.
|
||||
#ifndef _TRINITY_CORE_CONFVER
|
||||
# define _TRINITY_CORE_CONFVER 2008022901
|
||||
#endif //_TRINITY_CORE_CONFVER
|
||||
|
||||
#ifdef WIN32
|
||||
#include "ServiceWin32.h"
|
||||
char serviceName[] = "Trinityd";
|
||||
char serviceLongName[] = "Trinity core service";
|
||||
char serviceDescription[] = "Massive Network Game Object Server";
|
||||
/*
|
||||
* -1 - not in service mode
|
||||
* 0 - stopped
|
||||
* 1 - running
|
||||
* 2 - paused
|
||||
*/
|
||||
int m_ServiceStatus = -1;
|
||||
#endif
|
||||
|
||||
DatabaseType WorldDatabase; ///< Accessor to the world database
|
||||
DatabaseType CharacterDatabase; ///< Accessor to the character database
|
||||
DatabaseType LoginDatabase; ///< Accessor to the realm/login database
|
||||
|
||||
uint32 realmID; ///< Id of the realm
|
||||
|
||||
/// Print out the usage string for this program on the console.
|
||||
void usage(const char *prog)
|
||||
{
|
||||
sLog.outString("Usage: \n %s [<options>]\n"
|
||||
" -c config_file use config_file as configuration file\n\r"
|
||||
#ifdef WIN32
|
||||
" Running as service functions:\n\r"
|
||||
" --service run as service\n\r"
|
||||
" -s install install service\n\r"
|
||||
" -s uninstall uninstall service\n\r"
|
||||
#endif
|
||||
,prog);
|
||||
}
|
||||
|
||||
/// Launch the Trinity server
|
||||
extern int main(int argc, char **argv)
|
||||
{
|
||||
///- Command line parsing to get the configuration file name
|
||||
char const* cfg_file = _TRINITY_CORE_CONFIG;
|
||||
int c=1;
|
||||
while( c < argc )
|
||||
{
|
||||
if( strcmp(argv[c],"-c") == 0)
|
||||
{
|
||||
if( ++c >= argc )
|
||||
{
|
||||
sLog.outError("Runtime-Error: -c option requires an input argument");
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
cfg_file = argv[c];
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
////////////
|
||||
//Services//
|
||||
////////////
|
||||
if( strcmp(argv[c],"-s") == 0)
|
||||
{
|
||||
if( ++c >= argc )
|
||||
{
|
||||
sLog.outError("Runtime-Error: -s option requires an input argument");
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
if( strcmp(argv[c],"install") == 0)
|
||||
{
|
||||
if (WinServiceInstall())
|
||||
sLog.outString("Installing service");
|
||||
return 1;
|
||||
}
|
||||
else if( strcmp(argv[c],"uninstall") == 0)
|
||||
{
|
||||
if(WinServiceUninstall())
|
||||
sLog.outString("Uninstalling service");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog.outError("Runtime-Error: unsupported option %s",argv[c]);
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if( strcmp(argv[c],"--service") == 0)
|
||||
{
|
||||
WinServiceRun();
|
||||
}
|
||||
////
|
||||
#endif
|
||||
++c;
|
||||
}
|
||||
|
||||
if (!sConfig.SetSource(cfg_file))
|
||||
{
|
||||
sLog.outError("Could not find configuration file %s.", cfg_file);
|
||||
return 1;
|
||||
}
|
||||
sLog.outString("Using configuration file %s.", cfg_file);
|
||||
|
||||
uint32 confVersion = sConfig.GetIntDefault("ConfVersion", 0);
|
||||
if (confVersion < _TRINITY_CORE_CONFVER)
|
||||
{
|
||||
sLog.outError("*****************************************************************************");
|
||||
sLog.outError(" WARNING: Your trinitycore.conf version indicates your conf file is out of date!");
|
||||
sLog.outError(" Please check for updates, as your current default values may cause");
|
||||
sLog.outError(" strange behavior.");
|
||||
sLog.outError("*****************************************************************************");
|
||||
clock_t pause = 3000 + clock();
|
||||
|
||||
while (pause > clock()) {}
|
||||
}
|
||||
|
||||
///- and run the 'Master'
|
||||
/// \todo Why do we need this 'Master'? Can't all of this be in the Main as for Realmd?
|
||||
return sMaster.Run();
|
||||
|
||||
// at sMaster return function exist with codes
|
||||
// 0 - normal shutdown
|
||||
// 1 - shutdown at error
|
||||
// 2 - restart command used, this code can be used by restarter for restart Trinityd
|
||||
}
|
||||
|
||||
/// @}
|
||||
@@ -0,0 +1,517 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/** \file
|
||||
\ingroup Trinityd
|
||||
*/
|
||||
|
||||
#include <ace/OS_NS_signal.h>
|
||||
|
||||
#include "WorldSocketMgr.h"
|
||||
#include "Common.h"
|
||||
#include "Master.h"
|
||||
#include "WorldSocket.h"
|
||||
#include "WorldRunnable.h"
|
||||
#include "World.h"
|
||||
#include "Log.h"
|
||||
#include "Timer.h"
|
||||
#include "Policies/SingletonImp.h"
|
||||
#include "SystemConfig.h"
|
||||
#include "Config/ConfigEnv.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
#include "CliRunnable.h"
|
||||
#include "RASocket.h"
|
||||
#include "ScriptCalls.h"
|
||||
#include "Util.h"
|
||||
|
||||
#include "sockets/TcpSocket.h"
|
||||
#include "sockets/Utility.h"
|
||||
#include "sockets/Parse.h"
|
||||
#include "sockets/Socket.h"
|
||||
#include "sockets/SocketHandler.h"
|
||||
#include "sockets/ListenSocket.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include "ServiceWin32.h"
|
||||
extern int m_ServiceStatus;
|
||||
#endif
|
||||
|
||||
/// \todo Warning disabling not useful under VC++2005. Can somebody say on which compiler it is useful?
|
||||
#pragma warning(disable:4305)
|
||||
|
||||
INSTANTIATE_SINGLETON_1( Master );
|
||||
|
||||
volatile uint32 Master::m_masterLoopCounter = 0;
|
||||
|
||||
class FreezeDetectorRunnable : public ZThread::Runnable
|
||||
{
|
||||
public:
|
||||
FreezeDetectorRunnable() { _delaytime = 0; }
|
||||
uint32 m_loops, m_lastchange;
|
||||
uint32 w_loops, w_lastchange;
|
||||
uint32 _delaytime;
|
||||
void SetDelayTime(uint32 t) { _delaytime = t; }
|
||||
void run(void)
|
||||
{
|
||||
if(!_delaytime)
|
||||
return;
|
||||
sLog.outString("Starting up anti-freeze thread (%u seconds max stuck time)...",_delaytime/1000);
|
||||
m_loops = 0;
|
||||
w_loops = 0;
|
||||
m_lastchange = 0;
|
||||
w_lastchange = 0;
|
||||
while(!World::IsStopped())
|
||||
{
|
||||
ZThread::Thread::sleep(1000);
|
||||
uint32 curtime = getMSTime();
|
||||
//DEBUG_LOG("anti-freeze: time=%u, counters=[%u; %u]",curtime,Master::m_masterLoopCounter,World::m_worldLoopCounter);
|
||||
|
||||
// There is no Master anymore
|
||||
// TODO: clear the rest of the code
|
||||
// // normal work
|
||||
// if(m_loops != Master::m_masterLoopCounter)
|
||||
// {
|
||||
// m_lastchange = curtime;
|
||||
// m_loops = Master::m_masterLoopCounter;
|
||||
// }
|
||||
// // possible freeze
|
||||
// else if(getMSTimeDiff(m_lastchange,curtime) > _delaytime)
|
||||
// {
|
||||
// sLog.outError("Main/Sockets Thread hangs, kicking out server!");
|
||||
// *((uint32 volatile*)NULL) = 0; // bang crash
|
||||
// }
|
||||
|
||||
// normal work
|
||||
if(w_loops != World::m_worldLoopCounter)
|
||||
{
|
||||
w_lastchange = curtime;
|
||||
w_loops = World::m_worldLoopCounter;
|
||||
}
|
||||
// possible freeze
|
||||
else if(getMSTimeDiff(w_lastchange,curtime) > _delaytime)
|
||||
{
|
||||
sLog.outError("World Thread hangs, kicking out server!");
|
||||
*((uint32 volatile*)NULL) = 0; // bang crash
|
||||
}
|
||||
}
|
||||
sLog.outString("Anti-freeze thread exiting without problems.");
|
||||
}
|
||||
};
|
||||
|
||||
class RARunnable : public ZThread::Runnable
|
||||
{
|
||||
public:
|
||||
uint32 numLoops, loopCounter;
|
||||
|
||||
RARunnable ()
|
||||
{
|
||||
uint32 socketSelecttime = sWorld.getConfig (CONFIG_SOCKET_SELECTTIME);
|
||||
numLoops = (sConfig.GetIntDefault ("MaxPingTime", 30) * (MINUTE * 1000000 / socketSelecttime));
|
||||
loopCounter = 0;
|
||||
}
|
||||
|
||||
void
|
||||
checkping ()
|
||||
{
|
||||
// ping if need
|
||||
if ((++loopCounter) == numLoops)
|
||||
{
|
||||
loopCounter = 0;
|
||||
sLog.outDetail ("Ping MySQL to keep connection alive");
|
||||
delete WorldDatabase.Query ("SELECT 1 FROM command LIMIT 1");
|
||||
delete LoginDatabase.Query ("SELECT 1 FROM realmlist LIMIT 1");
|
||||
delete CharacterDatabase.Query ("SELECT 1 FROM bugreport LIMIT 1");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run (void)
|
||||
{
|
||||
SocketHandler h;
|
||||
|
||||
// Launch the RA listener socket
|
||||
ListenSocket<RASocket> RAListenSocket (h);
|
||||
bool usera = sConfig.GetBoolDefault ("Ra.Enable", false);
|
||||
|
||||
if (usera)
|
||||
{
|
||||
port_t raport = sConfig.GetIntDefault ("Ra.Port", 3443);
|
||||
std::string stringip = sConfig.GetStringDefault ("Ra.IP", "0.0.0.0");
|
||||
ipaddr_t raip;
|
||||
if (!Utility::u2ip (stringip, raip))
|
||||
sLog.outError ("Trinity RA can not bind to ip %s", stringip.c_str ());
|
||||
else if (RAListenSocket.Bind (raip, raport))
|
||||
sLog.outError ("Trinity RA can not bind to port %d on %s", raport, stringip.c_str ());
|
||||
else
|
||||
{
|
||||
h.Add (&RAListenSocket);
|
||||
|
||||
sLog.outString ("Starting Remote access listner on port %d on %s", raport, stringip.c_str ());
|
||||
}
|
||||
}
|
||||
|
||||
// Socket Selet time is in microseconds , not miliseconds!!
|
||||
uint32 socketSelecttime = sWorld.getConfig (CONFIG_SOCKET_SELECTTIME);
|
||||
|
||||
// if use ra spend time waiting for io, if not use ra ,just sleep
|
||||
if (usera)
|
||||
while (!World::IsStopped())
|
||||
{
|
||||
h.Select (0, socketSelecttime);
|
||||
checkping ();
|
||||
}
|
||||
else
|
||||
while (!World::IsStopped())
|
||||
{
|
||||
ZThread::Thread::sleep (static_cast<unsigned long> (socketSelecttime / 1000));
|
||||
checkping ();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Master::Master()
|
||||
{
|
||||
}
|
||||
|
||||
Master::~Master()
|
||||
{
|
||||
}
|
||||
|
||||
/// Main function
|
||||
int Master::Run()
|
||||
{
|
||||
sLog.outString( "%s (core-daemon)", _FULLVERSION );
|
||||
sLog.outString( "<Ctrl-C> to stop.\n" );
|
||||
|
||||
sLog.outTitle( " ______ __");
|
||||
sLog.outTitle( "/\\__ _\\ __ __/\\ \\__");
|
||||
sLog.outTitle( "\\/_/\\ \\/ _ __ /\\_\\ ___ /\\_\\ \\ ,_\\ __ __");
|
||||
sLog.outTitle( " \\ \\ \\/\\`'__\\/\\ \\ /' _ `\\/\\ \\ \\ \\/ /\\ \\/\\ \\");
|
||||
sLog.outTitle( " \\ \\ \\ \\ \\/ \\ \\ \\/\\ \\/\\ \\ \\ \\ \\ \\_\\ \\ \\_\\ \\");
|
||||
sLog.outTitle( " \\ \\_\\ \\_\\ \\ \\_\\ \\_\\ \\_\\ \\_\\ \\__\\\\/`____ \\");
|
||||
sLog.outTitle( " \\/_/\\/_/ \\/_/\\/_/\\/_/\\/_/\\/__/ `/___/> \\");
|
||||
sLog.outTitle( " C O R E /\\___/");
|
||||
sLog.outTitle( "http://TrinityCore.org \\/__/\n");
|
||||
|
||||
/// worldd PID file creation
|
||||
std::string pidfile = sConfig.GetStringDefault("PidFile", "");
|
||||
if(!pidfile.empty())
|
||||
{
|
||||
uint32 pid = CreatePIDFile(pidfile);
|
||||
if( !pid )
|
||||
{
|
||||
sLog.outError( "Cannot create PID file %s.\n", pidfile.c_str() );
|
||||
return 1;
|
||||
}
|
||||
|
||||
sLog.outString( "Daemon PID: %u\n", pid );
|
||||
}
|
||||
|
||||
///- Start the databases
|
||||
if (!_StartDB())
|
||||
return 1;
|
||||
|
||||
///- Initialize the World
|
||||
sWorld.SetInitialWorldSettings();
|
||||
|
||||
///- Catch termination signals
|
||||
_HookSignals();
|
||||
|
||||
///- Launch WorldRunnable thread
|
||||
ZThread::Thread t(new WorldRunnable);
|
||||
t.setPriority ((ZThread::Priority )2);
|
||||
|
||||
// set server online
|
||||
LoginDatabase.PExecute("UPDATE realmlist SET color = 0, population = 0 WHERE id = '%d'",realmID);
|
||||
|
||||
#ifdef WIN32
|
||||
if (sConfig.GetBoolDefault("Console.Enable", true) && (m_ServiceStatus == -1)/* need disable console in service mode*/)
|
||||
#else
|
||||
if (sConfig.GetBoolDefault("Console.Enable", true))
|
||||
#endif
|
||||
{
|
||||
///- Launch CliRunnable thread
|
||||
ZThread::Thread td1(new CliRunnable);
|
||||
}
|
||||
|
||||
ZThread::Thread td2(new RARunnable);
|
||||
|
||||
///- Handle affinity for multiple processors and process priority on Windows
|
||||
#ifdef WIN32
|
||||
{
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
|
||||
uint32 Aff = sConfig.GetIntDefault("UseProcessors", 0);
|
||||
if(Aff > 0)
|
||||
{
|
||||
ULONG_PTR appAff;
|
||||
ULONG_PTR sysAff;
|
||||
|
||||
if(GetProcessAffinityMask(hProcess,&appAff,&sysAff))
|
||||
{
|
||||
ULONG_PTR curAff = Aff & appAff; // remove non accessible processors
|
||||
|
||||
if(!curAff )
|
||||
{
|
||||
sLog.outError("Processors marked in UseProcessors bitmask (hex) %x not accessible for Trinityd. Accessible processors bitmask (hex): %x",Aff,appAff);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(SetProcessAffinityMask(hProcess,curAff))
|
||||
sLog.outString("Using processors (bitmask, hex): %x", curAff);
|
||||
else
|
||||
sLog.outError("Can't set used processors (hex): %x",curAff);
|
||||
}
|
||||
}
|
||||
sLog.outString();
|
||||
}
|
||||
|
||||
bool Prio = sConfig.GetBoolDefault("ProcessPriority", false);
|
||||
|
||||
// if(Prio && (m_ServiceStatus == -1)/* need set to default process priority class in service mode*/)
|
||||
if(Prio)
|
||||
{
|
||||
if(SetPriorityClass(hProcess,HIGH_PRIORITY_CLASS))
|
||||
sLog.outString("TrinityCore process priority class set to HIGH");
|
||||
else
|
||||
sLog.outError("ERROR: Can't set Trinityd process priority class.");
|
||||
sLog.outString();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32 realCurrTime, realPrevTime;
|
||||
realCurrTime = realPrevTime = getMSTime();
|
||||
|
||||
uint32 socketSelecttime = sWorld.getConfig(CONFIG_SOCKET_SELECTTIME);
|
||||
|
||||
// maximum counter for next ping
|
||||
uint32 numLoops = (sConfig.GetIntDefault( "MaxPingTime", 30 ) * (MINUTE * 1000000 / socketSelecttime));
|
||||
uint32 loopCounter = 0;
|
||||
|
||||
///- Start up freeze catcher thread
|
||||
uint32 freeze_delay = sConfig.GetIntDefault("MaxCoreStuckTime", 0);
|
||||
if(freeze_delay)
|
||||
{
|
||||
FreezeDetectorRunnable *fdr = new FreezeDetectorRunnable();
|
||||
fdr->SetDelayTime(freeze_delay*1000);
|
||||
ZThread::Thread t(fdr);
|
||||
t.setPriority(ZThread::High);
|
||||
}
|
||||
|
||||
///- Launch the world listener socket
|
||||
port_t wsport = sWorld.getConfig (CONFIG_PORT_WORLD);
|
||||
std::string bind_ip = sConfig.GetStringDefault ("BindIP", "0.0.0.0");
|
||||
|
||||
if (sWorldSocketMgr->StartNetwork (wsport, bind_ip.c_str ()) == -1)
|
||||
{
|
||||
sLog.outError ("Failed to start network");
|
||||
World::StopNow(ERROR_EXIT_CODE);
|
||||
// go down and shutdown the server
|
||||
}
|
||||
|
||||
sWorldSocketMgr->Wait ();
|
||||
|
||||
// set server offline
|
||||
LoginDatabase.PExecute("UPDATE realmlist SET color = 2 WHERE id = '%d'",realmID);
|
||||
|
||||
///- Remove signal handling before leaving
|
||||
_UnhookSignals();
|
||||
|
||||
// when the main thread closes the singletons get unloaded
|
||||
// since worldrunnable uses them, it will crash if unloaded after master
|
||||
t.wait();
|
||||
td2.wait ();
|
||||
|
||||
///- Clean database before leaving
|
||||
clearOnlineAccounts();
|
||||
|
||||
///- Wait for delay threads to end
|
||||
CharacterDatabase.HaltDelayThread();
|
||||
WorldDatabase.HaltDelayThread();
|
||||
LoginDatabase.HaltDelayThread();
|
||||
|
||||
sLog.outString( "Halting process..." );
|
||||
|
||||
#ifdef WIN32
|
||||
if (sConfig.GetBoolDefault("Console.Enable", true))
|
||||
{
|
||||
// this only way to terminate CLI thread exist at Win32 (alt. way exist only in Windows Vista API)
|
||||
//_exit(1);
|
||||
// send keyboard input to safely unblock the CLI thread
|
||||
INPUT_RECORD b[5];
|
||||
HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
|
||||
b[0].EventType = KEY_EVENT;
|
||||
b[0].Event.KeyEvent.bKeyDown = TRUE;
|
||||
b[0].Event.KeyEvent.uChar.AsciiChar = 'X';
|
||||
b[0].Event.KeyEvent.wVirtualKeyCode = 'X';
|
||||
b[0].Event.KeyEvent.wRepeatCount = 1;
|
||||
|
||||
b[1].EventType = KEY_EVENT;
|
||||
b[1].Event.KeyEvent.bKeyDown = FALSE;
|
||||
b[1].Event.KeyEvent.uChar.AsciiChar = 'X';
|
||||
b[1].Event.KeyEvent.wVirtualKeyCode = 'X';
|
||||
b[1].Event.KeyEvent.wRepeatCount = 1;
|
||||
|
||||
b[2].EventType = KEY_EVENT;
|
||||
b[2].Event.KeyEvent.bKeyDown = TRUE;
|
||||
b[2].Event.KeyEvent.dwControlKeyState = 0;
|
||||
b[2].Event.KeyEvent.uChar.AsciiChar = '\r';
|
||||
b[2].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
|
||||
b[2].Event.KeyEvent.wRepeatCount = 1;
|
||||
b[2].Event.KeyEvent.wVirtualScanCode = 0x1c;
|
||||
|
||||
b[3].EventType = KEY_EVENT;
|
||||
b[3].Event.KeyEvent.bKeyDown = FALSE;
|
||||
b[3].Event.KeyEvent.dwControlKeyState = 0;
|
||||
b[3].Event.KeyEvent.uChar.AsciiChar = '\r';
|
||||
b[3].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
|
||||
b[3].Event.KeyEvent.wVirtualScanCode = 0x1c;
|
||||
b[3].Event.KeyEvent.wRepeatCount = 1;
|
||||
DWORD numb;
|
||||
BOOL ret = WriteConsoleInput(hStdIn, b, 4, &numb);
|
||||
}
|
||||
#endif
|
||||
|
||||
// for some unknown reason, unloading scripts here and not in worldrunnable
|
||||
// fixes a memory leak related to detaching threads from the module
|
||||
UnloadScriptingModule();
|
||||
|
||||
// Exit the process with specified return value
|
||||
return World::GetExitCode();
|
||||
}
|
||||
|
||||
/// Initialize connection to the databases
|
||||
bool Master::_StartDB()
|
||||
{
|
||||
///- Get world database info from configuration file
|
||||
std::string dbstring;
|
||||
if(!sConfig.GetString("WorldDatabaseInfo", &dbstring))
|
||||
{
|
||||
sLog.outError("Database not specified in configuration file");
|
||||
return false;
|
||||
}
|
||||
sLog.outString("World Database: %s", dbstring.c_str());
|
||||
|
||||
///- Initialise the world database
|
||||
if(!WorldDatabase.Initialize(dbstring.c_str()))
|
||||
{
|
||||
sLog.outError("Cannot connect to world database %s",dbstring.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!sConfig.GetString("CharacterDatabaseInfo", &dbstring))
|
||||
{
|
||||
sLog.outError("Character Database not specified in configuration file");
|
||||
return false;
|
||||
}
|
||||
sLog.outString("Character Database: %s", dbstring.c_str());
|
||||
|
||||
///- Initialise the Character database
|
||||
if(!CharacterDatabase.Initialize(dbstring.c_str()))
|
||||
{
|
||||
sLog.outError("Cannot connect to Character database %s",dbstring.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
///- Get login database info from configuration file
|
||||
if(!sConfig.GetString("LoginDatabaseInfo", &dbstring))
|
||||
{
|
||||
sLog.outError("Login database not specified in configuration file");
|
||||
return false;
|
||||
}
|
||||
|
||||
///- Initialise the login database
|
||||
sLog.outString("Login Database: %s", dbstring.c_str() );
|
||||
if(!LoginDatabase.Initialize(dbstring.c_str()))
|
||||
{
|
||||
sLog.outError("Cannot connect to login database %s",dbstring.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
///- Get the realm Id from the configuration file
|
||||
realmID = sConfig.GetIntDefault("RealmID", 0);
|
||||
if(!realmID)
|
||||
{
|
||||
sLog.outError("Realm ID not defined in configuration file");
|
||||
return false;
|
||||
}
|
||||
sLog.outString("Realm running as realm ID %d", realmID);
|
||||
|
||||
///- Clean the database before starting
|
||||
clearOnlineAccounts();
|
||||
|
||||
sWorld.LoadDBVersion();
|
||||
|
||||
sLog.outString("Using %s", sWorld.GetDBVersion());
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Clear 'online' status for all accounts with characters in this realm
|
||||
void Master::clearOnlineAccounts()
|
||||
{
|
||||
// Cleanup online status for characters hosted at current realm
|
||||
/// \todo Only accounts with characters logged on *this* realm should have online status reset. Move the online column from 'account' to 'realmcharacters'?
|
||||
LoginDatabase.PExecute(
|
||||
"UPDATE account SET online = 0 WHERE online > 0 "
|
||||
"AND id IN (SELECT acctid FROM realmcharacters WHERE realmid = '%d')",realmID);
|
||||
|
||||
|
||||
CharacterDatabase.Execute("UPDATE characters SET online = 0 WHERE online<>0");
|
||||
}
|
||||
|
||||
/// Handle termination signals
|
||||
void Master::_OnSignal(int s)
|
||||
{
|
||||
switch (s)
|
||||
{
|
||||
case SIGINT:
|
||||
World::StopNow(RESTART_EXIT_CODE);
|
||||
break;
|
||||
case SIGTERM:
|
||||
#ifdef _WIN32
|
||||
case SIGBREAK:
|
||||
#endif
|
||||
World::StopNow(SHUTDOWN_EXIT_CODE);
|
||||
break;
|
||||
}
|
||||
|
||||
signal(s, _OnSignal);
|
||||
}
|
||||
|
||||
/// Define hook '_OnSignal' for all termination signals
|
||||
void Master::_HookSignals()
|
||||
{
|
||||
signal(SIGINT, _OnSignal);
|
||||
signal(SIGTERM, _OnSignal);
|
||||
#ifdef _WIN32
|
||||
signal(SIGBREAK, _OnSignal);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Unhook the signals before leaving
|
||||
void Master::_UnhookSignals()
|
||||
{
|
||||
signal(SIGINT, 0);
|
||||
signal(SIGTERM, 0);
|
||||
#ifdef _WIN32
|
||||
signal(SIGBREAK, 0);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/** \file
|
||||
\ingroup Trinityd
|
||||
*/
|
||||
|
||||
#include "Common.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
#include "Log.h"
|
||||
#include "RASocket.h"
|
||||
#include "World.h"
|
||||
#include "Config/ConfigEnv.h"
|
||||
#include "Util.h"
|
||||
#include "AccountMgr.h"
|
||||
|
||||
/// \todo Make this thread safe if in the future 2 admins should be able to log at the same time.
|
||||
SOCKET r;
|
||||
|
||||
#define dropclient {Sendf("I'm busy right now, come back later."); \
|
||||
SetCloseAndDelete(); \
|
||||
return; \
|
||||
}
|
||||
|
||||
uint32 iSession=0; ///< Session number (incremented each time a new connection is made)
|
||||
unsigned int iUsers=0; ///< Number of active administrators
|
||||
|
||||
typedef int(* pPrintf)(const char*,...);
|
||||
|
||||
void ParseCommand(CliCommandHolder::Print*, char*command);
|
||||
|
||||
/// RASocket constructor
|
||||
RASocket::RASocket(ISocketHandler &h): TcpSocket(h)
|
||||
{
|
||||
|
||||
///- Increment the session number
|
||||
iSess =iSession++ ;
|
||||
|
||||
///- Get the config parameters
|
||||
bSecure = sConfig.GetBoolDefault( "RA.Secure", true );
|
||||
iMinLevel = sConfig.GetIntDefault( "RA.MinLevel", 3 );
|
||||
|
||||
///- Initialize buffer and data
|
||||
iInputLength=0;
|
||||
buff=new char[RA_BUFF_SIZE];
|
||||
stage=NONE;
|
||||
}
|
||||
|
||||
/// RASocket destructor
|
||||
RASocket::~RASocket()
|
||||
{
|
||||
///- Delete buffer and decrease active admins count
|
||||
delete [] buff;
|
||||
|
||||
sLog.outRALog("Connection was closed.\n");
|
||||
|
||||
if(stage==OK)
|
||||
iUsers--;
|
||||
}
|
||||
|
||||
/// Accept an incoming connection
|
||||
void RASocket::OnAccept()
|
||||
{
|
||||
std::string ss=GetRemoteAddress();
|
||||
sLog.outRALog("Incoming connection from %s.\n",ss.c_str());
|
||||
///- If there is already an active admin, drop the connection
|
||||
if(iUsers)
|
||||
dropclient
|
||||
|
||||
///- Else print Motd
|
||||
Sendf("%s\r\n",sWorld.GetMotd());
|
||||
}
|
||||
|
||||
/// Read data from the network
|
||||
void RASocket::OnRead()
|
||||
{
|
||||
///- Read data and check input length
|
||||
TcpSocket::OnRead();
|
||||
|
||||
unsigned int sz=ibuf.GetLength();
|
||||
if(iInputLength+sz>=RA_BUFF_SIZE)
|
||||
{
|
||||
sLog.outRALog("Input buffer overflow, possible DOS attack.\n");
|
||||
SetCloseAndDelete();
|
||||
return;
|
||||
}
|
||||
|
||||
///- If there is already an active admin (other than you), drop the connection
|
||||
if(stage!=OK && iUsers)
|
||||
dropclient
|
||||
|
||||
char *inp = new char [sz+1];
|
||||
ibuf.Read(inp,sz);
|
||||
|
||||
/// \todo Can somebody explain this 'Linux bugfix'?
|
||||
if(stage==NONE)
|
||||
if(sz>4) //linux remote telnet
|
||||
if(memcmp(inp ,"USER ",5))
|
||||
{
|
||||
delete [] inp;return;
|
||||
printf("lin bugfix");
|
||||
} //linux bugfix
|
||||
|
||||
///- Discard data after line break or line feed
|
||||
bool gotenter=false;
|
||||
unsigned int y=0;
|
||||
for(;y<sz;y++)
|
||||
if(inp[y]=='\r'||inp[y]=='\n')
|
||||
{
|
||||
gotenter=true;
|
||||
break;
|
||||
}
|
||||
|
||||
//No buffer overflow (checked above)
|
||||
memcpy(&buff[iInputLength],inp,y);
|
||||
iInputLength+=y;
|
||||
delete [] inp;
|
||||
if(gotenter)
|
||||
{
|
||||
|
||||
buff[iInputLength]=0;
|
||||
iInputLength=0;
|
||||
switch(stage)
|
||||
{
|
||||
/// <ul> <li> If the input is 'USER <username>'
|
||||
case NONE:
|
||||
if(!memcmp(buff,"USER ",5)) //got "USER" cmd
|
||||
{
|
||||
szLogin=&buff[5];
|
||||
|
||||
///- Get the gmlevel and password from the account table
|
||||
std::string login = szLogin;
|
||||
|
||||
///- Convert Account name to Upper Format
|
||||
AccountMgr::normilizeString(login);
|
||||
|
||||
///- Escape the Login to allow quotes in names
|
||||
LoginDatabase.escape_string(login);
|
||||
|
||||
QueryResult* result = LoginDatabase.PQuery("SELECT gmlevel FROM account WHERE username = '%s'",login.c_str());
|
||||
|
||||
///- If the user is not found, deny access
|
||||
if(!result)
|
||||
{
|
||||
Sendf("-No such user.\r\n");
|
||||
sLog.outRALog("User %s does not exist.\n",szLogin.c_str());
|
||||
if(bSecure)SetCloseAndDelete();
|
||||
}
|
||||
else
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
|
||||
//szPass=fields[0].GetString();
|
||||
|
||||
///- if gmlevel is too low, deny access
|
||||
if(fields[0].GetUInt32()<iMinLevel)
|
||||
{
|
||||
Sendf("-Not enough privileges.\r\n");
|
||||
sLog.outRALog("User %s has no privilege.\n",szLogin.c_str());
|
||||
if(bSecure)SetCloseAndDelete();
|
||||
} else
|
||||
{
|
||||
stage=LG;
|
||||
}
|
||||
delete result;
|
||||
}
|
||||
}
|
||||
break;
|
||||
///<li> If the input is 'PASS <password>' (and the user already gave his username)
|
||||
case LG:
|
||||
if(!memcmp(buff,"PASS ",5)) //got "PASS" cmd
|
||||
{ //login+pass ok
|
||||
///- If password is correct, increment the number of active administrators
|
||||
std::string login = szLogin;
|
||||
std::string pw = &buff[5];
|
||||
|
||||
AccountMgr::normilizeString(login);
|
||||
AccountMgr::normilizeString(pw);
|
||||
LoginDatabase.escape_string(login);
|
||||
LoginDatabase.escape_string(pw);
|
||||
|
||||
QueryResult *check = LoginDatabase.PQuery(
|
||||
"SELECT 1 FROM account WHERE username = '%s' AND sha_pass_hash=SHA1(CONCAT(username,':','%s'))",
|
||||
login.c_str(), pw.c_str());
|
||||
|
||||
if(check)
|
||||
{
|
||||
delete check;
|
||||
r=GetSocket();
|
||||
stage=OK;
|
||||
++iUsers;
|
||||
|
||||
Sendf("+Logged in.\r\n");
|
||||
sLog.outRALog("User %s has logged in.\n",szLogin.c_str());
|
||||
Sendf("TC>");
|
||||
}
|
||||
else
|
||||
{
|
||||
///- Else deny access
|
||||
Sendf("-Wrong pass.\r\n");
|
||||
sLog.outRALog("User %s has failed to log in.\n",szLogin.c_str());
|
||||
if(bSecure)SetCloseAndDelete();
|
||||
}
|
||||
}
|
||||
break;
|
||||
///<li> If user is logged, parse and execute the command
|
||||
case OK:
|
||||
if(strlen(buff))
|
||||
{
|
||||
sLog.outRALog("Got '%s' cmd.\n",buff);
|
||||
sWorld.QueueCliCommand(&RASocket::zprint , buff);
|
||||
}
|
||||
else
|
||||
Sendf("TC>");
|
||||
break;
|
||||
///</ul>
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// Output function
|
||||
void RASocket::zprint( const char * szText )
|
||||
{
|
||||
if( !szText )
|
||||
return;
|
||||
|
||||
#ifdef RA_CRYPT
|
||||
|
||||
char *megabuffer=strdup(szText);
|
||||
unsigned int sz=strlen(megabuffer);
|
||||
Encrypt(megabuffer,sz);
|
||||
send(r,megabuffer,sz,0);
|
||||
delete [] megabuffer;
|
||||
|
||||
#else
|
||||
|
||||
unsigned int sz=strlen(szText);
|
||||
send(r,szText,sz,0);
|
||||
|
||||
#endif
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,345 @@
|
||||
/*
|
||||
* 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 realmd Realm Daemon
|
||||
/// @{
|
||||
/// \file
|
||||
|
||||
#include "Common.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
#include "RealmList.h"
|
||||
|
||||
#include "Config/ConfigEnv.h"
|
||||
#include "Log.h"
|
||||
#include "sockets/ListenSocket.h"
|
||||
#include "AuthSocket.h"
|
||||
#include "SystemConfig.h"
|
||||
#include "Util.h"
|
||||
|
||||
// Format is YYYYMMDDRR where RR is the change in the conf file
|
||||
// for that day.
|
||||
#ifndef _REALMDCONFVERSION
|
||||
# define _REALMDCONFVERSION 2007062001
|
||||
#endif
|
||||
|
||||
#ifndef _TRINITY_REALM_CONFIG
|
||||
# define _TRINITY_REALM_CONFIG "trinityrealm.conf"
|
||||
#endif //_TRINITY_REALM_CONFIG
|
||||
|
||||
#ifdef WIN32
|
||||
#include "ServiceWin32.h"
|
||||
char serviceName[] = "realmd";
|
||||
char serviceLongName[] = "Trinity realm service";
|
||||
char serviceDescription[] = "Massive Network Game Object Server";
|
||||
/*
|
||||
* -1 - not in service mode
|
||||
* 0 - stopped
|
||||
* 1 - running
|
||||
* 2 - paused
|
||||
*/
|
||||
int m_ServiceStatus = -1;
|
||||
#endif
|
||||
|
||||
bool StartDB(std::string &dbstring);
|
||||
void UnhookSignals();
|
||||
void HookSignals();
|
||||
|
||||
bool stopEvent = false; ///< Setting it to true stops the server
|
||||
RealmList m_realmList; ///< Holds the list of realms for this server
|
||||
|
||||
DatabaseType LoginDatabase; ///< Accessor to the realm server database
|
||||
|
||||
/// Print out the usage string for this program on the console.
|
||||
void usage(const char *prog)
|
||||
{
|
||||
sLog.outString("Usage: \n %s [<options>]\n"
|
||||
" -c config_file use config_file as configuration file\n\r"
|
||||
#ifdef WIN32
|
||||
" Running as service functions:\n\r"
|
||||
" --service run as service\n\r"
|
||||
" -s install install service\n\r"
|
||||
" -s uninstall uninstall service\n\r"
|
||||
#endif
|
||||
,prog);
|
||||
}
|
||||
|
||||
/// Launch the realm server
|
||||
extern int main(int argc, char **argv)
|
||||
{
|
||||
///- Command line parsing to get the configuration file name
|
||||
char const* cfg_file = _TRINITY_REALM_CONFIG;
|
||||
int c=1;
|
||||
while( c < argc )
|
||||
{
|
||||
if( strcmp(argv[c],"-c") == 0)
|
||||
{
|
||||
if( ++c >= argc )
|
||||
{
|
||||
sLog.outError("Runtime-Error: -c option requires an input argument");
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
cfg_file = argv[c];
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
////////////
|
||||
//Services//
|
||||
////////////
|
||||
if( strcmp(argv[c],"-s") == 0)
|
||||
{
|
||||
if( ++c >= argc )
|
||||
{
|
||||
sLog.outError("Runtime-Error: -s option requires an input argument");
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
if( strcmp(argv[c],"install") == 0)
|
||||
{
|
||||
if (WinServiceInstall())
|
||||
sLog.outString("Installing service");
|
||||
return 1;
|
||||
}
|
||||
else if( strcmp(argv[c],"uninstall") == 0)
|
||||
{
|
||||
if(WinServiceUninstall())
|
||||
sLog.outString("Uninstalling service");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog.outError("Runtime-Error: unsupported option %s",argv[c]);
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if( strcmp(argv[c],"--service") == 0)
|
||||
{
|
||||
WinServiceRun();
|
||||
}
|
||||
////
|
||||
#endif
|
||||
++c;
|
||||
}
|
||||
|
||||
if (!sConfig.SetSource(cfg_file))
|
||||
{
|
||||
sLog.outError("Could not find configuration file %s.", cfg_file);
|
||||
return 1;
|
||||
}
|
||||
sLog.outString("Using configuration file %s.", cfg_file);
|
||||
|
||||
///- Check the version of the configuration file
|
||||
uint32 confVersion = sConfig.GetIntDefault("ConfVersion", 0);
|
||||
if (confVersion < _REALMDCONFVERSION)
|
||||
{
|
||||
sLog.outError("*****************************************************************************");
|
||||
sLog.outError(" WARNING: Your trinityrealm.conf version indicates your conf file is out of date!");
|
||||
sLog.outError(" Please check for updates, as your current default values may cause");
|
||||
sLog.outError(" strange behavior.");
|
||||
sLog.outError("*****************************************************************************");
|
||||
clock_t pause = 3000 + clock();
|
||||
|
||||
while (pause > clock()) {}
|
||||
}
|
||||
|
||||
sLog.outString( "%s (realm-daemon)", _FULLVERSION );
|
||||
sLog.outString( "<Ctrl-C> to stop.\n" );
|
||||
|
||||
/// realmd PID file creation
|
||||
std::string pidfile = sConfig.GetStringDefault("PidFile", "");
|
||||
if(!pidfile.empty())
|
||||
{
|
||||
uint32 pid = CreatePIDFile(pidfile);
|
||||
if( !pid )
|
||||
{
|
||||
sLog.outError( "Cannot create PID file %s.\n", pidfile.c_str() );
|
||||
return 1;
|
||||
}
|
||||
|
||||
sLog.outString( "Daemon PID: %u\n", pid );
|
||||
}
|
||||
|
||||
///- Initialize the database connection
|
||||
std::string dbstring;
|
||||
if(!StartDB(dbstring))
|
||||
return 1;
|
||||
|
||||
///- Get the list of realms for the server
|
||||
m_realmList.Initialize(sConfig.GetIntDefault("RealmsStateUpdateDelay", 20));
|
||||
if (m_realmList.size() == 0)
|
||||
{
|
||||
sLog.outError("No valid realms specified.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
///- Launch the listening network socket
|
||||
port_t rmport = sConfig.GetIntDefault( "RealmServerPort", DEFAULT_REALMSERVER_PORT );
|
||||
std::string bind_ip = sConfig.GetStringDefault("BindIP", "0.0.0.0");
|
||||
|
||||
SocketHandler h;
|
||||
ListenSocket<AuthSocket> authListenSocket(h);
|
||||
if ( authListenSocket.Bind(bind_ip.c_str(),rmport))
|
||||
{
|
||||
sLog.outError( "Trinity realm can not bind to %s:%d",bind_ip.c_str(), rmport );
|
||||
return 1;
|
||||
}
|
||||
|
||||
h.Add(&authListenSocket);
|
||||
|
||||
///- Catch termination signals
|
||||
HookSignals();
|
||||
|
||||
///- Handle affinity for multiple processors and process priority on Windows
|
||||
#ifdef WIN32
|
||||
{
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
|
||||
uint32 Aff = sConfig.GetIntDefault("UseProcessors", 0);
|
||||
if(Aff > 0)
|
||||
{
|
||||
ULONG_PTR appAff;
|
||||
ULONG_PTR sysAff;
|
||||
|
||||
if(GetProcessAffinityMask(hProcess,&appAff,&sysAff))
|
||||
{
|
||||
ULONG_PTR curAff = Aff & appAff; // remove non accessible processors
|
||||
|
||||
if(!curAff )
|
||||
{
|
||||
sLog.outError("Processors marked in UseProcessors bitmask (hex) %x not accessible for realmd. Accessible processors bitmask (hex): %x",Aff,appAff);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(SetProcessAffinityMask(hProcess,curAff))
|
||||
sLog.outString("Using processors (bitmask, hex): %x", curAff);
|
||||
else
|
||||
sLog.outError("Can't set used processors (hex): %x", curAff);
|
||||
}
|
||||
}
|
||||
sLog.outString();
|
||||
}
|
||||
|
||||
bool Prio = sConfig.GetBoolDefault("ProcessPriority", false);
|
||||
|
||||
if(Prio)
|
||||
{
|
||||
if(SetPriorityClass(hProcess,HIGH_PRIORITY_CLASS))
|
||||
sLog.outString("TrinityRealm process priority class set to HIGH");
|
||||
else
|
||||
sLog.outError("ERROR: Can't set realmd process priority class.");
|
||||
sLog.outString();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// maximum counter for next ping
|
||||
uint32 numLoops = (sConfig.GetIntDefault( "MaxPingTime", 30 ) * (MINUTE * 1000000 / 100000));
|
||||
uint32 loopCounter = 0;
|
||||
|
||||
///- Wait for termination signal
|
||||
while (!stopEvent)
|
||||
{
|
||||
|
||||
h.Select(0, 100000);
|
||||
|
||||
if( (++loopCounter) == numLoops )
|
||||
{
|
||||
loopCounter = 0;
|
||||
sLog.outDetail("Ping MySQL to keep connection alive");
|
||||
delete LoginDatabase.Query("SELECT 1 FROM realmlist LIMIT 1");
|
||||
}
|
||||
#ifdef WIN32
|
||||
if (m_ServiceStatus == 0) stopEvent = true;
|
||||
while (m_ServiceStatus == 2) Sleep(1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
///- Wait for the delay thread to exit
|
||||
LoginDatabase.HaltDelayThread();
|
||||
|
||||
///- Remove signal handling before leaving
|
||||
UnhookSignals();
|
||||
|
||||
sLog.outString( "Halting process..." );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Handle termination signals
|
||||
/** Put the global variable stopEvent to 'true' if a termination signal is caught **/
|
||||
void OnSignal(int s)
|
||||
{
|
||||
switch (s)
|
||||
{
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
stopEvent = true;
|
||||
break;
|
||||
#ifdef _WIN32
|
||||
case SIGBREAK:
|
||||
stopEvent = true;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
signal(s, OnSignal);
|
||||
}
|
||||
|
||||
/// Initialize connection to the database
|
||||
bool StartDB(std::string &dbstring)
|
||||
{
|
||||
if(!sConfig.GetString("LoginDatabaseInfo", &dbstring))
|
||||
{
|
||||
sLog.outError("Database not specified");
|
||||
return false;
|
||||
}
|
||||
|
||||
sLog.outString("Database: %s", dbstring.c_str() );
|
||||
if(!LoginDatabase.Initialize(dbstring.c_str()))
|
||||
{
|
||||
sLog.outError("Cannot connect to database");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Define hook 'OnSignal' for all termination signals
|
||||
void HookSignals()
|
||||
{
|
||||
signal(SIGINT, OnSignal);
|
||||
signal(SIGTERM, OnSignal);
|
||||
#ifdef _WIN32
|
||||
signal(SIGBREAK, OnSignal);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Unhook the signals before leaving
|
||||
void UnhookSignals()
|
||||
{
|
||||
signal(SIGINT, 0);
|
||||
signal(SIGTERM, 0);
|
||||
#ifdef _WIN32
|
||||
signal(SIGBREAK, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// @}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/** \file
|
||||
\ingroup realmd
|
||||
*/
|
||||
|
||||
#include "Common.h"
|
||||
#include "RealmList.h"
|
||||
#include "Policies/SingletonImp.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
|
||||
INSTANTIATE_SINGLETON_1( RealmList );
|
||||
|
||||
extern DatabaseType LoginDatabase;
|
||||
|
||||
RealmList::RealmList( ) : m_UpdateInterval(0), m_NextUpdateTime(time(NULL))
|
||||
{
|
||||
}
|
||||
|
||||
/// Load the realm list from the database
|
||||
void RealmList::Initialize(uint32 updateInterval)
|
||||
{
|
||||
m_UpdateInterval = updateInterval;
|
||||
|
||||
///- Get the content of the realmlist table in the database
|
||||
UpdateRealms(true);
|
||||
}
|
||||
|
||||
void RealmList::UpdateRealm( uint32 ID, const std::string& name, const std::string& address, uint32 port, uint8 icon, uint8 color, uint8 timezone, AccountTypes allowedSecurityLevel, float popu)
|
||||
{
|
||||
///- Create new if not exist or update existed
|
||||
Realm& realm = m_realms[name];
|
||||
|
||||
realm.m_ID = ID;
|
||||
realm.name = name;
|
||||
realm.icon = icon;
|
||||
realm.color = color;
|
||||
realm.timezone = timezone;
|
||||
realm.allowedSecurityLevel = allowedSecurityLevel;
|
||||
realm.populationLevel = popu;
|
||||
|
||||
///- Append port to IP address.
|
||||
std::ostringstream ss;
|
||||
ss << address << ":" << port;
|
||||
realm.address = ss.str();
|
||||
}
|
||||
|
||||
void RealmList::UpdateIfNeed()
|
||||
{
|
||||
// maybe disabled or updated recently
|
||||
if(!m_UpdateInterval || m_NextUpdateTime > time(NULL))
|
||||
return;
|
||||
|
||||
m_NextUpdateTime = time(NULL) + m_UpdateInterval;
|
||||
|
||||
// Clears Realm list
|
||||
m_realms.clear();
|
||||
|
||||
// Get the content of the realmlist table in the database
|
||||
UpdateRealms(false);
|
||||
}
|
||||
|
||||
void RealmList::UpdateRealms(bool init)
|
||||
{
|
||||
sLog.outDetail("Updating Realm List...");
|
||||
|
||||
QueryResult *result = LoginDatabase.Query( "SELECT id, name, address, port, icon, color, timezone, allowedSecurityLevel, population FROM realmlist WHERE color <> 3 ORDER BY name" );
|
||||
|
||||
///- Circle through results and add them to the realm map
|
||||
if(result)
|
||||
{
|
||||
do
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
|
||||
uint8 allowedSecurityLevel = fields[7].GetUInt8();
|
||||
|
||||
UpdateRealm(fields[0].GetUInt32(), fields[1].GetCppString(),fields[2].GetCppString(),fields[3].GetUInt32(),fields[4].GetUInt8(), fields[5].GetUInt8(), fields[6].GetUInt8(), (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), fields[8].GetFloat() );
|
||||
if(init)
|
||||
sLog.outString("Added realm \"%s\".", fields[1].GetString());
|
||||
} while( result->NextRow() );
|
||||
delete result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user