diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/game/AI/SmartScripts/SmartAI.cpp | 2 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 12 | ||||
| -rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 60 | ||||
| -rw-r--r-- | src/server/game/Handlers/CharacterHandler.cpp | 5 | ||||
| -rw-r--r-- | src/server/game/Quests/QuestDef.cpp | 21 | ||||
| -rw-r--r-- | src/server/game/Quests/QuestDef.h | 1 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSession.cpp | 15 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSession.h | 78 | ||||
| -rw-r--r-- | src/server/game/World/World.cpp | 14 | ||||
| -rw-r--r-- | src/server/game/World/World.h | 4 | ||||
| -rw-r--r-- | src/server/scripts/Commands/cs_quest.cpp | 7 | ||||
| -rw-r--r-- | src/server/scripts/Spells/spell_quest.cpp | 150 | ||||
| -rw-r--r-- | src/server/worldserver/worldserver.conf.dist | 36 |
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 |
