*Merge with Trinity 783.

--HG--
branch : trunk
This commit is contained in:
megamage
2009-01-04 16:17:46 -06:00
38 changed files with 3090 additions and 415 deletions
+9
View File
@@ -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);
+2
View File
@@ -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;
+1
View File
@@ -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 \
+4
View File
@@ -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"
+2 -1
View File
@@ -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;
}
}
}
@@ -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
View File
@@ -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;
+5 -5
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+1 -1
View File
@@ -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());
+3
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+2 -1
View File
@@ -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
+3 -9
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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()
+1 -1
View File
@@ -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());
+6 -6
View File
@@ -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 (),
+1 -1
View File
@@ -53,6 +53,6 @@ typedef DatabaseMysql DatabaseType;
extern DatabaseType WorldDatabase;
extern DatabaseType CharacterDatabase;
extern DatabaseType loginDatabase;
extern DatabaseType LoginDatabase;
#endif
+1 -1
View File
@@ -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)
{
+165
View File
@@ -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
}
/// @}
+517
View File
@@ -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
}
+259
View File
@@ -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
+345
View File
@@ -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
}
/// @}
+102
View File
@@ -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;
}
}