aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp2
-rw-r--r--src/server/game/Entities/Player/Player.cpp12
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp60
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp5
-rw-r--r--src/server/game/Quests/QuestDef.cpp21
-rw-r--r--src/server/game/Quests/QuestDef.h1
-rw-r--r--src/server/game/Server/WorldSession.cpp15
-rw-r--r--src/server/game/Server/WorldSession.h78
-rw-r--r--src/server/game/World/World.cpp14
-rw-r--r--src/server/game/World/World.h4
-rw-r--r--src/server/scripts/Commands/cs_quest.cpp7
-rw-r--r--src/server/scripts/Spells/spell_quest.cpp150
-rw-r--r--src/server/worldserver/worldserver.conf.dist36
13 files changed, 280 insertions, 125 deletions
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index febf2e789a2..a1862c07d14 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -312,7 +312,7 @@ void SmartAI::UpdatePath(const uint32 diff)
mWPReached = false;
}
}
- if (me->IsInCombat() || HasEscortState(SMART_ESCORT_PAUSED | SMART_ESCORT_RETURNING))
+ if ((!me->HasReactState(REACT_PASSIVE) && me->IsInCombat()) || HasEscortState(SMART_ESCORT_PAUSED | SMART_ESCORT_RETURNING))
return;
// handle next wp
if (mWPReached)//reached WP
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 10dfe946a86..2c0d22bee29 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -16267,10 +16267,6 @@ void Player::KilledMonsterCredit(uint32 entry, uint64 guid /*= 0*/)
if (qInfo->RequiredNpcOrGo[j] <= 0)
continue;
- // skip Cast at creature objective
- if (qInfo->RequiredSpellCast[j] != 0)
- continue;
-
uint32 reqkill = qInfo->RequiredNpcOrGo[j];
if (reqkill == real_entry)
@@ -16360,10 +16356,6 @@ void Player::CastedCreatureOrGO(uint32 entry, uint64 guid, uint32 spell_id)
{
for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j)
{
- // skip kill creature objective (0) or wrong spell casts
- if (qInfo->RequiredSpellCast[j] != spell_id)
- continue;
-
uint32 reqTarget = 0;
if (isCreature)
@@ -16443,8 +16435,8 @@ void Player::TalkedToCreature(uint32 entry, uint64 guid)
{
for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j)
{
- // skip spell casts and Gameobject objectives
- if (qInfo->RequiredSpellCast[j] > 0 || qInfo->RequiredNpcOrGo[j] < 0)
+ // skip gameobject objectives
+ if (qInfo->RequiredNpcOrGo[j] < 0)
continue;
uint32 reqTarget = 0;
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index b902872ed4e..a46720e6d03 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -3725,16 +3725,12 @@ void ObjectMgr::LoadQuests()
"RequiredNpcOrGo1, RequiredNpcOrGo2, RequiredNpcOrGo3, RequiredNpcOrGo4, RequiredNpcOrGoCount1, RequiredNpcOrGoCount2, RequiredNpcOrGoCount3, RequiredNpcOrGoCount4, "
// 97 98 99 100 101 102 103 104
"RequiredSourceItemId1, RequiredSourceItemId2, RequiredSourceItemId3, RequiredSourceItemId4, RequiredSourceItemCount1, RequiredSourceItemCount2, RequiredSourceItemCount3, RequiredSourceItemCount4, "
- // 105 106 107 108 109 110 111 112 113 114 115 116
+ // 105 106 107 108 109 110 111 112 113 114 115 116
"RequiredItemId1, RequiredItemId2, RequiredItemId3, RequiredItemId4, RequiredItemId5, RequiredItemId6, RequiredItemCount1, RequiredItemCount2, RequiredItemCount3, RequiredItemCount4, RequiredItemCount5, RequiredItemCount6, "
- // 117 118 119 120 121 122 123 124 125
- "RequiredSpellCast1, RequiredSpellCast2, RequiredSpellCast3, RequiredSpellCast4, Unknown0, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4, "
- // 126 127 128 129 130 131 132 133 134 135
- "DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4, DetailsEmoteDelay1, DetailsEmoteDelay2, DetailsEmoteDelay3, DetailsEmoteDelay4, EmoteOnIncomplete, EmoteOnComplete, "
- // 136 137 138 139 140 141 142 143
- "OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4, OfferRewardEmoteDelay1, OfferRewardEmoteDelay2, OfferRewardEmoteDelay3, OfferRewardEmoteDelay4, "
- // 144
- "WDBVerified"
+ // 117 118 119 120 121 122 123 124 125 126 127 128 129
+ "Unknown0, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4, DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4, DetailsEmoteDelay1, DetailsEmoteDelay2, DetailsEmoteDelay3, DetailsEmoteDelay4, "
+ // 130 131 132 133 134 135 136 137 138 139 140
+ "EmoteOnIncomplete, EmoteOnComplete, OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4, OfferRewardEmoteDelay1, OfferRewardEmoteDelay2, OfferRewardEmoteDelay3, OfferRewardEmoteDelay4, WDBVerified"
" FROM quest_template");
if (!result)
{
@@ -4065,52 +4061,6 @@ void ObjectMgr::LoadQuests()
for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j)
{
- uint32 id = qinfo->RequiredSpellCast[j];
- if (id)
- {
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(id);
- if (!spellInfo)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `ReqSpellCast%d` = %u but spell %u does not exist, quest can't be done.",
- qinfo->GetQuestId(), j+1, id, id);
- continue;
- }
-
- if (!qinfo->RequiredNpcOrGo[j])
- {
- bool found = false;
- for (uint8 k = 0; k < MAX_SPELL_EFFECTS; ++k)
- {
- if ((spellInfo->Effects[k].Effect == SPELL_EFFECT_QUEST_COMPLETE && uint32(spellInfo->Effects[k].MiscValue) == qinfo->Id) ||
- spellInfo->Effects[k].Effect == SPELL_EFFECT_SEND_EVENT)
- {
- found = true;
- break;
- }
- }
-
- if (found)
- {
- if (!qinfo->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Spell (id: %u) have SPELL_EFFECT_QUEST_COMPLETE or SPELL_EFFECT_SEND_EVENT for quest %u and RequiredNpcOrGo%d = 0, but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT. Quest flags or RequiredNpcOrGo%d must be fixed, quest modified to enable objective.", spellInfo->Id, qinfo->Id, j+1, j+1);
-
- // this will prevent quest completing without objective
- const_cast<Quest*>(qinfo)->SetFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT);
- }
- }
- else
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `ReqSpellCast%d` = %u and RequiredNpcOrGo%d = 0 but spell %u does not have SPELL_EFFECT_QUEST_COMPLETE or SPELL_EFFECT_SEND_EVENT effect for this quest, quest can't be done.",
- qinfo->GetQuestId(), j+1, id, j+1, id);
- // no changes, quest can't be done for this requirement
- }
- }
- }
- }
-
- for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j)
- {
int32 id = qinfo->RequiredNpcOrGo[j];
if (id < 0 && !sObjectMgr->GetGameObjectTemplate(-id))
{
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 0554820364d..79d5c22e6a2 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -243,6 +243,8 @@ void WorldSession::HandleCharEnum(PreparedQueryResult result)
void WorldSession::HandleCharEnumOpcode(WorldPacket & /*recvData*/)
{
+ AntiDOS.AllowOpcode(CMSG_CHAR_ENUM, false);
+
// remove expired bans
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_EXPIRED_BANS);
CharacterDatabase.Execute(stmt);
@@ -679,6 +681,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
data << uint8(CHAR_CREATE_SUCCESS);
SendPacket(&data);
+ AntiDOS.AllowOpcode(CMSG_CHAR_ENUM, true);
std::string IP_str = GetRemoteAddress();
TC_LOG_INFO(LOG_FILTER_CHARACTER, "Account: %d (IP: %s) Create Character:[%s] (GUID: %u)", GetAccountId(), IP_str.c_str(), createInfo->Name.c_str(), newChar.GetGUIDLow());
sScriptMgr->OnPlayerCreate(&newChar);
@@ -755,6 +758,8 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData)
WorldPacket data(SMSG_CHAR_DELETE, 1);
data << uint8(CHAR_DELETE_SUCCESS);
SendPacket(&data);
+
+ AntiDOS.AllowOpcode(CMSG_CHAR_ENUM, true);
}
void WorldSession::HandlePlayerLoginOpcode(WorldPacket& recvData)
diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp
index 3fefa812489..7345dcafe92 100644
--- a/src/server/game/Quests/QuestDef.cpp
+++ b/src/server/game/Quests/QuestDef.cpp
@@ -117,30 +117,27 @@ Quest::Quest(Field* questRecord)
for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
RequiredItemCount[i] = questRecord[111+i].GetUInt16();
- for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- RequiredSpellCast[i] = questRecord[117+i].GetUInt32();
-
- // int8 Unknown0 = questRecord[121].GetUInt8();
+ // int8 Unknown0 = questRecord[117].GetUInt8();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- ObjectiveText[i] = questRecord[122+i].GetString();
+ ObjectiveText[i] = questRecord[118+i].GetString();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
- DetailsEmote[i] = questRecord[126+i].GetUInt16();
+ DetailsEmote[i] = questRecord[122+i].GetUInt16();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
- DetailsEmoteDelay[i] = questRecord[130+i].GetUInt32();
+ DetailsEmoteDelay[i] = questRecord[126+i].GetUInt32();
- EmoteOnIncomplete = questRecord[134].GetUInt16();
- EmoteOnComplete = questRecord[135].GetUInt16();
+ EmoteOnIncomplete = questRecord[130].GetUInt16();
+ EmoteOnComplete = questRecord[131].GetUInt16();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
- OfferRewardEmote[i] = questRecord[136+i].GetInt16();
+ OfferRewardEmote[i] = questRecord[132+i].GetInt16();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
- OfferRewardEmoteDelay[i] = questRecord[140+i].GetInt32();
+ OfferRewardEmoteDelay[i] = questRecord[136+i].GetInt32();
- //int32 WDBVerified = questRecord[144].GetInt32();
+ //int32 WDBVerified = questRecord[140].GetInt32();
Flags |= SpecialFlags << 20;
if (Flags & QUEST_TRINITY_FLAGS_AUTO_ACCEPT)
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index 8c2bbc192b8..c202374187f 100644
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -267,7 +267,6 @@ class Quest
uint32 RequiredSourceItemCount[QUEST_SOURCE_ITEM_IDS_COUNT];
int32 RequiredNpcOrGo[QUEST_OBJECTIVES_COUNT]; // >0 Creature <0 Gameobject
uint32 RequiredNpcOrGoCount[QUEST_OBJECTIVES_COUNT];
- uint32 RequiredSpellCast[QUEST_OBJECTIVES_COUNT];
uint32 RewardChoiceItemId[QUEST_REWARD_CHOICES_COUNT];
uint32 RewardChoiceItemCount[QUEST_REWARD_CHOICES_COUNT];
uint32 RewardItemId[QUEST_REWARDS_COUNT];
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index 5519f1d4d0e..d6e9c17cb11 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -118,7 +118,8 @@ WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8
recruiterId(recruiter),
isRecruiter(isARecruiter),
timeLastWhoCommand(0),
- _RBACData(NULL)
+ _RBACData(NULL),
+ AntiDOS(this)
{
if (sock)
{
@@ -274,13 +275,20 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
!_recvQueue.empty() && _recvQueue.peek(true) != firstDelayedPacket &&
_recvQueue.next(packet, updater))
{
- if (packet->GetOpcode() >= NUM_MSG_TYPES)
+ if (!AntiDOS.EvaluateOpcode(*packet))
+ {
+ delete packet;
+ packet = NULL;
+ KickPlayer();
+ }
+
+ if (packet && packet->GetOpcode() >= NUM_MSG_TYPES)
{
TC_LOG_ERROR(LOG_FILTER_OPCODES, "Received non-existed opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str()
, GetPlayerInfo().c_str());
sScriptMgr->OnUnknownPacketReceive(m_Socket, WorldPacket(*packet));
}
- else
+ else if (packet)
{
OpcodeHandler &opHandle = opcodeTable[packet->GetOpcode()];
try
@@ -547,6 +555,7 @@ void WorldSession::LogoutPlayer(bool save)
m_playerLogout = false;
m_playerSave = false;
m_playerRecentlyLogout = true;
+ AntiDOS.AllowOpcode(CMSG_CHAR_ENUM, true);
LogoutRequest(0);
}
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index bf79b34822d..643f74024af 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -30,6 +30,7 @@
#include "World.h"
#include "WorldPacket.h"
#include "Cryptography/BigNumber.h"
+#include "AccountMgr.h"
class Creature;
class GameObject;
@@ -911,6 +912,83 @@ class WorldSession
QueryCallback<PreparedQueryResult, CharacterCreateInfo*, true> _charCreateCallback;
QueryResultHolderFuture _charLoginCallback;
+ friend class World;
+ protected:
+ class DosProtection
+ {
+ friend class World;
+ public:
+ DosProtection(WorldSession* s) : Session(s), _policy((Policy)sWorld->getIntConfig(CONFIG_PACKET_SPOOF_POLICY)) {}
+
+ bool EvaluateOpcode(WorldPacket& p) const
+ {
+ if (IsOpcodeAllowed(p.GetOpcode()))
+ return true;
+
+ // Opcode not allowed, let the punishment begin
+ TC_LOG_INFO(LOG_FILTER_NETWORKIO, "AntiDOS: Account %u, IP: %s, sent unacceptable packet (opc: %u, size: %u)",
+ Session->GetAccountId(), Session->GetRemoteAddress().c_str(), p.GetOpcode(), (uint32)p.size());
+
+ switch (_policy)
+ {
+ case POLICY_LOG:
+ return true;
+ case POLICY_KICK:
+ TC_LOG_INFO(LOG_FILTER_NETWORKIO, "AntiDOS: Player kicked!");
+ return false;
+ case POLICY_BAN:
+ {
+ BanMode bm = (BanMode)sWorld->getIntConfig(CONFIG_PACKET_SPOOF_BANMODE);
+ int64 duration = (int64)sWorld->getIntConfig(CONFIG_PACKET_SPOOF_BANDURATION); // in seconds
+ std::string nameOrIp = "";
+ switch (bm)
+ {
+ case BAN_CHARACTER: // not supported, ban account
+ case BAN_ACCOUNT: (void)sAccountMgr->GetName(Session->GetAccountId(), nameOrIp); break;
+ case BAN_IP: nameOrIp = Session->GetRemoteAddress(); break;
+ }
+ sWorld->BanAccount(bm, nameOrIp, duration, "DOS (Packet Flooding/Spoofing", "Server: AutoDOS");
+ sLog->outInfo(LOG_FILTER_NETWORKIO, "AntiDOS: Player automatically banned for "I64FMT" seconds.", duration);
+
+ return false;
+ }
+ default: // invalid policy
+ return true;
+ }
+ }
+
+ void AllowOpcode(uint16 opcode, bool allow)
+ {
+ _isOpcodeAllowed[opcode] = allow;
+ }
+
+ protected:
+ enum Policy
+ {
+ POLICY_LOG,
+ POLICY_KICK,
+ POLICY_BAN,
+ };
+
+ bool IsOpcodeAllowed(uint16 opcode) const
+ {
+ OpcodeStatusMap::const_iterator itr = _isOpcodeAllowed.find(opcode);
+ if (itr == _isOpcodeAllowed.end())
+ return true; // No presence in the map indicates this is the first time the opcode was sent this session, so allow
+
+ return itr->second;
+ }
+
+ WorldSession* Session;
+
+ private:
+ typedef UNORDERED_MAP<uint16, bool> OpcodeStatusMap;
+ OpcodeStatusMap _isOpcodeAllowed; // could be bool array, but wouldn't be practical for game versions with non-linear opcodes
+ Policy _policy;
+
+
+ } AntiDOS;
+
private:
// private trade methods
void moveItems(Item* myItems[], Item* hisItems[]);
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 52ac2d28a41..2bc4f3a0258 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1229,6 +1229,14 @@ void World::LoadConfigSettings(bool reload)
m_float_configs[CONFIG_STATS_LIMITS_BLOCK] = sConfigMgr->GetFloatDefault("Stats.Limits.Block", 95.0f);
m_float_configs[CONFIG_STATS_LIMITS_CRIT] = sConfigMgr->GetFloatDefault("Stats.Limits.Crit", 95.0f);
+ //packet spoof punishment
+ m_int_configs[CONFIG_PACKET_SPOOF_POLICY] = sConfigMgr->GetIntDefault("PacketSpoof.Policy", (uint32)WorldSession::DosProtection::POLICY_KICK);
+ m_int_configs[CONFIG_PACKET_SPOOF_BANMODE] = sConfigMgr->GetIntDefault("PacketSpoof.BanMode", (uint32)BAN_ACCOUNT);
+ if (m_int_configs[CONFIG_PACKET_SPOOF_BANMODE] == BAN_CHARACTER || m_int_configs[CONFIG_PACKET_SPOOF_BANMODE] > BAN_IP)
+ m_int_configs[CONFIG_PACKET_SPOOF_BANMODE] = BAN_ACCOUNT;
+
+ m_int_configs[CONFIG_PACKET_SPOOF_BANDURATION] = sConfigMgr->GetIntDefault("PacketSpoof.BanDuration", 86400);
+
// call ScriptMgr if we're reloading the configuration
if (reload)
sScriptMgr->OnConfigLoad(reload);
@@ -2307,6 +2315,12 @@ void World::KickAllLess(AccountTypes sec)
BanReturn World::BanAccount(BanMode mode, std::string const& nameOrIP, std::string const& duration, std::string const& reason, std::string const& author)
{
uint32 duration_secs = TimeStringToSecs(duration);
+ return BanAccount(mode, nameOrIP, duration_secs, reason, author);
+}
+
+/// Ban an account or ban an IP address, duration is in seconds if positive, otherwise permban
+BanReturn World::BanAccount(BanMode mode, std::string const& nameOrIP, uint32 duration_secs, std::string const& reason, std::string const& author)
+{
PreparedQueryResult resultAccounts = PreparedQueryResult(NULL); //used for kicking
PreparedStatement* stmt = NULL;
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 12586ed4969..bf90b5ac01a 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -326,6 +326,9 @@ enum WorldIntConfigs
CONFIG_WINTERGRASP_BATTLETIME,
CONFIG_WINTERGRASP_NOBATTLETIME,
CONFIG_WINTERGRASP_RESTART_AFTER_CRASH,
+ CONFIG_PACKET_SPOOF_POLICY,
+ CONFIG_PACKET_SPOOF_BANMODE,
+ CONFIG_PACKET_SPOOF_BANDURATION,
INT_CONFIG_VALUE_COUNT
};
@@ -687,6 +690,7 @@ class World
void KickAll();
void KickAllLess(AccountTypes sec);
BanReturn BanAccount(BanMode mode, std::string const& nameOrIP, std::string const& duration, std::string const& reason, std::string const& author);
+ BanReturn BanAccount(BanMode mode, std::string const& nameOrIP, uint32 duration_secs, std::string const& reason, std::string const& author);
bool RemoveBanAccount(BanMode mode, std::string const& nameOrIP);
BanReturn BanCharacter(std::string const& name, std::string const& duration, std::string const& reason, std::string const& author);
bool RemoveBanCharacter(std::string const& name);
diff --git a/src/server/scripts/Commands/cs_quest.cpp b/src/server/scripts/Commands/cs_quest.cpp
index 6b7d10ff7b1..12912f68bd5 100644
--- a/src/server/scripts/Commands/cs_quest.cpp
+++ b/src/server/scripts/Commands/cs_quest.cpp
@@ -207,12 +207,7 @@ public:
int32 creature = quest->RequiredNpcOrGo[i];
uint32 creaturecount = quest->RequiredNpcOrGoCount[i];
- if (uint32 spell_id = quest->RequiredSpellCast[i])
- {
- for (uint16 z = 0; z < creaturecount; ++z)
- player->CastedCreatureOrGO(creature, 0, spell_id);
- }
- else if (creature > 0)
+ if (creature > 0)
{
if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creature))
for (uint16 z = 0; z < creaturecount; ++z)
diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp
index 46a39828afd..2a23d6d8135 100644
--- a/src/server/scripts/Spells/spell_quest.cpp
+++ b/src/server/scripts/Spells/spell_quest.cpp
@@ -1878,73 +1878,76 @@ class spell_q13086_cannons_target : public SpellScriptLoader
enum BurstAtTheSeams
{
- BURST_AT_THE_SEAMS = 52510, //Burst at the Seams
- BURST_AT_THE_SEAMS_DMG = 52508, //Damage spell
- BURST_AT_THE_SEAMS_DMG_2 = 59580, //Abomination self damage spell
- BURST_AT_THE_SEAMS_BONE = 52516, //Burst at the Seams:Bone
- BURST_AT_THE_SEAMS_MEAT = 52520, //Explode Abomination:Meat
- BURST_AT_THE_SEAMS_BMEAT = 52523, //Explode Abomination:Bloody Meat
- DRAKKARI_SKULLCRUSHER_CREDIT = 52590, //Credit for Drakkari Skullcrusher
- SUMMON_DRAKKARI_CHIEFTAIN = 52616, //Summon Drakkari Chieftain
- DRAKKARI_CHIEFTAINK_KILL_CREDIT = 52620, //Drakkari Chieftain Kill Credit
+ NPC_DRAKKARI_CHIEFTAINK = 29099,
+
+ QUEST_BURST_AT_THE_SEAMS = 12690,
+
+ SPELL_BURST_AT_THE_SEAMS = 52510, // Burst at the Seams
+ SPELL_BURST_AT_THE_SEAMS_DMG = 52508, // Damage spell
+ SPELL_BURST_AT_THE_SEAMS_DMG_2 = 59580, // Abomination self damage spell
+ SPELL_BURST_AT_THE_SEAMS_BONE = 52516, // Burst at the Seams:Bone
+ SPELL_BURST_AT_THE_SEAMS_MEAT = 52520, // Explode Abomination:Meat
+ SPELL_BURST_AT_THE_SEAMS_BMEAT = 52523, // Explode Abomination:Bloody Meat
+ SPELL_DRAKKARI_SKULLCRUSHER_CREDIT = 52590, // Credit for Drakkari Skullcrusher
+ SPELL_SUMMON_DRAKKARI_CHIEFTAIN = 52616, // Summon Drakkari Chieftain
+ SPELL_DRAKKARI_CHIEFTAINK_KILL_CREDIT = 52620 // Drakkari Chieftain Kill Credit
};
class spell_q12690_burst_at_the_seams : public SpellScriptLoader
{
-
public:
spell_q12690_burst_at_the_seams() : SpellScriptLoader("spell_q12690_burst_at_the_seams") { }
+
class spell_q12690_burst_at_the_seams_SpellScript : public SpellScript
{
PrepareSpellScript(spell_q12690_burst_at_the_seams_SpellScript);
-
- bool Validate(SpellInfo const* spellInfo) OVERRIDE
+
+ bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE
{
- if (!sSpellMgr->GetSpellInfo(BURST_AT_THE_SEAMS) || !sSpellMgr->GetSpellInfo(BURST_AT_THE_SEAMS_DMG) || !sSpellMgr->GetSpellInfo(BURST_AT_THE_SEAMS_DMG_2) || !sSpellMgr->GetSpellInfo(BURST_AT_THE_SEAMS_BONE) || !sSpellMgr->GetSpellInfo(BURST_AT_THE_SEAMS_MEAT) || !sSpellMgr->GetSpellInfo(BURST_AT_THE_SEAMS_BMEAT))
+ if (!sSpellMgr->GetSpellInfo(SPELL_BURST_AT_THE_SEAMS)
+ || !sSpellMgr->GetSpellInfo(SPELL_BURST_AT_THE_SEAMS_DMG)
+ || !sSpellMgr->GetSpellInfo(SPELL_BURST_AT_THE_SEAMS_DMG_2)
+ || !sSpellMgr->GetSpellInfo(SPELL_BURST_AT_THE_SEAMS_BONE)
+ || !sSpellMgr->GetSpellInfo(SPELL_BURST_AT_THE_SEAMS_MEAT)
+ || !sSpellMgr->GetSpellInfo(SPELL_BURST_AT_THE_SEAMS_BMEAT))
return false;
return true;
}
-
+
bool Load() OVERRIDE
{
return GetCaster()->GetTypeId() == TYPEID_UNIT;
}
-
+
void HandleKnockBack(SpellEffIndex /*effIndex*/)
{
- if (Unit* abomination = GetCaster())
+ if (Unit* creature = GetHitCreature())
{
- if (Unit* creature = GetHitCreature())
+ if (Unit* charmer = GetCaster()->GetCharmerOrOwner())
{
- if(Unit* charmer = abomination->GetCharmerOrOwner())
+ if (Player* player = charmer->ToPlayer())
{
- if (Player* player = charmer->ToPlayer())
+ if (player->GetQuestStatus(QUEST_BURST_AT_THE_SEAMS) == QUEST_STATUS_INCOMPLETE)
{
- if (player->GetQuestStatus(12690) == QUEST_STATUS_INCOMPLETE)
- {
- player->CastSpell(player, DRAKKARI_SKULLCRUSHER_CREDIT, true);
- creature->CastSpell(creature,BURST_AT_THE_SEAMS_BONE);
- creature->CastSpell(creature,BURST_AT_THE_SEAMS_MEAT);
- creature->CastSpell(creature,BURST_AT_THE_SEAMS_BMEAT);
- creature->CastSpell(creature,BURST_AT_THE_SEAMS_DMG);
- creature->CastSpell(creature,BURST_AT_THE_SEAMS_DMG_2);
- player->CastSpell(player, DRAKKARI_SKULLCRUSHER_CREDIT, true);
- uint16 count = player->GetReqKillOrCastCurrentCount(12690 /*questid*/, 29099 /*creditid*/);
- if (count % 20 == 0)
- player->CastSpell(player, SUMMON_DRAKKARI_CHIEFTAIN, true);
- }
+ creature->CastSpell(creature, SPELL_BURST_AT_THE_SEAMS_BONE, true);
+ creature->CastSpell(creature, SPELL_BURST_AT_THE_SEAMS_MEAT, true);
+ creature->CastSpell(creature, SPELL_BURST_AT_THE_SEAMS_BMEAT, true);
+ creature->CastSpell(creature, SPELL_BURST_AT_THE_SEAMS_DMG, true);
+ creature->CastSpell(creature, SPELL_BURST_AT_THE_SEAMS_DMG_2, true);
+
+ player->CastSpell(player, SPELL_DRAKKARI_SKULLCRUSHER_CREDIT, true);
+ uint16 count = player->GetReqKillOrCastCurrentCount(QUEST_BURST_AT_THE_SEAMS, NPC_DRAKKARI_CHIEFTAINK);
+ if ((count % 20) == 0)
+ player->CastSpell(player, SPELL_SUMMON_DRAKKARI_CHIEFTAIN, true);
}
}
}
}
}
-
-
+
void HandleScript(SpellEffIndex /*effIndex*/)
{
- if (Unit* abomination = GetCaster())
- if(abomination->IsAlive())
- abomination->ToCreature()->DespawnOrUnsummon(2*IN_MILLISECONDS);
+ GetCaster()->ToCreature()->DespawnOrUnsummon(2 * IN_MILLISECONDS);
}
void Register() OVERRIDE
@@ -1960,6 +1963,77 @@ class spell_q12690_burst_at_the_seams : public SpellScriptLoader
}
};
+enum EscapeFromSilverbrook
+{
+ SPELL_SUMMON_WORGEN = 48681
+};
+
+// 48682 - Escape from Silverbrook - Periodic Dummy
+class spell_q12308_escape_from_silverbrook : public SpellScriptLoader
+{
+ public:
+ spell_q12308_escape_from_silverbrook() : SpellScriptLoader("spell_q12308_escape_from_silverbrook") { }
+
+ class spell_q12308_escape_from_silverbrook_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_q12308_escape_from_silverbrook_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_WORGEN))
+ return false;
+ return true;
+ }
+
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->CastSpell(GetCaster(), SPELL_SUMMON_WORGEN, true);
+ }
+
+ void Register() OVERRIDE
+ {
+ OnEffectHit += SpellEffectFn(spell_q12308_escape_from_silverbrook_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const OVERRIDE
+ {
+ return new spell_q12308_escape_from_silverbrook_SpellScript();
+ }
+};
+
+// 48681 - Summon Silverbrook Worgen
+class spell_q12308_escape_from_silverbrook_summon_worgen : public SpellScriptLoader
+{
+ public:
+ spell_q12308_escape_from_silverbrook_summon_worgen() : SpellScriptLoader("spell_q12308_escape_from_silverbrook_summon_worgen") { }
+
+ class spell_q12308_escape_from_silverbrook_summon_worgen_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_q12308_escape_from_silverbrook_summon_worgen_SpellScript);
+
+ void ModDest(SpellEffIndex effIndex)
+ {
+ float dist = GetSpellInfo()->Effects[effIndex].CalcRadius(GetCaster());
+ float angle = (urand(0, 1) ? -1 : 1) * (frand(0.75f, 1.0f) * M_PI);
+
+ Position pos;
+ GetCaster()->GetNearPosition(pos, dist, angle);
+ GetHitDest()->Relocate(&pos);
+ }
+
+ void Register() OVERRIDE
+ {
+ OnEffectHit += SpellEffectFn(spell_q12308_escape_from_silverbrook_summon_worgen_SpellScript::ModDest, EFFECT_0, SPELL_EFFECT_SUMMON);
+ }
+ };
+
+ SpellScript* GetSpellScript() const OVERRIDE
+ {
+ return new spell_q12308_escape_from_silverbrook_summon_worgen_SpellScript();
+ }
+};
+
void AddSC_quest_spell_scripts()
{
new spell_q55_sacred_cleansing();
@@ -2007,4 +2081,6 @@ void AddSC_quest_spell_scripts()
new spell_q13011_bear_flank_master();
new spell_q13086_cannons_target();
new spell_q12690_burst_at_the_seams();
+ new spell_q12308_escape_from_silverbrook_summon_worgen();
+ new spell_q12308_escape_from_silverbrook();
}
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index c4e19e851b3..a98a4e61448 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -2794,3 +2794,39 @@ Log.Async.Enable = 0
#
###################################################################################################
+
+###################################################################################################
+#
+# Packet Spoof Protection Settings
+#
+# These settings determine which action to take when harmful packet spoofing is detected.
+#
+# PacketSpoof.Policy
+# Description: Determines the course of action when packet spoofing is detected.
+# Values: 0 - Log only (LOG_FILTER_NETWORKIO)
+# 1 - Log + kick
+# 2 - Log + kick + ban
+
+PacketSpoof.Policy = 1
+
+#
+# PacketSpoof.BanMode
+# Description: If PacketSpoof.Policy equals 2, this will determine the ban mode.
+# Values: 0 - Ban Account
+# 2 - Ban IP
+# Note: Banning by character not supported for logical reasons.
+#
+
+PacketSpoof.BanMode = 0
+
+#
+# PacketSpoof.BanDuration
+# Description: Duration of the ban in seconds. Only valid if PacketSpoof.Policy is set to 2.
+# Set to 0 for permanent ban.
+# Default: 86400 seconds (1 day)
+#
+
+PacketSpoof.BanDuration = 86400
+
+#
+################################################################################################### \ No newline at end of file