aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVincent_Michael <Vincent_Michael@gmx.de>2013-01-16 23:43:07 +0100
committerVincent_Michael <Vincent_Michael@gmx.de>2013-01-16 23:43:07 +0100
commit224b4480a70c4896d67e2f2907620b550e585057 (patch)
tree6241ec784a2594c10d51ebb5a010667a1d0bf00e /src
parent11bd11badcb730304efa9f850c925dd426f756fd (diff)
parenta8652baaa437cca3eced2d533c0dde3ca3184d1b (diff)
Merge branch 'master' of github.com:TrinityCore/TrinityCore into mmaps
Diffstat (limited to 'src')
-rw-r--r--src/server/authserver/Main.cpp4
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp46
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp2
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp31
-rw-r--r--src/server/game/Server/WorldSession.cpp35
-rw-r--r--src/server/game/Server/WorldSession.h3
-rw-r--r--src/server/game/Server/WorldSocket.cpp199
-rw-r--r--src/server/game/Server/WorldSocket.h43
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp9
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp114
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.h9
-rw-r--r--src/server/game/Spells/SpellMgr.cpp2
-rw-r--r--src/server/game/Spells/SpellScript.cpp67
-rw-r--r--src/server/game/Spells/SpellScript.h72
-rw-r--r--src/server/game/World/World.cpp4
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp56
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp10
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp230
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp69
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h17
-rw-r--r--src/server/shared/Logging/Appender.cpp4
-rw-r--r--src/server/shared/Logging/Appender.h2
-rw-r--r--src/server/shared/Logging/AppenderConsole.cpp2
-rw-r--r--src/server/shared/Logging/AppenderConsole.h2
-rw-r--r--src/server/shared/Logging/AppenderDB.cpp16
-rw-r--r--src/server/shared/Logging/AppenderDB.h11
-rw-r--r--src/server/shared/Logging/AppenderFile.cpp3
-rw-r--r--src/server/shared/Logging/AppenderFile.h2
-rw-r--r--src/server/shared/Logging/Log.cpp33
-rw-r--r--src/server/shared/Logging/Log.h4
-rw-r--r--src/server/worldserver/Master.cpp2
-rw-r--r--src/server/worldserver/worldserver.conf.dist8
32 files changed, 737 insertions, 374 deletions
diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp
index f4f73e2c33d..c87df4ef7ab 100644
--- a/src/server/authserver/Main.cpp
+++ b/src/server/authserver/Main.cpp
@@ -134,8 +134,6 @@ extern int main(int argc, char **argv)
if (!StartDB())
return 1;
- sLog->SetRealmID(0); // ensure we've set realm to 0 (authserver realmid)
-
// Get the list of realms for the server
sRealmList->Initialize(ConfigMgr::GetIntDefault("RealmsStateUpdateDelay", 20));
if (sRealmList->size() == 0)
@@ -272,7 +270,7 @@ bool StartDB()
}
sLog->outInfo(LOG_FILTER_AUTHSERVER, "Started auth database connection pool.");
- sLog->EnableDBAppenders();
+ sLog->SetRealmId(0); // Enables DB appenders when realm is set.
return true;
}
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index c08e085e816..84c9dffabd2 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -2121,18 +2121,20 @@ SmartScriptHolder SmartScript::CreateEvent(SMART_EVENT e, uint32 event_flags, ui
ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*= NULL*/)
{
- Unit* trigger = NULL;
+ Unit* scriptTrigger = NULL;
if (invoker)
- trigger = invoker;
+ scriptTrigger = invoker;
else if (Unit* tempLastInvoker = GetLastInvoker())
- trigger = tempLastInvoker;
+ scriptTrigger = tempLastInvoker;
+
+ WorldObject* baseObject = GetBaseObject();
ObjectList* l = new ObjectList();
switch (e.GetTargetType())
{
case SMART_TARGET_SELF:
- if (GetBaseObject())
- l->push_back(GetBaseObject());
+ if (baseObject)
+ l->push_back(baseObject);
break;
case SMART_TARGET_VICTIM:
if (me && me->getVictim())
@@ -2160,17 +2162,17 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
break;
case SMART_TARGET_NONE:
case SMART_TARGET_ACTION_INVOKER:
- if (trigger)
- l->push_back(trigger);
+ if (scriptTrigger)
+ l->push_back(scriptTrigger);
break;
case SMART_TARGET_ACTION_INVOKER_VEHICLE:
- if (trigger && trigger->GetVehicle() && trigger->GetVehicle()->GetBase())
- l->push_back(trigger->GetVehicle()->GetBase());
+ if (scriptTrigger && scriptTrigger->GetVehicle() && scriptTrigger->GetVehicle()->GetBase())
+ l->push_back(scriptTrigger->GetVehicle()->GetBase());
break;
case SMART_TARGET_INVOKER_PARTY:
- if (trigger)
+ if (scriptTrigger)
{
- if (Player* player = trigger->ToPlayer())
+ if (Player* player = scriptTrigger->ToPlayer())
{
if (Group* group = player->GetGroup())
{
@@ -2182,7 +2184,7 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
// this even if there is a group (thus the else-check), it will add the
// same player to the list twice. We don't want that to happen.
else
- l->push_back(trigger);
+ l->push_back(scriptTrigger);
}
}
break;
@@ -2198,7 +2200,7 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
if (me && me == *itr)
continue;
- if (((e.target.unitRange.creature && (*itr)->ToCreature()->GetEntry() == e.target.unitRange.creature) || !e.target.unitRange.creature) && GetBaseObject()->IsInRange(*itr, (float)e.target.unitRange.minDist, (float)e.target.unitRange.maxDist))
+ if (((e.target.unitRange.creature && (*itr)->ToCreature()->GetEntry() == e.target.unitRange.creature) || !e.target.unitRange.creature) && baseObject->IsInRange(*itr, (float)e.target.unitRange.minDist, (float)e.target.unitRange.maxDist))
l->push_back(*itr);
}
@@ -2255,7 +2257,7 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
if (go && go == *itr)
continue;
- if (((e.target.goRange.entry && IsGameObject(*itr) && (*itr)->ToGameObject()->GetEntry() == e.target.goRange.entry) || !e.target.goRange.entry) && GetBaseObject()->IsInRange((*itr), (float)e.target.goRange.minDist, (float)e.target.goRange.maxDist))
+ if (((e.target.goRange.entry && IsGameObject(*itr) && (*itr)->ToGameObject()->GetEntry() == e.target.goRange.entry) || !e.target.goRange.entry) && baseObject->IsInRange((*itr), (float)e.target.goRange.minDist, (float)e.target.goRange.maxDist))
l->push_back(*itr);
}
@@ -2265,13 +2267,13 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
case SMART_TARGET_CREATURE_GUID:
{
Creature* target = NULL;
- if (!trigger && !GetBaseObject())
+ if (!scriptTrigger && !baseObject)
{
sLog->outError(LOG_FILTER_SQL, "SMART_TARGET_CREATURE_GUID can not be used without invoker");
break;
}
- target = FindCreatureNear(trigger ? trigger : GetBaseObject(), e.target.unitGUID.dbGuid);
+ target = FindCreatureNear(scriptTrigger ? scriptTrigger : baseObject, e.target.unitGUID.dbGuid);
if (target && (!e.target.unitGUID.entry || target->GetEntry() == e.target.unitGUID.entry))
l->push_back(target);
@@ -2280,13 +2282,13 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
case SMART_TARGET_GAMEOBJECT_GUID:
{
GameObject* target = NULL;
- if (!trigger && !GetBaseObject())
+ if (!scriptTrigger && !baseObject)
{
sLog->outError(LOG_FILTER_SQL, "SMART_TARGET_GAMEOBJECT_GUID can not be used without invoker");
break;
}
- target = FindGameObjectNear(trigger ? trigger : GetBaseObject(), e.target.goGUID.dbGuid);
+ target = FindGameObjectNear(scriptTrigger ? scriptTrigger : baseObject, e.target.goGUID.dbGuid);
if (target && (!e.target.goGUID.entry || target->GetEntry() == e.target.goGUID.entry))
l->push_back(target);
@@ -2296,9 +2298,9 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
{
// will always return a valid pointer, even if empty list
ObjectList* units = GetWorldObjectsInDist((float)e.target.playerRange.maxDist);
- if (!units->empty() && GetBaseObject())
+ if (!units->empty() && baseObject)
for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr)
- if (IsPlayer(*itr) && GetBaseObject()->IsInRange(*itr, (float)e.target.playerRange.minDist, (float)e.target.playerRange.maxDist))
+ if (IsPlayer(*itr) && baseObject->IsInRange(*itr, (float)e.target.playerRange.minDist, (float)e.target.playerRange.maxDist))
l->push_back(*itr);
delete units;
@@ -2325,14 +2327,14 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
}
case SMART_TARGET_CLOSEST_CREATURE:
{
- Creature* target = GetClosestCreatureWithEntry(GetBaseObject(), e.target.closest.entry, (float)(e.target.closest.dist ? e.target.closest.dist : 100), e.target.closest.dead ? false : true);
+ Creature* target = GetClosestCreatureWithEntry(baseObject, e.target.closest.entry, (float)(e.target.closest.dist ? e.target.closest.dist : 100), e.target.closest.dead ? false : true);
if (target)
l->push_back(target);
break;
}
case SMART_TARGET_CLOSEST_GAMEOBJECT:
{
- GameObject* target = GetClosestGameObjectWithEntry(GetBaseObject(), e.target.closest.entry, (float)(e.target.closest.dist ? e.target.closest.dist : 100));
+ GameObject* target = GetClosestGameObjectWithEntry(baseObject, e.target.closest.entry, (float)(e.target.closest.dist ? e.target.closest.dist : 100));
if (target)
l->push_back(target);
break;
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 5b3969c9b9d..93d4796f21a 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -2148,7 +2148,7 @@ bool Creature::LoadCreaturesAddon(bool reload)
if (HasAura(*itr))
{
if (!reload)
- sLog->outError(LOG_FILTER_SQL, "Creature (GUID: %u Entry: %u) has duplicate aura (spell %u) in `auras` field.", GetGUIDLow(), GetEntry(), *itr);
+ sLog->outError(LOG_FILTER_SQL, "Creature (GUID: %u Entry: %u) has duplicate aura (spell %u) in `auras` field.", GetDBTableGUIDLow(), GetEntry(), *itr);
continue;
}
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 3afe74fd68a..49ebb900189 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -14452,7 +14452,8 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
Unit* actionTarget = !isVictim ? target : this;
DamageInfo damageInfo = DamageInfo(actor, actionTarget, damage, procSpell, procSpell ? SpellSchoolMask(procSpell->SchoolMask) : SPELL_SCHOOL_MASK_NORMAL, SPELL_DIRECT_DAMAGE);
- ProcEventInfo eventInfo = ProcEventInfo(actor, actionTarget, target, procFlag, 0, 0, procExtra, NULL, &damageInfo, NULL /*HealInfo*/);
+ HealInfo healInfo = HealInfo(actor, actionTarget, damage, procSpell, procSpell ? SpellSchoolMask(procSpell->SchoolMask) : SPELL_SCHOOL_MASK_NORMAL);
+ ProcEventInfo eventInfo = ProcEventInfo(actor, actionTarget, target, procFlag, 0, 0, procExtra, NULL, &damageInfo, &healInfo);
ProcTriggeredList procTriggered;
// Fill procTriggered list
@@ -14483,6 +14484,10 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
if (!sConditionMgr->IsObjectMeetToConditions(condInfo, conditions))
continue;
+ // AuraScript Hook
+ if (!triggerData.aura->CallScriptCheckProcHandlers(itr->second, eventInfo))
+ continue;
+
// Triggered spells not triggering additional spells
bool triggered = !(spellProto->AttributesEx3 & SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED) ?
(procExtra & PROC_EX_INTERNAL_TRIGGERED && !(procFlag & PROC_FLAG_DONE_TRAP_ACTIVATION)) : false;
@@ -14531,15 +14536,21 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
SpellInfo const* spellInfo = i->aura->GetSpellInfo();
uint32 Id = i->aura->GetId();
+ AuraApplication const* aurApp = i->aura->GetApplicationOfTarget(GetGUID());
+
+ bool prepare = i->aura->CallScriptPrepareProcHandlers(aurApp, eventInfo);
+
// For players set spell cooldown if need
uint32 cooldown = 0;
- if (GetTypeId() == TYPEID_PLAYER && i->spellProcEvent && i->spellProcEvent->cooldown)
+ if (prepare && GetTypeId() == TYPEID_PLAYER && i->spellProcEvent && i->spellProcEvent->cooldown)
cooldown = i->spellProcEvent->cooldown;
// Note: must SetCantProc(false) before return
if (spellInfo->AttributesEx3 & SPELL_ATTR3_DISABLE_PROC)
SetCantProc(true);
+ i->aura->CallScriptProcHandlers(aurApp, eventInfo);
+
// This bool is needed till separate aura effect procs are still here
bool handled = false;
if (HandleAuraProc(target, damage, i->aura, procSpell, procFlag, procExtra, cooldown, &handled))
@@ -14558,6 +14569,13 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
AuraEffect* triggeredByAura = i->aura->GetEffect(effIndex);
ASSERT(triggeredByAura);
+ bool prevented = i->aura->CallScriptEffectProcHandlers(triggeredByAura, aurApp, eventInfo);
+ if (prevented)
+ {
+ takeCharges = true;
+ continue;
+ }
+
switch (triggeredByAura->GetAuraType())
{
case SPELL_AURA_PROC_TRIGGER_SPELL:
@@ -14725,13 +14743,16 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
takeCharges = true;
break;
} // switch (triggeredByAura->GetAuraType())
+ i->aura->CallScriptAfterEffectProcHandlers(triggeredByAura, aurApp, eventInfo);
} // for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
} // if (!handled)
// Remove charge (aura can be removed by triggers)
- if (useCharges && takeCharges)
+ if (prepare && useCharges && takeCharges)
i->aura->DropCharge();
+ i->aura->CallScriptAfterProcHandlers(aurApp, eventInfo);
+
if (spellInfo->AttributesEx3 & SPELL_ATTR3_DISABLE_PROC)
SetCantProc(false);
}
@@ -14752,7 +14773,7 @@ void Unit::GetProcAurasTriggeredOnEvent(std::list<AuraApplication*>& aurasTrigge
if (!(*itr)->GetRemoveMode())
if ((*itr)->GetBase()->IsProcTriggeredOnEvent(*itr, eventInfo))
{
- (*itr)->GetBase()->PrepareProcToTrigger();
+ (*itr)->GetBase()->PrepareProcToTrigger(*itr, eventInfo);
aurasTriggeringProc.push_back(*itr);
}
}
@@ -14764,7 +14785,7 @@ void Unit::GetProcAurasTriggeredOnEvent(std::list<AuraApplication*>& aurasTrigge
{
if (itr->second->GetBase()->IsProcTriggeredOnEvent(itr->second, eventInfo))
{
- itr->second->GetBase()->PrepareProcToTrigger();
+ itr->second->GetBase()->PrepareProcToTrigger(itr->second, eventInfo);
aurasTriggeringProc.push_back(itr->second);
}
}
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index 990963b8c4d..6a26dafde79 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -95,17 +95,28 @@ bool WorldSessionFilter::Process(WorldPacket* packet)
/// WorldSession constructor
WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter):
-m_muteTime(mute_time), m_timeOutTime(0), _player(NULL), m_Socket(sock),
-_security(sec), _accountId(id), m_expansion(expansion), _logoutTime(0),
-m_inQueue(false), m_playerLoading(false), m_playerLogout(false),
-m_playerRecentlyLogout(false), m_playerSave(false),
-m_sessionDbcLocale(sWorld->GetAvailableDbcLocale(locale)),
-m_sessionDbLocaleIndex(locale),
-m_latency(0), m_TutorialsChanged(false), recruiterId(recruiter),
-isRecruiter(isARecruiter), timeLastWhoCommand(0)
+ m_muteTime(mute_time),
+ m_timeOutTime(0),
+ _player(NULL),
+ m_Socket(sock),
+ _security(sec),
+ _accountId(id),
+ m_expansion(expansion),
+ _warden(NULL),
+ _logoutTime(0),
+ m_inQueue(false),
+ m_playerLoading(false),
+ m_playerLogout(false),
+ m_playerRecentlyLogout(false),
+ m_playerSave(false),
+ m_sessionDbcLocale(sWorld->GetAvailableDbcLocale(locale)),
+ m_sessionDbLocaleIndex(locale),
+ m_latency(0),
+ m_TutorialsChanged(false),
+ recruiterId(recruiter),
+ isRecruiter(isARecruiter),
+ timeLastWhoCommand(0)
{
- _warden = NULL;
-
if (sock)
{
m_Address = sock->GetRemoteAddress();
@@ -727,8 +738,8 @@ void WorldSession::SetAccountData(AccountDataType type, time_t tm, std::string c
void WorldSession::SendAccountDataTimes(uint32 mask)
{
- WorldPacket data(SMSG_ACCOUNT_DATA_TIMES, 4 + 1 + 4 + 8 * 4); // changed in WotLK
- data << uint32(time(NULL)); // unix time of something
+ WorldPacket data(SMSG_ACCOUNT_DATA_TIMES, 4 + 1 + 4 + NUM_ACCOUNT_DATA_TYPES * 4);
+ data << uint32(time(NULL)); // Server time
data << uint8(1);
data << uint32(mask); // type mask
for (uint32 i = 0; i < NUM_ACCOUNT_DATA_TYPES; ++i)
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 39f5425d9df..abe048279db 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -181,9 +181,6 @@ class CharacterCreateInfo
/// Server side data
uint8 CharCount;
-
- private:
- virtual ~CharacterCreateInfo(){};
};
/// Player session in the World
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index b47f801ab29..b9955fac523 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -159,27 +159,29 @@ int WorldSocket::SendPacket(WorldPacket const& pct)
if (closing_)
return -1;
- // Dump outgoing packet.
+ // Dump outgoing packet
if (sPacketLog->CanLogPacket())
sPacketLog->LogPacket(pct, SERVER_TO_CLIENT);
+ WorldPacket const* pkt = &pct;
+
+
if (m_Session)
- sLog->outTrace(LOG_FILTER_OPCODES, "S->C %s %s", m_Session->GetPlayerInfo().c_str(), GetOpcodeNameForLogging(pct.GetOpcode()).c_str());
+ sLog->outTrace(LOG_FILTER_OPCODES, "S->C: %s %s", m_Session->GetPlayerInfo().c_str(), GetOpcodeNameForLogging(pkt->GetOpcode()).c_str());
- // Create a copy of the original packet; this is to avoid issues if a hook modifies it.
- sScriptMgr->OnPacketSend(this, WorldPacket(pct));
+ sScriptMgr->OnPacketSend(this, *pkt);
- ServerPktHeader header(pct.size()+2, pct.GetOpcode());
+ ServerPktHeader header(pkt->size()+2, pkt->GetOpcode());
m_Crypt.EncryptSend ((uint8*)header.header, header.getHeaderLength());
- if (m_OutBuffer->space() >= pct.size() + header.getHeaderLength() && msg_queue()->is_empty())
+ if (m_OutBuffer->space() >= pkt->size() + header.getHeaderLength() && msg_queue()->is_empty())
{
// Put the packet on the buffer.
if (m_OutBuffer->copy((char*) header.header, header.getHeaderLength()) == -1)
ACE_ASSERT (false);
- if (!pct.empty())
- if (m_OutBuffer->copy((char*) pct.contents(), pct.size()) == -1)
+ if (!pkt->empty())
+ if (m_OutBuffer->copy((char*) pkt->contents(), pkt->size()) == -1)
ACE_ASSERT (false);
}
else
@@ -187,12 +189,12 @@ int WorldSocket::SendPacket(WorldPacket const& pct)
// Enqueue the packet.
ACE_Message_Block* mb;
- ACE_NEW_RETURN(mb, ACE_Message_Block(pct.size() + header.getHeaderLength()), -1);
+ ACE_NEW_RETURN(mb, ACE_Message_Block(pkt->size() + header.getHeaderLength()), -1);
mb->copy((char*) header.header, header.getHeaderLength());
- if (!pct.empty())
- mb->copy((const char*)pct.contents(), pct.size());
+ if (!pkt->empty())
+ mb->copy((const char*)pkt->contents(), pkt->size());
if (msg_queue()->enqueue_tail(mb, (ACE_Time_Value*)&ACE_Time_Value::zero) == -1)
{
@@ -245,20 +247,7 @@ int WorldSocket::open (void *a)
m_Address = remote_addr.get_host_addr();
- // Send startup packet.
- WorldPacket packet (SMSG_AUTH_CHALLENGE, 24);
- packet << uint32(1); // 1...31
- packet << m_Seed;
-
- BigNumber seed1;
- seed1.SetRand(16 * 8);
- packet.append(seed1.AsByteArray(16), 16); // new encryption seeds
-
- BigNumber seed2;
- seed2.SetRand(16 * 8);
- packet.append(seed2.AsByteArray(16), 16); // new encryption seeds
-
- if (SendPacket(packet) == -1)
+ if (HandleSendAuthSession() == -1)
return -1;
// Register with ACE Reactor
@@ -461,7 +450,7 @@ int WorldSocket::Update (void)
int ret;
do
- ret = handle_output (get_handle());
+ ret = handle_output(get_handle());
while (ret > 0);
return ret;
@@ -469,18 +458,18 @@ int WorldSocket::Update (void)
int WorldSocket::handle_input_header (void)
{
- ACE_ASSERT (m_RecvWPct == NULL);
+ ACE_ASSERT(m_RecvWPct == NULL);
- ACE_ASSERT (m_Header.length() == sizeof(ClientPktHeader));
+ ACE_ASSERT(m_Header.length() == sizeof(ClientPktHeader));
- m_Crypt.DecryptRecv ((uint8*) m_Header.rd_ptr(), sizeof(ClientPktHeader));
+ m_Crypt.DecryptRecv ((uint8*)m_Header.rd_ptr(), sizeof(ClientPktHeader));
- ClientPktHeader& header = *((ClientPktHeader*) m_Header.rd_ptr());
+ ClientPktHeader& header = *((ClientPktHeader*)m_Header.rd_ptr());
EndianConvertReverse(header.size);
EndianConvert(header.cmd);
- if ((header.size < 4) || (header.size > 10240) || (header.cmd > 10240))
+ if ((header.size < 4) || (header.size > 10240) || (header.cmd > 10240))
{
Player* _player = m_Session ? m_Session->GetPlayer() : NULL;
sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::handle_input_header(): client (account: %u, char [GUID: %u, name: %s]) sent malformed packet (size: %d, cmd: %d)",
@@ -495,11 +484,11 @@ int WorldSocket::handle_input_header (void)
header.size -= 4;
- ACE_NEW_RETURN (m_RecvWPct, WorldPacket ((uint16) header.cmd, header.size), -1);
+ ACE_NEW_RETURN(m_RecvWPct, WorldPacket ((uint16)header.cmd, header.size), -1);
if (header.size > 0)
{
- m_RecvWPct->resize (header.size);
+ m_RecvWPct->resize(header.size);
m_RecvPct.base ((char*) m_RecvWPct->contents(), m_RecvWPct->size());
}
else
@@ -666,7 +655,7 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct)
ACE_ASSERT (new_pct);
// manage memory ;)
- ACE_Auto_Ptr<WorldPacket> aptr (new_pct);
+ ACE_Auto_Ptr<WorldPacket> aptr(new_pct);
const ACE_UINT16 opcode = new_pct->GetOpcode();
@@ -677,15 +666,16 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct)
if (sPacketLog->CanLogPacket())
sPacketLog->LogPacket(*new_pct, CLIENT_TO_SERVER);
+ std::string opcodeName = GetOpcodeNameForLogging(opcode);
if (m_Session)
- sLog->outTrace(LOG_FILTER_OPCODES, "C->S %s %s", m_Session->GetPlayerInfo().c_str(), GetOpcodeNameForLogging(new_pct->GetOpcode()).c_str());
+ sLog->outTrace(LOG_FILTER_OPCODES, "C->S: %s %s", m_Session->GetPlayerInfo().c_str(), opcodeName.c_str());
try
{
switch (opcode)
{
case CMSG_PING:
- return HandlePing (*new_pct);
+ return HandlePing(*new_pct);
case CMSG_AUTH_SESSION:
if (m_Session)
{
@@ -694,18 +684,17 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct)
}
sScriptMgr->OnPacketReceive(this, WorldPacket(*new_pct));
- return HandleAuthSession (*new_pct);
+ return HandleAuthSession(*new_pct);
case CMSG_KEEP_ALIVE:
- sLog->outDebug(LOG_FILTER_NETWORKIO, "%s", GetOpcodeNameForLogging(opcode).c_str());
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "%s", opcodeName.c_str());
sScriptMgr->OnPacketReceive(this, WorldPacket(*new_pct));
return 0;
default:
{
- ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1);
-
+ ACE_GUARD_RETURN(LockType, Guard, m_SessionLock, -1);
if (!m_Session)
{
- sLog->outError(LOG_FILTER_NETWORKIO, "ProcessIncoming: Client not authed opcode = %u", uint32(opcode));
+ sLog->outError(LOG_FILTER_OPCODES, "ProcessIncoming: Client not authed opcode = %u", uint32(opcode));
return -1;
}
@@ -715,7 +704,7 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct)
// OK, give the packet to WorldSession
aptr.release();
- // WARNINIG here we call it with locks held.
+ // WARNING here we call it with locks held.
// Its possible to cause deadlock if QueuePacket calls back
m_Session->QueuePacket(new_pct);
return 0;
@@ -724,8 +713,8 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct)
}
catch (ByteBufferException &)
{
- sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::ProcessIncoming ByteBufferException occured while parsing an instant handled packet (opcode: %u) from client %s, accountid=%i. Disconnected client.",
- opcode, GetRemoteAddress().c_str(), m_Session ? int32(m_Session->GetAccountId()) : -1);
+ sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::ProcessIncoming ByteBufferException occured while parsing an instant handled packet %s from client %s, accountid=%i. Disconnected client.",
+ opcodeName.c_str(), GetRemoteAddress().c_str(), m_Session ? int32(m_Session->GetAccountId()) : -1);
new_pct->hexlike();
return -1;
}
@@ -733,36 +722,47 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct)
ACE_NOTREACHED (return 0);
}
+int WorldSocket::HandleSendAuthSession()
+{
+ WorldPacket packet(SMSG_AUTH_CHALLENGE, 37);
+ packet << uint32(1); // 1...31
+ packet << uint32(m_Seed);
+
+ BigNumber seed1;
+ seed1.SetRand(16 * 8);
+ packet.append(seed1.AsByteArray(16), 16); // new encryption seeds
+
+ BigNumber seed2;
+ seed2.SetRand(16 * 8);
+ packet.append(seed2.AsByteArray(16), 16); // new encryption seeds
+ return SendPacket(packet);
+}
+
int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
{
- // NOTE: ATM the socket is singlethread, have this in mind ...
uint8 digest[20];
uint32 clientSeed;
- uint32 unk2, unk3, unk5, unk6, unk7;
- uint64 unk4;
- uint32 BuiltNumberClient;
- uint32 id, security;
- //uint8 expansion = 0;
+ uint8 security;
+ uint32 id;
LocaleConstant locale;
std::string account;
SHA1Hash sha;
+ uint32 clientBuild;
+ uint32 unk2, unk3, unk5, unk6, unk7;
+ uint64 unk4;
BigNumber v, s, g, N;
WorldPacket packet, SendAddonPacked;
-
BigNumber k;
if (sWorld->IsClosed())
{
- packet.Initialize(SMSG_AUTH_RESPONSE, 1);
- packet << uint8(AUTH_REJECT);
- SendPacket(packet);
-
+ SendAuthResponseError(AUTH_REJECT);
sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: World closed, denying client (%s).", GetRemoteAddress().c_str());
return -1;
}
// Read the content of the packet
- recvPacket >> BuiltNumberClient; // for now no use
+ recvPacket >> clientBuild;
recvPacket >> unk2;
recvPacket >> account;
recvPacket >> unk3;
@@ -772,7 +772,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
recvPacket.read(digest, 20);
sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, unk3 %u, clientseed %u",
- BuiltNumberClient,
+ clientBuild,
unk2,
account.c_str(),
unk3,
@@ -788,11 +788,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
// Stop if the account is not found
if (!result)
{
- packet.Initialize (SMSG_AUTH_RESPONSE, 1);
- packet << uint8 (AUTH_UNKNOWN_ACCOUNT);
-
- SendPacket(packet);
-
+ SendAuthResponseError(AUTH_UNKNOWN_ACCOUNT);
sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: Sent Auth Response (unknown account).");
return -1;
}
@@ -810,37 +806,30 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
v.SetHexStr(fields[4].GetCString());
s.SetHexStr (fields[5].GetCString());
- const char* sStr = s.AsHexStr(); //Must be freed by OPENSSL_free()
- const char* vStr = v.AsHexStr(); //Must be freed by OPENSSL_free()
+ const char* sStr = s.AsHexStr(); // Must be freed by OPENSSL_free()
+ const char* vStr = v.AsHexStr(); // Must be freed by OPENSSL_free()
sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: (s, v) check s: %s v: %s",
- sStr,
- vStr);
+ sStr,
+ vStr);
- OPENSSL_free ((void*) sStr);
- OPENSSL_free ((void*) vStr);
+ OPENSSL_free((void*)sStr);
+ OPENSSL_free((void*)vStr);
///- Re-check ip locking (same check as in realmd).
if (fields[3].GetUInt8() == 1) // if ip is locked
{
if (strcmp (fields[2].GetCString(), GetRemoteAddress().c_str()))
{
- packet.Initialize (SMSG_AUTH_RESPONSE, 1);
- packet << uint8 (AUTH_FAILED);
- SendPacket(packet);
-
+ SendAuthResponseError(AUTH_FAILED);
sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs).");
return -1;
}
}
id = fields[0].GetUInt32();
- /*
- if (security > SEC_ADMINISTRATOR) // prevent invalid security settings in DB
- security = SEC_ADMINISTRATOR;
- */
- k.SetHexStr (fields[1].GetCString());
+ k.SetHexStr(fields[1].GetCString());
int64 mutetime = fields[7].GetInt64();
//! Negative mutetime indicates amount of seconds to be muted effective on next login - which is now.
@@ -866,10 +855,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
// Must be done before WorldSession is created
if (sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED) && os != "Win" && os != "OSX")
{
- packet.Initialize(SMSG_AUTH_RESPONSE, 1);
- packet << uint8(AUTH_REJECT);
- SendPacket(packet);
-
+ SendAuthResponseError(AUTH_REJECT);
sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: Client %s attempted to log in using invalid client OS (%s).", GetRemoteAddress().c_str(), os.c_str());
return -1;
}
@@ -900,10 +886,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
if (banresult) // if account banned
{
- packet.Initialize (SMSG_AUTH_RESPONSE, 1);
- packet << uint8 (AUTH_BANNED);
- SendPacket(packet);
-
+ SendAuthResponseError(AUTH_BANNED);
sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: Sent Auth Response (Account banned).");
return -1;
}
@@ -911,13 +894,9 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
// Check locked state for server
AccountTypes allowedAccountType = sWorld->GetPlayerSecurityLimit();
sLog->outDebug(LOG_FILTER_NETWORKIO, "Allowed Level: %u Player Level %u", allowedAccountType, AccountTypes(security));
- if (AccountTypes(security) < allowedAccountType)
+ if (allowedAccountType > SEC_PLAYER && AccountTypes(security) < allowedAccountType)
{
- WorldPacket Packet (SMSG_AUTH_RESPONSE, 1);
- Packet << uint8 (AUTH_UNAVAILABLE);
-
- SendPacket(packet);
-
+ SendAuthResponseError(AUTH_UNAVAILABLE);
sLog->outInfo(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: User tries to login but his security level is not enough");
return -1;
}
@@ -926,29 +905,25 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
uint32 t = 0;
uint32 seed = m_Seed;
- sha.UpdateData (account);
- sha.UpdateData ((uint8 *) & t, 4);
- sha.UpdateData ((uint8 *) & clientSeed, 4);
- sha.UpdateData ((uint8 *) & seed, 4);
- sha.UpdateBigNumbers (&k, NULL);
+ sha.UpdateData(account);
+ sha.UpdateData((uint8*)&t, 4);
+ sha.UpdateData((uint8*)&clientSeed, 4);
+ sha.UpdateData((uint8*)&seed, 4);
+ sha.UpdateBigNumbers(&k, NULL);
sha.Finalize();
std::string address = GetRemoteAddress();
- if (memcmp (sha.GetDigest(), digest, 20))
+ if (memcmp(sha.GetDigest(), digest, 20))
{
- packet.Initialize (SMSG_AUTH_RESPONSE, 1);
- packet << uint8 (AUTH_FAILED);
-
- SendPacket(packet);
-
+ SendAuthResponseError(AUTH_FAILED);
sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: Authentication failed for account: %u ('%s') address: %s", id, account.c_str(), address.c_str());
return -1;
}
sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.",
- account.c_str(),
- address.c_str());
+ account.c_str(),
+ address.c_str());
// Check if this user is by any chance a recruiter
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_RECRUITER);
@@ -971,7 +946,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
LoginDatabase.Execute(stmt);
// NOTE ATM the socket is single-threaded, have this in mind ...
- ACE_NEW_RETURN (m_Session, WorldSession (id, this, AccountTypes(security), expansion, mutetime, locale, recruiter, isRecruiter), -1);
+ ACE_NEW_RETURN(m_Session, WorldSession(id, this, AccountTypes(security), expansion, mutetime, locale, recruiter, isRecruiter), -1);
m_Crypt.Init(&k);
@@ -985,10 +960,9 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
// Sleep this Network thread for
uint32 sleepTime = sWorld->getIntConfig(CONFIG_SESSION_ADD_DELAY);
- ACE_OS::sleep (ACE_Time_Value (0, sleepTime));
-
- sWorld->AddSession (m_Session);
+ ACE_OS::sleep(ACE_Time_Value(0, sleepTime));
+ sWorld->AddSession(m_Session);
return 0;
}
@@ -1049,7 +1023,14 @@ int WorldSocket::HandlePing (WorldPacket& recvPacket)
}
}
- WorldPacket packet (SMSG_PONG, 4);
+ WorldPacket packet(SMSG_PONG, 4);
packet << ping;
return SendPacket(packet);
}
+
+void WorldSocket::SendAuthResponseError(uint8 code)
+{
+ WorldPacket packet(SMSG_AUTH_RESPONSE, 1);
+ packet << uint8(code);
+ SendPacket(packet);
+} \ No newline at end of file
diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h
index 6b59647bb6c..2d5762ef60e 100644
--- a/src/server/game/Server/WorldSocket.h
+++ b/src/server/game/Server/WorldSocket.h
@@ -97,13 +97,13 @@ class WorldSocket : public WorldHandler
typedef ACE_Guard<LockType> GuardType;
/// Check if socket is closed.
- bool IsClosed (void) const;
+ bool IsClosed(void) const;
/// Close the socket.
- void CloseSocket (void);
+ void CloseSocket(void);
/// Get address of connected peer.
- const std::string& GetRemoteAddress (void) const;
+ const std::string& GetRemoteAddress(void) const;
/// Send A packet on the socket, this function is reentrant.
/// @param pct packet to send
@@ -111,57 +111,60 @@ class WorldSocket : public WorldHandler
int SendPacket(const WorldPacket& pct);
/// Add reference to this object.
- long AddReference (void);
+ long AddReference(void);
/// Remove reference to this object.
- long RemoveReference (void);
+ long RemoveReference(void);
/// things called by ACE framework.
/// Called on open, the void* is the acceptor.
- virtual int open (void *);
+ virtual int open(void *);
/// Called on failures inside of the acceptor, don't call from your code.
- virtual int close (u_long);
+ virtual int close(u_long);
/// Called when we can read from the socket.
- virtual int handle_input (ACE_HANDLE = ACE_INVALID_HANDLE);
+ virtual int handle_input(ACE_HANDLE = ACE_INVALID_HANDLE);
/// Called when the socket can write.
- virtual int handle_output (ACE_HANDLE = ACE_INVALID_HANDLE);
+ virtual int handle_output(ACE_HANDLE = ACE_INVALID_HANDLE);
/// Called when connection is closed or error happens.
- virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE,
+ virtual int handle_close(ACE_HANDLE = ACE_INVALID_HANDLE,
ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK);
/// Called by WorldSocketMgr/ReactorRunnable.
- int Update (void);
+ int Update(void);
private:
/// Helper functions for processing incoming data.
- int handle_input_header (void);
- int handle_input_payload (void);
- int handle_input_missing_data (void);
+ int handle_input_header(void);
+ int handle_input_payload(void);
+ int handle_input_missing_data(void);
/// Help functions to mark/unmark the socket for output.
/// @param g the guard is for m_OutBufferLock, the function will release it
- int cancel_wakeup_output (GuardType& g);
- int schedule_wakeup_output (GuardType& g);
+ int cancel_wakeup_output(GuardType& g);
+ int schedule_wakeup_output(GuardType& g);
/// Drain the queue if its not empty.
- int handle_output_queue (GuardType& g);
+ int handle_output_queue(GuardType& g);
/// process one incoming packet.
/// @param new_pct received packet, note that you need to delete it.
- int ProcessIncoming (WorldPacket* new_pct);
+ int ProcessIncoming(WorldPacket* new_pct);
/// Called by ProcessIncoming() on CMSG_AUTH_SESSION.
- int HandleAuthSession (WorldPacket& recvPacket);
+ int HandleAuthSession(WorldPacket& recvPacket);
/// Called by ProcessIncoming() on CMSG_PING.
- int HandlePing (WorldPacket& recvPacket);
+ int HandlePing(WorldPacket& recvPacket);
+
+ int HandleSendAuthSession();
private:
+ void SendAuthResponseError(uint8);
/// Time in which the last ping was received
ACE_Time_Value m_LastPingTime;
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 3b5c6131c5a..da38a519917 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -1274,7 +1274,10 @@ void AuraEffect::PeriodicTick(AuraApplication * aurApp, Unit* caster) const
void AuraEffect::HandleProc(AuraApplication* aurApp, ProcEventInfo& eventInfo)
{
- // TODO: effect script handlers here
+ bool prevented = GetBase()->CallScriptEffectProcHandlers(const_cast<AuraEffect const*>(this), const_cast<AuraApplication const*>(aurApp), eventInfo);
+ if (prevented)
+ return;
+
switch (GetAuraType())
{
case SPELL_AURA_PROC_TRIGGER_SPELL:
@@ -1295,6 +1298,8 @@ void AuraEffect::HandleProc(AuraApplication* aurApp, ProcEventInfo& eventInfo)
default:
break;
}
+
+ GetBase()->CallScriptAfterEffectProcHandlers(const_cast<AuraEffect const*>(this), const_cast<AuraApplication const*>(aurApp), eventInfo);
}
void AuraEffect::CleanupTriggeredSpells(Unit* target)
@@ -1854,7 +1859,7 @@ void AuraEffect::HandlePhase(AuraApplication const* aurApp, uint8 mode, bool app
// call functions which may have additional effects after chainging state of unit
// phase auras normally not expected at BG but anyway better check
- if (apply && (mode & AURA_EFFECT_HANDLE_REAL))
+ if (apply)
{
// drop flag at invisibiliy in bg
target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 24a83c7990c..a41d25eae09 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -1940,9 +1940,12 @@ void Aura::AddProcCooldown(uint32 /*msec*/)
//m_procCooldown = time(NULL) + msec;
}
-void Aura::PrepareProcToTrigger()
+void Aura::PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInfo)
{
- // TODO: allow scripts to prevent charge drop/cooldown
+ bool prepare = CallScriptPrepareProcHandlers(aurApp, eventInfo);
+ if (!prepare)
+ return;
+
// take one charge, aura expiration will be handled in Aura::TriggerProcOnEvent (if needed)
if (IsUsingCharges())
{
@@ -1981,14 +1984,18 @@ bool Aura::IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventI
return false;
// do checks using conditions table
- ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_PROC, GetSpellInfo()->Id);
+ ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_PROC, GetId());
ConditionSourceInfo condInfo = ConditionSourceInfo(eventInfo.GetActor(), eventInfo.GetActionTarget());
if (!sConditionMgr->IsObjectMeetToConditions(condInfo, conditions))
return false;
+ // AuraScript Hook
+ bool check = const_cast<Aura*>(this)->CallScriptCheckProcHandlers(aurApp, eventInfo);
+ if (!check)
+ return false;
+
// TODO:
- // - add DoCheckProc() AuraScript hook
- // to allow additional requirements for procs
+ // do allow additional requirements for procs
// this is needed because this is the last moment in which you can prevent aura charge drop on proc
// and possibly a way to prevent default checks (if there're going to be any)
@@ -2052,14 +2059,14 @@ float Aura::CalcProcChance(SpellProcEntry const& procEntry, ProcEventInfo& event
void Aura::TriggerProcOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo)
{
- // TODO: OnProc hook here
+ CallScriptProcHandlers(const_cast<AuraApplication const*>(aurApp), eventInfo);
+
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
if (aurApp->HasEffect(i))
- // TODO: OnEffectProc hook here (allowing prevention of selected effects)
+ // OnEffectProc / AfterEffectProc hooks handled in AuraEffect::HandleProc()
GetEffect(i)->HandleProc(aurApp, eventInfo);
- // TODO: AfterEffectProc hook here
- // TODO: AfterProc hook here
+ CallScriptAfterProcHandlers(const_cast<AuraApplication const*>(aurApp), eventInfo);
// Remove aura if we've used last charge to proc
if (IsUsingCharges() && !GetCharges())
@@ -2355,6 +2362,95 @@ void Aura::CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication con
}
}
+bool Aura::CallScriptCheckProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo)
+{
+ for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ {
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_PROC, aurApp);
+ std::list<AuraScript::CheckProcHandler>::iterator hookItrEnd = (*scritr)->DoCheckProc.end(), hookItr = (*scritr)->DoCheckProc.begin();
+ for (; hookItr != hookItrEnd; ++hookItr)
+ if (!(*hookItr).Call(*scritr, eventInfo))
+ return false;
+ (*scritr)->_FinishScriptCall();
+ }
+ return true;
+}
+
+bool Aura::CallScriptPrepareProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo)
+{
+ bool prepare = true;
+ for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ {
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_PREPARE_PROC, aurApp);
+ std::list<AuraScript::AuraProcHandler>::iterator effEndItr = (*scritr)->DoPrepareProc.end(), effItr = (*scritr)->DoPrepareProc.begin();
+ for (; effItr != effEndItr; ++effItr)
+ (*effItr).Call(*scritr, eventInfo);
+
+ if (prepare && (*scritr)->_IsDefaultActionPrevented())
+ prepare = false;
+ (*scritr)->_FinishScriptCall();
+ }
+ return prepare;
+}
+
+void Aura::CallScriptProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo)
+{
+ for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ {
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_PROC, aurApp);
+ std::list<AuraScript::AuraProcHandler>::iterator hookItrEnd = (*scritr)->OnProc.end(), hookItr = (*scritr)->OnProc.begin();
+ for (; hookItr != hookItrEnd; ++hookItr)
+ (*hookItr).Call(*scritr, eventInfo);
+ (*scritr)->_FinishScriptCall();
+ }
+}
+
+void Aura::CallScriptAfterProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo)
+{
+ for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ {
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_PROC, aurApp);
+ std::list<AuraScript::AuraProcHandler>::iterator hookItrEnd = (*scritr)->AfterProc.end(), hookItr = (*scritr)->AfterProc.begin();
+ for (; hookItr != hookItrEnd; ++hookItr)
+ (*hookItr).Call(*scritr, eventInfo);
+ (*scritr)->_FinishScriptCall();
+ }
+}
+
+bool Aura::CallScriptEffectProcHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo)
+{
+ bool preventDefault = false;
+ for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ {
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PROC, aurApp);
+ std::list<AuraScript::EffectProcHandler>::iterator effEndItr = (*scritr)->OnEffectProc.end(), effItr = (*scritr)->OnEffectProc.begin();
+ for (; effItr != effEndItr; ++effItr)
+ {
+ if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
+ (*effItr).Call(*scritr, aurEff, eventInfo);
+ }
+ if (!preventDefault)
+ preventDefault = (*scritr)->_IsDefaultActionPrevented();
+ (*scritr)->_FinishScriptCall();
+ }
+ return preventDefault;
+}
+
+void Aura::CallScriptAfterEffectProcHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo)
+{
+ for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ {
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_PROC, aurApp);
+ std::list<AuraScript::EffectProcHandler>::iterator effEndItr = (*scritr)->AfterEffectProc.end(), effItr = (*scritr)->AfterEffectProc.begin();
+ for (; effItr != effEndItr; ++effItr)
+ {
+ if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
+ (*effItr).Call(*scritr, aurEff, eventInfo);
+ }
+ (*scritr)->_FinishScriptCall();
+ }
+}
+
UnitAura::UnitAura(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, uint64 casterGUID)
: Aura(spellproto, owner, caster, castItem, casterGUID)
{
diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h
index 88ebee18981..bd351548255 100644
--- a/src/server/game/Spells/Auras/SpellAuras.h
+++ b/src/server/game/Spells/Auras/SpellAuras.h
@@ -194,7 +194,7 @@ class Aura
void AddProcCooldown(uint32 msec);
bool IsUsingCharges() const { return m_isUsingCharges; }
void SetUsingCharges(bool val) { m_isUsingCharges = val; }
- void PrepareProcToTrigger();
+ void PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInfo);
bool IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo) const;
float CalcProcChance(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo) const;
void TriggerProcOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo);
@@ -218,6 +218,13 @@ class Aura
void CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount, bool & defaultPrevented);
void CallScriptEffectAfterManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount);
void CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & splitAmount);
+ // Spell Proc Hooks
+ bool CallScriptCheckProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo);
+ bool CallScriptPrepareProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo);
+ void CallScriptProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo);
+ void CallScriptAfterProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo);
+ bool CallScriptEffectProcHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo);
+ void CallScriptAfterEffectProcHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo);
std::list<AuraScript*> m_loadedScripts;
private:
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 582f13284bb..b258f01ccd5 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3633,6 +3633,8 @@ void SpellMgr::LoadDbcDataCorrections()
case 49345: // Call Emerald Drake
spellInfo->Effect[1] = 0;
break;
+ case 24314: // Threatening Gaze
+ spellInfo->AuraInterruptFlags |= AURA_INTERRUPT_FLAG_CAST | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_JUMP;
default:
break;
}
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index c29b08242a0..89ed223545f 100644
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -470,7 +470,7 @@ WorldLocation* SpellScript::GetHitDest()
{
if (!IsInEffectHook())
{
- sLog->outError(LOG_FILTER_TSCR, "Script: `%s` Spell: `%u`: function SpellScript::GetHitGObj was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId);
+ sLog->outError(LOG_FILTER_TSCR, "Script: `%s` Spell: `%u`: function SpellScript::GetHitDest was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId);
return NULL;
}
return m_spell->destTarget;
@@ -679,6 +679,30 @@ bool AuraScript::_Validate(SpellInfo const* entry)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog->outError(LOG_FILTER_TSCR, "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectSplit` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
+ for (std::list<CheckProcHandler>::iterator itr = DoCheckProc.begin(); itr != DoCheckProc.end(); ++itr)
+ if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
+ sLog->outError(LOG_FILTER_TSCR, "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `DoCheckProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
+
+ for (std::list<AuraProcHandler>::iterator itr = DoPrepareProc.begin(); itr != DoPrepareProc.end(); ++itr)
+ if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
+ sLog->outError(LOG_FILTER_TSCR, "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `DoPrepareProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
+
+ for (std::list<AuraProcHandler>::iterator itr = OnProc.begin(); itr != OnProc.end(); ++itr)
+ if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
+ sLog->outError(LOG_FILTER_TSCR, "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `OnProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
+
+ for (std::list<AuraProcHandler>::iterator itr = AfterProc.begin(); itr != AfterProc.end(); ++itr)
+ if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
+ sLog->outError(LOG_FILTER_TSCR, "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `AfterProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
+
+ for (std::list<EffectProcHandler>::iterator itr = OnEffectProc.begin(); itr != OnEffectProc.end(); ++itr)
+ if (!(*itr).GetAffectedEffectsMask(entry))
+ sLog->outError(LOG_FILTER_TSCR, "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectProc` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
+
+ for (std::list<EffectProcHandler>::iterator itr = AfterEffectProc.begin(); itr != AfterEffectProc.end(); ++itr)
+ if (!(*itr).GetAffectedEffectsMask(entry))
+ sLog->outError(LOG_FILTER_TSCR, "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `AfterEffectProc` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
+
return _SpellScript::_Validate(entry);
}
@@ -818,6 +842,37 @@ void AuraScript::EffectSplitHandler::Call(AuraScript* auraScript, AuraEffect* au
(auraScript->*pEffectHandlerScript)(aurEff, dmgInfo, splitAmount);
}
+AuraScript::CheckProcHandler::CheckProcHandler(AuraCheckProcFnType handlerScript)
+{
+ _HandlerScript = handlerScript;
+}
+
+bool AuraScript::CheckProcHandler::Call(AuraScript* auraScript, ProcEventInfo& eventInfo)
+{
+ return (auraScript->*_HandlerScript)(eventInfo);
+}
+
+AuraScript::AuraProcHandler::AuraProcHandler(AuraProcFnType handlerScript)
+{
+ _HandlerScript = handlerScript;
+}
+
+void AuraScript::AuraProcHandler::Call(AuraScript* auraScript, ProcEventInfo& eventInfo)
+{
+ (auraScript->*_HandlerScript)(eventInfo);
+}
+
+AuraScript::EffectProcHandler::EffectProcHandler(AuraEffectProcFnType effectHandlerScript, uint8 effIndex, uint16 effName)
+ : AuraScript::EffectBase(effIndex, effName)
+{
+ _EffectHandlerScript = effectHandlerScript;
+}
+
+void AuraScript::EffectProcHandler::Call(AuraScript* auraScript, AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+{
+ (auraScript->*_EffectHandlerScript)(aurEff, eventInfo);
+}
+
bool AuraScript::_Load(Aura* aura)
{
m_aura = aura;
@@ -853,6 +908,8 @@ bool AuraScript::_IsDefaultActionPrevented()
case AURA_SCRIPT_HOOK_EFFECT_PERIODIC:
case AURA_SCRIPT_HOOK_EFFECT_ABSORB:
case AURA_SCRIPT_HOOK_EFFECT_SPLIT:
+ case AURA_SCRIPT_HOOK_PREPARE_PROC:
+ case AURA_SCRIPT_HOOK_EFFECT_PROC:
return m_defaultActionPrevented;
default:
ASSERT(false && "AuraScript::_IsDefaultActionPrevented is called in a wrong place");
@@ -869,6 +926,8 @@ void AuraScript::PreventDefaultAction()
case AURA_SCRIPT_HOOK_EFFECT_PERIODIC:
case AURA_SCRIPT_HOOK_EFFECT_ABSORB:
case AURA_SCRIPT_HOOK_EFFECT_SPLIT:
+ case AURA_SCRIPT_HOOK_PREPARE_PROC:
+ case AURA_SCRIPT_HOOK_EFFECT_PROC:
m_defaultActionPrevented = true;
break;
default:
@@ -1051,6 +1110,12 @@ Unit* AuraScript::GetTarget() const
case AURA_SCRIPT_HOOK_EFFECT_MANASHIELD:
case AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD:
case AURA_SCRIPT_HOOK_EFFECT_SPLIT:
+ case AURA_SCRIPT_HOOK_CHECK_PROC:
+ case AURA_SCRIPT_HOOK_PREPARE_PROC:
+ case AURA_SCRIPT_HOOK_PROC:
+ case AURA_SCRIPT_HOOK_AFTER_PROC:
+ case AURA_SCRIPT_HOOK_EFFECT_PROC:
+ case AURA_SCRIPT_HOOK_EFFECT_AFTER_PROC:
return m_auraApplication->GetTarget();
default:
sLog->outError(LOG_FILTER_TSCR, "Script: `%s` Spell: `%u` AuraScript::GetTarget called in a hook in which the call won't have effect!", m_scriptName->c_str(), m_scriptSpellId);
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index 5791c701c07..6f1df2560dc 100644
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -428,14 +428,22 @@ enum AuraScriptHookType
AURA_SCRIPT_HOOK_EFFECT_SPLIT,
AURA_SCRIPT_HOOK_CHECK_AREA_TARGET,
AURA_SCRIPT_HOOK_DISPEL,
- AURA_SCRIPT_HOOK_AFTER_DISPEL
+ AURA_SCRIPT_HOOK_AFTER_DISPEL,
+ // Spell Proc Hooks
+ AURA_SCRIPT_HOOK_CHECK_PROC,
+ AURA_SCRIPT_HOOK_PREPARE_PROC,
+ AURA_SCRIPT_HOOK_PROC,
+ AURA_SCRIPT_HOOK_EFFECT_PROC,
+ AURA_SCRIPT_HOOK_EFFECT_AFTER_PROC,
+ AURA_SCRIPT_HOOK_AFTER_PROC,
/*AURA_SCRIPT_HOOK_APPLY,
AURA_SCRIPT_HOOK_REMOVE, */
};
+/*
#define HOOK_AURA_EFFECT_START HOOK_AURA_EFFECT_APPLY
#define HOOK_AURA_EFFECT_END HOOK_AURA_EFFECT_CALC_SPELLMOD + 1
#define HOOK_AURA_EFFECT_COUNT HOOK_AURA_EFFECT_END - HOOK_AURA_EFFECT_START
-
+*/
class AuraScript : public _SpellScript
{
// internal use classes & functions
@@ -453,6 +461,9 @@ class AuraScript : public _SpellScript
typedef void(CLASSNAME::*AuraEffectCalcSpellModFnType)(AuraEffect const*, SpellModifier* &); \
typedef void(CLASSNAME::*AuraEffectAbsorbFnType)(AuraEffect*, DamageInfo &, uint32 &); \
typedef void(CLASSNAME::*AuraEffectSplitFnType)(AuraEffect*, DamageInfo &, uint32 &); \
+ typedef bool(CLASSNAME::*AuraCheckProcFnType)(ProcEventInfo&); \
+ typedef void(CLASSNAME::*AuraProcFnType)(ProcEventInfo&); \
+ typedef void(CLASSNAME::*AuraEffectProcFnType)(AuraEffect const*, ProcEventInfo&); \
AURASCRIPT_FUNCTION_TYPE_DEFINES(AuraScript)
@@ -552,6 +563,30 @@ class AuraScript : public _SpellScript
private:
AuraEffectSplitFnType pEffectHandlerScript;
};
+ class CheckProcHandler
+ {
+ public:
+ CheckProcHandler(AuraCheckProcFnType handlerScript);
+ bool Call(AuraScript* auraScript, ProcEventInfo& eventInfo);
+ private:
+ AuraCheckProcFnType _HandlerScript;
+ };
+ class AuraProcHandler
+ {
+ public:
+ AuraProcHandler(AuraProcFnType handlerScript);
+ void Call(AuraScript* auraScript, ProcEventInfo& eventInfo);
+ private:
+ AuraProcFnType _HandlerScript;
+ };
+ class EffectProcHandler : public EffectBase
+ {
+ public:
+ EffectProcHandler(AuraEffectProcFnType effectHandlerScript, uint8 effIndex, uint16 effName);
+ void Call(AuraScript* auraScript, AuraEffect const* aurEff, ProcEventInfo& eventInfo);
+ private:
+ AuraEffectProcFnType _EffectHandlerScript;
+ };
#define AURASCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) \
class CheckAreaTargetFunction : public AuraScript::CheckAreaTargetHandler { public: CheckAreaTargetFunction(AuraCheckAreaTargetFnType _pHandlerScript) : AuraScript::CheckAreaTargetHandler((AuraScript::AuraCheckAreaTargetFnType)_pHandlerScript) {} }; \
@@ -565,6 +600,9 @@ class AuraScript : public _SpellScript
class EffectAbsorbFunction : public AuraScript::EffectAbsorbHandler { public: EffectAbsorbFunction(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectAbsorbHandler((AuraScript::AuraEffectAbsorbFnType)_pEffectHandlerScript, _effIndex) {} }; \
class EffectManaShieldFunction : public AuraScript::EffectManaShieldHandler { public: EffectManaShieldFunction(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectManaShieldHandler((AuraScript::AuraEffectAbsorbFnType)_pEffectHandlerScript, _effIndex) {} }; \
class EffectSplitFunction : public AuraScript::EffectSplitHandler { public: EffectSplitFunction(AuraEffectSplitFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectSplitHandler((AuraScript::AuraEffectSplitFnType)_pEffectHandlerScript, _effIndex) {} }; \
+ class CheckProcHandlerFunction : public AuraScript::CheckProcHandler { public: CheckProcHandlerFunction(AuraCheckProcFnType handlerScript) : AuraScript::CheckProcHandler((AuraScript::AuraCheckProcFnType)handlerScript) {} }; \
+ class AuraProcHandlerFunction : public AuraScript::AuraProcHandler { public: AuraProcHandlerFunction(AuraProcFnType handlerScript) : AuraScript::AuraProcHandler((AuraScript::AuraProcFnType)handlerScript) {} }; \
+ class EffectProcHandlerFunction : public AuraScript::EffectProcHandler { public: EffectProcHandlerFunction(AuraEffectProcFnType effectHandlerScript, uint8 effIndex, uint16 effName) : AuraScript::EffectProcHandler((AuraScript::AuraEffectProcFnType)effectHandlerScript, effIndex, effName) {} }; \
#define PrepareAuraScript(CLASSNAME) AURASCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) AURASCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME)
@@ -695,6 +733,36 @@ class AuraScript : public _SpellScript
HookList<EffectSplitHandler> OnEffectSplit;
#define AuraEffectSplitFn(F, I) EffectSplitFunction(&F, I)
+ // executed when aura checks if it can proc
+ // example: DoCheckProc += AuraCheckProcFn(class::function);
+ // where function is: bool function (ProcEventInfo& eventInfo);
+ HookList<CheckProcHandler> DoCheckProc;
+ #define AuraCheckProcFn(F) CheckProcHandlerFunction(&F)
+
+ // executed before aura procs (possibility to prevent charge drop/cooldown)
+ // example: DoPrepareProc += AuraProcFn(class::function);
+ // where function is: void function (ProcEventInfo& eventInfo);
+ HookList<AuraProcHandler> DoPrepareProc;
+ // executed when aura procs
+ // example: OnProc += AuraProcFn(class::function);
+ // where function is: void function (ProcEventInfo& eventInfo);
+ HookList<AuraProcHandler> OnProc;
+ // executed after aura proced
+ // example: AfterProc += AuraProcFn(class::function);
+ // where function is: void function (ProcEventInfo& eventInfo);
+ HookList<AuraProcHandler> AfterProc;
+ #define AuraProcFn(F) AuraProcHandlerFunction(&F)
+
+ // executed when aura effect procs
+ // example: OnEffectProc += AuraEffectProcFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
+ // where function is: void function (AuraEffect const* aurEff, ProcEventInfo& procInfo);
+ HookList<EffectProcHandler> OnEffectProc;
+ // executed after aura effect proced
+ // example: AfterEffectProc += AuraEffectProcFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
+ // where function is: void function (AuraEffect const* aurEff, ProcEventInfo& procInfo);
+ HookList<EffectProcHandler> AfterEffectProc;
+ #define AuraEffectProcFn(F, I, N) EffectProcHandlerFunction(&F, I, N)
+
// AuraScript interface - hook/effect execution manipulators
// prevents default action of a hook from being executed (works only while called in a hook which default action can be prevented)
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 9a6f0881471..da00034108c 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1788,7 +1788,9 @@ void World::SetInitialWorldSettings()
uint32 startupDuration = GetMSTimeDiffToNow(startupBegin);
sLog->outInfo(LOG_FILTER_WORLDSERVER, "World initialized in %u minutes %u seconds", (startupDuration / 60000), ((startupDuration % 60000) / 1000));
- sLog->EnableDBAppenders();
+
+ if (uint32 realmId = ConfigMgr::GetIntDefault("RealmID", 0)) // 0 reserved for auth
+ sLog->SetRealmId(realmId);
}
void World::DetectDBCLang()
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp
index 7d2c8807eeb..51aab7c20d0 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp
@@ -79,11 +79,7 @@ class boss_arlokk : public CreatureScript
struct boss_arlokkAI : public BossAI
{
- boss_arlokkAI(Creature* creature) : BossAI(creature, DATA_ARLOKK) {}
-
- uint32 summonCount;
- // Unit* markedTarget;
- uint64 markedTargetGUID;
+ boss_arlokkAI(Creature* creature) : BossAI(creature, DATA_ARLOKK) { }
void Reset()
{
@@ -113,13 +109,15 @@ class boss_arlokk : public CreatureScript
void JustReachedHome()
{
- if (instance)
- instance->SetData(DATA_ARLOKK, NOT_STARTED);
+ instance->SetBossState(DATA_ARLOKK, NOT_STARTED);
me->DespawnOrUnsummon();
}
void DoSummonPhanters()
{
+ if (summonCount > 30)
+ return;
+
if (markedTargetGUID)
Talk(SAY_FEAST_PANTHER, markedTargetGUID);
me->SummonCreature(NPC_ZULIAN_PROWLER, PosSummonProwlers[0], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
@@ -152,7 +150,8 @@ class boss_arlokk : public CreatureScript
events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 15000, 0, PHASE_ONE);
break;
case EVENT_MARK:
- DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_MARK);
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ DoCast(target, SPELL_MARK);
events.ScheduleEvent(EVENT_MARK, 15000, 0, PHASE_ONE);
break;
case EVENT_CLEAVE:
@@ -164,8 +163,7 @@ class boss_arlokk : public CreatureScript
events.ScheduleEvent(EVENT_GOUGE, urand(17000, 27000), 0, PHASE_TWO);
break;
case EVENT_SUMMON:
- if (summonCount <= 30)
- DoSummonPhanters();
+ DoSummonPhanters();
events.ScheduleEvent(EVENT_SUMMON, 5000);
break;
case EVENT_VANISH:
@@ -176,21 +174,21 @@ class boss_arlokk : public CreatureScript
events.ScheduleEvent(EVENT_VISIBLE, 6000);
break;
case EVENT_VISIBLE:
- {
- me->SetDisplayId(MODEL_ID_PANTHER);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- const CreatureTemplate* cinfo = me->GetCreatureTemplate();
- me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35)));
- me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35)));
- me->UpdateDamagePhysical(BASE_ATTACK);
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- AttackStart(target);
- events.ScheduleEvent(EVENT_VANISH, 39000);
- events.ScheduleEvent(EVENT_CLEAVE, 0, PHASE_TWO);
- events.ScheduleEvent(EVENT_GOUGE, 14000, 0, PHASE_TWO);
- events.SetPhase(PHASE_TWO);
- break;
- }
+ {
+ me->SetDisplayId(MODEL_ID_PANTHER);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ const CreatureTemplate* cinfo = me->GetCreatureTemplate();
+ me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35)));
+ me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35)));
+ me->UpdateDamagePhysical(BASE_ATTACK);
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ AttackStart(target);
+ events.ScheduleEvent(EVENT_VANISH, 39000);
+ events.ScheduleEvent(EVENT_CLEAVE, 0, PHASE_TWO);
+ events.ScheduleEvent(EVENT_GOUGE, 14000, 0, PHASE_TWO);
+ events.SetPhase(PHASE_TWO);
+ break;
+ }
default:
break;
}
@@ -198,11 +196,15 @@ class boss_arlokk : public CreatureScript
DoMeleeAttackIfReady();
}
+
+ private:
+ uint32 summonCount;
+ uint64 markedTargetGUID;
};
CreatureAI* GetAI(Creature* creature) const
{
- return new boss_arlokkAI(creature);
+ return GetZulGurubAI<boss_arlokkAI>(creature);
}
};
@@ -214,7 +216,7 @@ class go_gong_of_bethekk : public GameObjectScript
{
if (InstanceScript* instance = go->GetInstanceScript())
{
- if (instance->GetData(DATA_ARLOKK) == DONE || instance->GetBossState(DATA_ARLOKK) == IN_PROGRESS)
+ if (instance->GetBossState(DATA_ARLOKK) == DONE || instance->GetBossState(DATA_ARLOKK) == IN_PROGRESS)
return true;
instance->SetBossState(DATA_ARLOKK, IN_PROGRESS);
return true;
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp
index 8003f4a1ed7..68aac7547df 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp
@@ -90,15 +90,15 @@ class boss_hakkar : public CreatureScript
events.ScheduleEvent(EVENT_CAUSE_INSANITY, 17000);
events.ScheduleEvent(EVENT_WILL_OF_HAKKAR, 17000);
events.ScheduleEvent(EVENT_ENRAGE, 600000);
- if (instance->GetData(DATA_JEKLIK) != DONE)
+ if (instance->GetBossState(DATA_JEKLIK) != DONE)
events.ScheduleEvent(EVENT_ASPECT_OF_JEKLIK, 4000);
- if (instance->GetData(DATA_VENOXIS) != DONE)
+ if (instance->GetBossState(DATA_VENOXIS) != DONE)
events.ScheduleEvent(EVENT_ASPECT_OF_VENOXIS, 7000);
- if (instance->GetData(DATA_MARLI) != DONE)
+ if (instance->GetBossState(DATA_MARLI) != DONE)
events.ScheduleEvent(EVENT_ASPECT_OF_MARLI, 12000);
- if (instance->GetData(DATA_THEKAL) != DONE)
+ if (instance->GetBossState(DATA_THEKAL) != DONE)
events.ScheduleEvent(EVENT_ASPECT_OF_THEKAL, 8000);
- if (instance->GetData(DATA_ARLOKK) != DONE)
+ if (instance->GetBossState(DATA_ARLOKK) != DONE)
events.ScheduleEvent(EVENT_ASPECT_OF_ARLOKK, 18000);
Talk(SAY_AGGRO);
}
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp
index acfa38e542d..e402480609b 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp
@@ -25,6 +25,9 @@ EndScriptData */
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
+#include "Spell.h"
+#include "SpellAuras.h"
+#include "SpellScript.h"
#include "zulgurub.h"
enum Says
@@ -52,19 +55,22 @@ enum Spells
enum Events
{
- EVENT_CHECK_START = 1,
- EVENT_STARTED = 2,
- EVENT_OVERPOWER = 3,
- EVENT_MORTAL_STRIKE = 4,
- EVENT_WHIRLWIND = 5,
- EVENT_CHECK_OHGAN = 6,
- EVENT_WATCH_PLAYER = 7
+ EVENT_CHECK_SPEAKER = 1,
+ EVENT_CHECK_START = 2,
+ EVENT_STARTED = 3,
+ EVENT_OVERPOWER = 4,
+ EVENT_MORTAL_STRIKE = 5,
+ EVENT_WHIRLWIND = 6,
+ EVENT_CHECK_OHGAN = 7,
+ EVENT_WATCH_PLAYER = 8,
+ EVENT_CHARGE_PLAYER = 9
};
enum Misc
{
MODEL_OHGAN_MOUNT = 15271,
PATH_MANDOKIR = 492861,
+ POINT_MANDOKIR_END = 24,
CHAINED_SPIRT_COUNT = 20
};
@@ -92,33 +98,44 @@ Position const PosSummonChainedSpirits[CHAINED_SPIRT_COUNT] =
{ -12283.51f, -1924.839f, 133.5170f, 0.069813f }
};
+Position const PosMandokir[2] =
+{
+ { -12167.8f, -1927.25f, 153.73f, 3.76991f },
+ { -12197.86f, -1949.392f, 130.2745f, 0.0f }
+};
+
class boss_mandokir : public CreatureScript
{
public: boss_mandokir() : CreatureScript("boss_mandokir") {}
struct boss_mandokirAI : public BossAI
{
- boss_mandokirAI(Creature* creature) : BossAI(creature, DATA_MANDOKIR) {}
-
- uint8 killCount;
+ boss_mandokirAI(Creature* creature) : BossAI(creature, DATA_MANDOKIR) { }
void Reset()
{
- _Reset();
- killCount = 0;
+ if (me->GetPositionZ() > 140.0f)
+ {
+ _Reset();
+ killCount = 0;
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
+ events.ScheduleEvent(EVENT_CHECK_START, 1000);
+ if (Creature* speaker = Creature::GetCreature(*me, instance->GetData64(NPC_VILEBRANCH_SPEAKER)))
+ if (!speaker->isAlive())
+ speaker->Respawn(true);
+ }
+ summons.DespawnAll();
me->Mount(MODEL_OHGAN_MOUNT);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
- events.ScheduleEvent(EVENT_CHECK_START, 1000);
}
void JustDied(Unit* /*killer*/)
{
- _JustDied();
- }
-
- void Evade(Unit* /*killer*/)
- {
-
+ // Do not want to unsummon Ohgan
+ for (int i = 0; i < CHAINED_SPIRT_COUNT; ++i)
+ if (Creature* unsummon = Creature::GetCreature(*me, chainedSpirtGUIDs[i]))
+ unsummon->DespawnOrUnsummon();
+ instance->SetBossState(DATA_MANDOKIR, DONE);
+ instance->SaveToDB();
}
void EnterCombat(Unit* /*who*/)
@@ -129,39 +146,57 @@ class boss_mandokir : public CreatureScript
events.ScheduleEvent(EVENT_WHIRLWIND, urand(24000, 30000));
events.ScheduleEvent(EVENT_CHECK_OHGAN, 1000);
events.ScheduleEvent(EVENT_WATCH_PLAYER, urand(13000, 15000));
- me->SetSpeed(MOVE_RUN, false);
- me->GetMotionMaster()->Clear(true);
+ events.ScheduleEvent(EVENT_CHARGE_PLAYER, urand(33000, 38000));
+ me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation());
Talk(SAY_AGGRO);
me->Dismount();
// Summon Ohgan (Spell missing) TEMP HACK
- me->SummonCreature(NPC_OHGAN, me->getVictim()->GetPositionX(), me->getVictim()->GetPositionY(), me->getVictim()->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 35000);
+ me->SummonCreature(NPC_OHGAN, me->GetPositionX()-3, me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 35000);
+ // Summon Chained Spirits
for (int i = 0; i < CHAINED_SPIRT_COUNT; ++i)
- me->SummonCreature(NPC_CHAINED_SPIRT, PosSummonChainedSpirits[i], TEMPSUMMON_CORPSE_DESPAWN);
+ {
+ Creature* chainedSpirt = me->SummonCreature(NPC_CHAINED_SPIRT, PosSummonChainedSpirits[i], TEMPSUMMON_CORPSE_DESPAWN);
+ chainedSpirtGUIDs[i] = chainedSpirt->GetGUID();
+ }
+ DoZoneInCombat();
}
void KilledUnit(Unit* victim)
{
- if (victim->GetTypeId() == TYPEID_PLAYER)
+ if (victim->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if (++killCount == 3)
+ {
+ Talk(SAY_DING_KILL);
+ if (Creature* jindo = Creature::GetCreature(*me, instance->GetData64(DATA_JINDO)))
+ if (jindo->isAlive())
+ jindo->AI()->Talk(SAY_GRATS_JINDO);
+ DoCast(me, SPELL_LEVEL_UP, true);
+ killCount = 0;
+ }
+ }
+
+ void MovementInform(uint32 type, uint32 id)
+ {
+ if (type == WAYPOINT_MOTION_TYPE)
{
- if (++killCount == 3 && instance)
+ me->SetWalk(false);
+ if (id == POINT_MANDOKIR_END)
{
- Talk(SAY_DING_KILL);
- if (uint64 JindoGUID = instance->GetData64(DATA_JINDO))
- if (Creature* jTemp = Creature::GetCreature(*me, JindoGUID))
- if (jTemp->isAlive())
- jTemp->AI()->Talk(SAY_GRATS_JINDO);
- DoCast(me, SPELL_LEVEL_UP, true);
- killCount = 0;
+ me->SetHomePosition(PosMandokir[0]);
+ instance->SetBossState(DATA_MANDOKIR, NOT_STARTED);
+ me->DespawnOrUnsummon(6000); // No idea how to respawn on wipe.
}
}
}
void UpdateAI(uint32 const diff)
{
-
events.Update(diff);
if (!UpdateVictim())
+ {
if (instance->GetBossState(DATA_MANDOKIR) == NOT_STARTED || instance->GetBossState(DATA_MANDOKIR) == SPECIAL)
{
while (uint32 eventId = events.ExecuteEvent())
@@ -169,20 +204,17 @@ class boss_mandokir : public CreatureScript
switch (eventId)
{
case EVENT_CHECK_START:
- if(instance)
- if (instance->GetBossState(DATA_MANDOKIR) == SPECIAL)
- {
- me->SetSpeed(MOVE_RUN, true);
- me->GetMotionMaster()->MovePoint(0, -12197.86f, -1949.392f, 130.2745f);
- events.ScheduleEvent(EVENT_STARTED, 3000);
- }
- else
- events.ScheduleEvent(EVENT_CHECK_START, 1000);
+ if (instance->GetBossState(DATA_MANDOKIR) == SPECIAL)
+ {
+ me->GetMotionMaster()->MovePoint(0, PosMandokir[1].m_positionX, PosMandokir[1].m_positionY, PosMandokir[1].m_positionZ);
+ events.ScheduleEvent(EVENT_STARTED, 6000);
+ }
+ else
+ events.ScheduleEvent(EVENT_CHECK_START, 1000);
break;
case EVENT_STARTED:
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
- me->SetReactState(REACT_AGGRESSIVE);
- me->GetMotionMaster()->MovePath(PATH_MANDOKIR,false);
+ me->GetMotionMaster()->MovePath(PATH_MANDOKIR, false);
break;
default:
break;
@@ -190,6 +222,7 @@ class boss_mandokir : public CreatureScript
}
}
return;
+ }
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
@@ -212,24 +245,26 @@ class boss_mandokir : public CreatureScript
events.ScheduleEvent(EVENT_WHIRLWIND, urand(22000, 26000));
break;
case EVENT_CHECK_OHGAN:
- if (instance)
- if (instance->GetBossState(DATA_OHGAN) == DONE)
- {
- DoCast(me, SPELL_FRENZY);
- Talk(SAY_OHGAN_DEAD);
- }
- else
- events.ScheduleEvent(EVENT_CHECK_OHGAN, 1000);
+ if (instance->GetBossState(DATA_OHGAN) == DONE)
+ {
+ DoCast(me, SPELL_FRENZY);
+ Talk(SAY_OHGAN_DEAD);
+ }
+ else
+ events.ScheduleEvent(EVENT_CHECK_OHGAN, 1000);
break;
case EVENT_WATCH_PLAYER:
- if (Unit* player = SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true))
+ if (Unit* player = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
{
DoCast(player, SPELL_WATCH);
Talk(SAY_WATCH, player->GetGUID());
- // Not complete
}
events.ScheduleEvent(EVENT_WATCH_PLAYER, urand(12000, 15000));
break;
+ case EVENT_CHARGE_PLAYER:
+ DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true), SPELL_CHARGE);
+ events.ScheduleEvent(EVENT_CHARGE_PLAYER, urand(22000, 30000));
+ break;
default:
break;
}
@@ -237,17 +272,21 @@ class boss_mandokir : public CreatureScript
DoMeleeAttackIfReady();
}
+
+ private:
+ uint8 killCount;
+ uint64 chainedSpirtGUIDs[CHAINED_SPIRT_COUNT];
};
CreatureAI* GetAI(Creature* creature) const
{
- return new boss_mandokirAI(creature);
+ return GetZulGurubAI<boss_mandokirAI>(creature);
}
};
// Ohgan
-enum O_Spells
+enum OhganSpells
{
SPELL_SUNDERARMOR = 24317
};
@@ -258,13 +297,7 @@ class mob_ohgan : public CreatureScript
struct mob_ohganAI : public ScriptedAI
{
- mob_ohganAI(Creature* creature) : ScriptedAI(creature)
- {
- instance = me->GetInstanceScript();
- }
-
- uint32 SunderArmor_Timer;
- InstanceScript* instance;
+ mob_ohganAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript()) { }
void Reset()
{
@@ -275,17 +308,15 @@ class mob_ohgan : public CreatureScript
void JustDied(Unit* /*killer*/)
{
- if (instance)
- instance->SetBossState(DATA_OHGAN, DONE);
+ instance->SetBossState(DATA_OHGAN, DONE);
}
- void UpdateAI (const uint32 diff)
+ void UpdateAI(const uint32 diff)
{
- //Return since we have no target
+ // Return since we have no target
if (!UpdateVictim())
return;
- //SunderArmor_Timer
if (SunderArmor_Timer <= diff)
{
DoCastVictim(SPELL_SUNDERARMOR, true);
@@ -294,17 +325,19 @@ class mob_ohgan : public CreatureScript
DoMeleeAttackIfReady();
}
+
+ private:
+ uint32 SunderArmor_Timer;
+ InstanceScript* instance;
};
CreatureAI* GetAI(Creature* creature) const
{
- return new mob_ohganAI(creature);
+ return GetZulGurubAI<mob_ohganAI>(creature);
}
};
-// Vilebranch Speaker
-
-enum VS_Spells
+enum VilebranchSpells
{
SPELL_DEMORALIZING_SHOUT = 13730,
SPELL_CLEAVE = 15284
@@ -316,14 +349,7 @@ class mob_vilebranch_speaker : public CreatureScript
struct mob_vilebranch_speakerAI : public ScriptedAI
{
- mob_vilebranch_speakerAI(Creature* creature) : ScriptedAI(creature)
- {
- instance = me->GetInstanceScript();
- }
-
- uint32 demoralizing_Shout_Timer;
- uint32 cleave_Timer;
- InstanceScript* instance;
+ mob_vilebranch_speakerAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript()) { }
void Reset()
{
@@ -335,24 +361,21 @@ class mob_vilebranch_speaker : public CreatureScript
void JustDied(Unit* /*killer*/)
{
- if (instance)
- instance->SetBossState(DATA_MANDOKIR, SPECIAL);
+ instance->SetBossState(DATA_MANDOKIR, SPECIAL);
}
- void UpdateAI (const uint32 diff)
+ void UpdateAI(const uint32 diff)
{
// Return since we have no target
if (!UpdateVictim())
return;
- // demoralizing_Shout_Timer
if (demoralizing_Shout_Timer <= diff)
{
DoCast(me, SPELL_DEMORALIZING_SHOUT);
demoralizing_Shout_Timer = urand(22000, 30000);
} else demoralizing_Shout_Timer -= diff;
- // cleave_Timer
if (cleave_Timer <= diff)
{
DoCastVictim(SPELL_CLEAVE, true);
@@ -361,6 +384,11 @@ class mob_vilebranch_speaker : public CreatureScript
DoMeleeAttackIfReady();
}
+
+ private:
+ uint32 demoralizing_Shout_Timer;
+ uint32 cleave_Timer;
+ InstanceScript* instance;
};
CreatureAI* GetAI(Creature* creature) const
@@ -369,9 +397,39 @@ class mob_vilebranch_speaker : public CreatureScript
}
};
+class spell_threatening_gaze : public SpellScriptLoader
+{
+ public:
+ spell_threatening_gaze() : SpellScriptLoader("spell_threatening_gaze") { }
+
+ class spell_threatening_gaze_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_threatening_gaze_AuraScript);
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* caster = GetCaster())
+ if(Unit* target = GetTarget())
+ if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE && GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_DEATH)
+ caster->CastSpell(target, SPELL_WATCH_CHARGE);
+ }
+
+ void Register()
+ {
+ OnEffectRemove += AuraEffectRemoveFn(spell_threatening_gaze_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_threatening_gaze_AuraScript();
+ }
+};
+
void AddSC_boss_mandokir()
{
new boss_mandokir();
new mob_ohgan();
new mob_vilebranch_speaker();
+ new spell_threatening_gaze();
}
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp
index 48f1377da80..19a2ba39578 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp
@@ -29,7 +29,7 @@ EndScriptData */
class instance_zulgurub : public InstanceMapScript
{
- public: instance_zulgurub(): InstanceMapScript("instance_zulgurub", 309) {}
+ public: instance_zulgurub(): InstanceMapScript(ZGScriptName, 309) {}
struct instance_zulgurub_InstanceMapScript : public InstanceScript
{
@@ -38,25 +38,18 @@ class instance_zulgurub : public InstanceMapScript
SetBossNumber(EncounterCount);
}
- //If all High Priest bosses were killed. Lorkhan, Zath and Ohgan are added too.
- //Storing Lorkhan, Zath and Thekal because we need to cast on them later. Jindo is needed for healfunction too.
-
- uint64 lorKhanGUID;
- uint64 zathGUID;
- uint64 thekalGUID;
- uint64 jindoGUID;
-
void Initialize()
{
- lorKhanGUID = 0;
- zathGUID = 0;
- thekalGUID = 0;
- jindoGUID = 0;
+ ZealotLorkhanGUID = 0;
+ ZealotZathGUID = 0;
+ HighPriestTekalGUID = 0;
+ JindoTheHexxerGUID = 0;
+ VilebranchSpeakerGUID = 0;
}
bool IsEncounterInProgress() const
{
- //not active in Zul'Gurub
+ // not active in Zul'Gurub
return false;
}
@@ -64,10 +57,25 @@ class instance_zulgurub : public InstanceMapScript
{
switch (creature->GetEntry())
{
- case NPC_ZEALOT_LORKHAN: lorKhanGUID = creature->GetGUID(); break;
- case NPC_ZEALOT_ZATH: zathGUID = creature->GetGUID(); break;
- case NPC_HIGH_PRIEST_THEKAL: thekalGUID = creature->GetGUID(); break;
- case NPC_JINDO_THE_HEXXER: jindoGUID = creature->GetGUID(); break;
+ case NPC_ZEALOT_LORKHAN:
+ ZealotLorkhanGUID = creature->GetGUID();
+ break;
+ case NPC_ZEALOT_ZATH:
+ ZealotZathGUID = creature->GetGUID();
+ break;
+ case NPC_HIGH_PRIEST_THEKAL:
+ HighPriestTekalGUID = creature->GetGUID();
+ break;
+ case NPC_JINDO_THE_HEXXER:
+ JindoTheHexxerGUID = creature->GetGUID();
+ break;
+ case NPC_VILEBRANCH_SPEAKER:
+ VilebranchSpeakerGUID = creature->GetGUID();
+ break;
+ case NPC_MANDOKIR:
+ if (GetBossState(DATA_MANDOKIR) == DONE)
+ creature->DespawnOrUnsummon();
+ break;
}
}
@@ -75,10 +83,18 @@ class instance_zulgurub : public InstanceMapScript
{
switch (uiData)
{
- case DATA_LORKHAN: return lorKhanGUID;
- case DATA_ZATH: return zathGUID;
- case DATA_THEKAL: return thekalGUID;
- case DATA_JINDO: return jindoGUID;
+ case DATA_LORKHAN:
+ return ZealotLorkhanGUID;
+ break;
+ case DATA_ZATH:
+ return ZealotZathGUID;
+ break;
+ case DATA_THEKAL:
+ return HighPriestTekalGUID;
+ break;
+ case DATA_JINDO:
+ return JindoTheHexxerGUID;
+ break;
}
return 0;
}
@@ -125,6 +141,15 @@ class instance_zulgurub : public InstanceMapScript
OUT_LOAD_INST_DATA_COMPLETE;
}
+ private:
+ //If all High Priest bosses were killed. Lorkhan, Zath and Ohgan are added too.
+ //Storing Lorkhan, Zath and Thekal because we need to cast on them later. Jindo is needed for healfunction too.
+
+ uint64 ZealotLorkhanGUID;
+ uint64 ZealotZathGUID;
+ uint64 HighPriestTekalGUID;
+ uint64 JindoTheHexxerGUID;
+ uint64 VilebranchSpeakerGUID;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h b/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h
index 5871a203b00..34680447cd7 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h
@@ -20,6 +20,8 @@
uint32 const EncounterCount = 13;
+#define ZGScriptName "instance_zulgurub"
+
enum DataTypes
{
DATA_JEKLIK = 0, // Main boss
@@ -45,11 +47,22 @@ enum CreatureIds
NPC_JINDO_THE_HEXXER = 11380,
NPC_NIGHTMARE_ILLUSION = 15163,
NPC_ZULIAN_PROWLER = 15101,
- NPC_SPEAKER = 11391,
+ NPC_VILEBRANCH_SPEAKER = 11391,
NPC_SHADE_OF_JINDO = 14986,
NPC_SACRIFICED_TROLL = 14826,
NPC_OHGAN = 14988,
- NPC_CHAINED_SPIRT = 15117
+ NPC_CHAINED_SPIRT = 15117,
+ NPC_MANDOKIR = 11382
};
+template<class AI>
+CreatureAI* GetZulGurubAI(Creature* creature)
+{
+ if (InstanceMap* instance = creature->GetMap()->ToInstanceMap())
+ if (instance->GetInstanceScript())
+ if (instance->GetScriptId() == sObjectMgr->GetScriptId(ZGScriptName))
+ return new AI(creature);
+ return NULL;
+}
+
#endif
diff --git a/src/server/shared/Logging/Appender.cpp b/src/server/shared/Logging/Appender.cpp
index f2f5da53dae..1d215e1212e 100644
--- a/src/server/shared/Logging/Appender.cpp
+++ b/src/server/shared/Logging/Appender.cpp
@@ -73,10 +73,7 @@ void Appender::setLogLevel(LogLevel _level)
void Appender::write(LogMessage& message)
{
if (!level || level > message.level)
- {
- //fprintf(stderr, "Appender::write: Appender %s, Level %s. Msg %s Level %s Type %s WRONG LEVEL MASK\n", getName().c_str(), getLogLevelString(level), message.text.c_str(), getLogLevelString(message.level), getLogFilterTypeString(message.type)); // DEBUG - RemoveMe
return;
- }
message.prefix.clear();
if (flags & APPENDER_FLAGS_PREFIX_TIMESTAMP)
@@ -222,5 +219,6 @@ char const* Appender::getLogFilterTypeString(LogFilterType type)
default:
break;
}
+
return "???";
}
diff --git a/src/server/shared/Logging/Appender.h b/src/server/shared/Logging/Appender.h
index 6a0f0bdac26..a8854a8abc6 100644
--- a/src/server/shared/Logging/Appender.h
+++ b/src/server/shared/Logging/Appender.h
@@ -143,7 +143,7 @@ class Appender
static const char* getLogFilterTypeString(LogFilterType type);
private:
- virtual void _write(LogMessage& /*message*/) = 0;
+ virtual void _write(LogMessage const& /*message*/) = 0;
uint8 id;
std::string name;
diff --git a/src/server/shared/Logging/AppenderConsole.cpp b/src/server/shared/Logging/AppenderConsole.cpp
index d0af761188c..a1212bd135b 100644
--- a/src/server/shared/Logging/AppenderConsole.cpp
+++ b/src/server/shared/Logging/AppenderConsole.cpp
@@ -154,7 +154,7 @@ void AppenderConsole::ResetColor(bool stdout_stream)
#endif
}
-void AppenderConsole::_write(LogMessage& message)
+void AppenderConsole::_write(LogMessage const& message)
{
bool stdout_stream = message.level == LOG_LEVEL_ERROR || message.level == LOG_LEVEL_FATAL;
diff --git a/src/server/shared/Logging/AppenderConsole.h b/src/server/shared/Logging/AppenderConsole.h
index 3319c84e887..6f3fcca901c 100644
--- a/src/server/shared/Logging/AppenderConsole.h
+++ b/src/server/shared/Logging/AppenderConsole.h
@@ -51,7 +51,7 @@ class AppenderConsole: public Appender
private:
void SetColor(bool stdout_stream, ColorTypes color);
void ResetColor(bool stdout_stream);
- void _write(LogMessage& message);
+ void _write(LogMessage const& message);
bool _colored;
ColorTypes _colors[MaxLogLevels];
};
diff --git a/src/server/shared/Logging/AppenderDB.cpp b/src/server/shared/Logging/AppenderDB.cpp
index 86677eeedd8..ae5fc17de73 100644
--- a/src/server/shared/Logging/AppenderDB.cpp
+++ b/src/server/shared/Logging/AppenderDB.cpp
@@ -18,8 +18,8 @@
#include "AppenderDB.h"
#include "Database/DatabaseEnv.h"
-AppenderDB::AppenderDB(uint8 id, std::string const& name, LogLevel level, uint32 realmId)
- : Appender(id, name, APPENDER_DB, level), realm(realmId), enable(false)
+AppenderDB::AppenderDB(uint8 id, std::string const& name, LogLevel level)
+ : Appender(id, name, APPENDER_DB, level), realmId(0), enabled(false)
{
}
@@ -27,10 +27,11 @@ AppenderDB::~AppenderDB()
{
}
-void AppenderDB::_write(LogMessage& message)
+void AppenderDB::_write(LogMessage const& message)
{
- if (!enable)
+ if (!enabled)
return;
+
switch (message.type)
{
case LOG_FILTER_SQL:
@@ -40,7 +41,7 @@ void AppenderDB::_write(LogMessage& message)
default:
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_LOG);
stmt->setUInt64(0, message.mtime);
- stmt->setUInt32(1, realm);
+ stmt->setUInt32(1, realmId);
stmt->setUInt8(2, uint8(message.type));
stmt->setUInt8(3, uint8(message.level));
stmt->setString(4, message.text);
@@ -49,7 +50,8 @@ void AppenderDB::_write(LogMessage& message)
}
}
-void AppenderDB::setEnable(bool _enable)
+void AppenderDB::setRealmId(uint32 _realmId)
{
- enable = _enable;
+ enabled = true;
+ realmId = _realmId;
}
diff --git a/src/server/shared/Logging/AppenderDB.h b/src/server/shared/Logging/AppenderDB.h
index 5ab9a1ee423..f9dde0a1e82 100644
--- a/src/server/shared/Logging/AppenderDB.h
+++ b/src/server/shared/Logging/AppenderDB.h
@@ -23,14 +23,15 @@
class AppenderDB: public Appender
{
public:
- AppenderDB(uint8 _id, std::string const& _name, LogLevel level, uint32 realmId);
+ AppenderDB(uint8 _id, std::string const& _name, LogLevel level);
~AppenderDB();
- void setEnable(bool enable);
+
+ void setRealmId(uint32 realmId);
private:
- uint32 realm;
- bool enable;
- void _write(LogMessage& message);
+ uint32 realmId;
+ bool enabled;
+ void _write(LogMessage const& message);
};
#endif
diff --git a/src/server/shared/Logging/AppenderFile.cpp b/src/server/shared/Logging/AppenderFile.cpp
index 7b0bac03d03..8189237bb4e 100644
--- a/src/server/shared/Logging/AppenderFile.cpp
+++ b/src/server/shared/Logging/AppenderFile.cpp
@@ -39,7 +39,7 @@ AppenderFile::~AppenderFile()
}
}
-void AppenderFile::_write(LogMessage& message)
+void AppenderFile::_write(LogMessage const& message)
{
if (dynamicName)
{
@@ -70,5 +70,6 @@ FILE* AppenderFile::OpenFile(std::string const &filename, std::string const &mod
newName.append(LogMessage::getTimeStr(time(NULL)));
rename(filename.c_str(), newName.c_str()); // no error handling... if we couldn't make a backup, just ignore
}
+
return fopen((logDir + filename).c_str(), mode.c_str());
}
diff --git a/src/server/shared/Logging/AppenderFile.h b/src/server/shared/Logging/AppenderFile.h
index 934370d70b4..a3fe285cc7d 100644
--- a/src/server/shared/Logging/AppenderFile.h
+++ b/src/server/shared/Logging/AppenderFile.h
@@ -28,7 +28,7 @@ class AppenderFile: public Appender
FILE* OpenFile(std::string const& _name, std::string const& _mode, bool _backup);
private:
- void _write(LogMessage& message);
+ void _write(LogMessage const& message);
FILE* logfile;
std::string filename;
std::string logDir;
diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp
index 60320d049ac..96c72b5eb74 100644
--- a/src/server/shared/Logging/Log.cpp
+++ b/src/server/shared/Logging/Log.cpp
@@ -31,7 +31,6 @@
Log::Log() : worker(NULL)
{
- SetRealmID(0);
m_logsTimestamp = "_" + GetTimestampStr();
LoadFromConfig();
}
@@ -154,7 +153,7 @@ void Log::CreateAppenderFromConfig(const char* name)
case APPENDER_DB:
{
uint8 id = NextAppenderId();
- appenders[id] = new AppenderDB(id, name, level, realm);
+ appenders[id] = new AppenderDB(id, name, level);
break;
}
default:
@@ -265,13 +264,6 @@ void Log::ReadLoggersFromConfig()
loggers[LOG_FILTER_GENERAL].Create("root", LOG_FILTER_GENERAL, LOG_LEVEL_DISABLED);
}
-void Log::EnableDBAppenders()
-{
- for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it)
- if (it->second && it->second->getType() == APPENDER_DB)
- ((AppenderDB *)it->second)->setEnable(true);
-}
-
void Log::vlog(LogFilterType filter, LogLevel level, char const* str, va_list argptr)
{
char text[MAX_QUERY_LEN];
@@ -281,12 +273,16 @@ void Log::vlog(LogFilterType filter, LogLevel level, char const* str, va_list ar
void Log::write(LogMessage* msg)
{
+ if (loggers.empty())
+ return;
+
+ msg->text.append("\n");
+ Logger* logger = GetLoggerByType(msg->type);
+
if (worker)
- {
- msg->text.append("\n");
- Logger* logger = GetLoggerByType(msg->type);
worker->enqueue(new LogOperation(logger, msg));
- }
+ else
+ logger->write(*msg);
}
std::string Log::GetTimestampStr()
@@ -463,9 +459,11 @@ void Log::outCommand(uint32 account, const char * str, ...)
write(msg);
}
-void Log::SetRealmID(uint32 id)
+void Log::SetRealmId(uint32 id)
{
- realm = id;
+ for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it)
+ if (it->second && it->second->getType() == APPENDER_DB)
+ ((AppenderDB *)it->second)->setRealmId(id);
}
void Log::Close()
@@ -484,7 +482,10 @@ void Log::Close()
void Log::LoadFromConfig()
{
Close();
- worker = new LogWorker();
+
+ if (ConfigMgr::GetBoolDefault("Log.Async.Enable", false))
+ worker = new LogWorker();
+
AppenderId = 0;
m_logsDir = ConfigMgr::GetStringDefault("LogsDir", "");
if (!m_logsDir.empty())
diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h
index 6d6cfe715e8..46aaea4bad1 100644
--- a/src/server/shared/Logging/Log.h
+++ b/src/server/shared/Logging/Log.h
@@ -52,12 +52,11 @@ class Log
void outError(LogFilterType f, char const* str, ...) ATTR_PRINTF(3, 4);
void outFatal(LogFilterType f, char const* str, ...) ATTR_PRINTF(3, 4);
- void EnableDBAppenders();
void outCommand(uint32 account, const char * str, ...) ATTR_PRINTF(3, 4);
void outCharDump(char const* str, uint32 account_id, uint32 guid, char const* name);
static std::string GetTimestampStr();
- void SetRealmID(uint32 id);
+ void SetRealmId(uint32 id);
private:
void vlog(LogFilterType f, LogLevel level, char const* str, va_list argptr);
@@ -78,7 +77,6 @@ class Log
std::string m_logsDir;
std::string m_logsTimestamp;
- uint32 realm;
LogWorker* worker;
};
diff --git a/src/server/worldserver/Master.cpp b/src/server/worldserver/Master.cpp
index fe872c1977f..56dd64bc45a 100644
--- a/src/server/worldserver/Master.cpp
+++ b/src/server/worldserver/Master.cpp
@@ -438,8 +438,6 @@ bool Master::_StartDB()
}
sLog->outInfo(LOG_FILTER_WORLDSERVER, "Realm running as realm ID %d", realmID);
- sLog->SetRealmID(realmID);
-
///- Clean the database before starting
ClearOnlineAccounts();
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index 7c7aacd2f47..b3e6b636b32 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -2824,4 +2824,12 @@ Logger.Opcodes=41,6,Console Server
Loggers=Root Chat DBErrors GM RA Warden Character Load WorldServer Opcodes
#
+# Log.Async.Enable
+# Description: Enables asyncronous message logging.
+# Default: 0 - (Disabled)
+# 1 - (Enabled)
+
+Log.Async.Enable = 0
+
+#
###################################################################################################