aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/collision/Maps/MapTree.cpp3
-rw-r--r--src/server/collision/Models/GameObjectModel.cpp3
-rw-r--r--src/server/collision/Models/GameObjectModel.h3
-rw-r--r--src/server/game/AI/CoreAI/PetAI.cpp3
-rw-r--r--src/server/game/Accounts/AccountMgr.cpp2
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp4
-rw-r--r--src/server/game/Entities/Player/Player.cpp72
-rw-r--r--src/server/game/Entities/Player/Player.h12
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp14
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp12
-rw-r--r--src/server/game/Handlers/ItemHandler.cpp13
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp12
-rw-r--r--src/server/game/Handlers/QueryHandler.cpp16
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h2
-rw-r--r--src/server/game/Server/WorldSession.cpp70
-rw-r--r--src/server/game/Server/WorldSession.h3
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp2
-rw-r--r--src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp2
-rw-r--r--src/server/scripts/Outland/zone_shadowmoon_valley.cpp39
-rw-r--r--src/server/scripts/Spells/spell_priest.cpp4
-rw-r--r--src/server/shared/Containers.h28
-rw-r--r--src/server/shared/Packets/ByteBuffer.cpp7
-rw-r--r--src/server/shared/Packets/ByteBuffer.h5
23 files changed, 185 insertions, 146 deletions
diff --git a/src/server/collision/Maps/MapTree.cpp b/src/server/collision/Maps/MapTree.cpp
index bb57079c389..d592d795125 100644
--- a/src/server/collision/Maps/MapTree.cpp
+++ b/src/server/collision/Maps/MapTree.cpp
@@ -157,8 +157,7 @@ namespace VMAP
{
float maxDist = (pos2 - pos1).magnitude();
// return false if distance is over max float, in case of cheater teleporting to the end of the universe
- if (maxDist == std::numeric_limits<float>::max() ||
- maxDist == std::numeric_limits<float>::infinity())
+ if (maxDist == std::numeric_limits<float>::max() || !std::isfinite(maxDist))
return false;
// valid map coords should *never ever* produce float overflow, but this would produce NaNs too
diff --git a/src/server/collision/Models/GameObjectModel.cpp b/src/server/collision/Models/GameObjectModel.cpp
index 1b99e282132..de97943bb37 100644
--- a/src/server/collision/Models/GameObjectModel.cpp
+++ b/src/server/collision/Models/GameObjectModel.cpp
@@ -140,6 +140,7 @@ bool GameObjectModel::initialize(const GameObject& go, const GameObjectDisplayIn
}
#endif
+ owner = &go;
return true;
}
@@ -161,7 +162,7 @@ GameObjectModel* GameObjectModel::Create(const GameObject& go)
bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask) const
{
- if (!(phasemask & ph_mask))
+ if (!(phasemask & ph_mask) || !owner->isSpawned())
return false;
float time = ray.intersectionTime(iBound);
diff --git a/src/server/collision/Models/GameObjectModel.h b/src/server/collision/Models/GameObjectModel.h
index 6088b924343..99c9b1337b3 100644
--- a/src/server/collision/Models/GameObjectModel.h
+++ b/src/server/collision/Models/GameObjectModel.h
@@ -44,8 +44,9 @@ class GameObjectModel /*, public Intersectable*/
float iInvScale;
float iScale;
VMAP::WorldModel* iModel;
+ GameObject const* owner;
- GameObjectModel() : phasemask(0), iInvScale(0), iScale(0), iModel(NULL) { }
+ GameObjectModel() : phasemask(0), iInvScale(0), iScale(0), iModel(NULL), owner(NULL) { }
bool initialize(const GameObject& go, const GameObjectDisplayInfoEntry& info);
public:
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp
index f0a75403c8c..7c640f9a66d 100644
--- a/src/server/game/AI/CoreAI/PetAI.cpp
+++ b/src/server/game/AI/CoreAI/PetAI.cpp
@@ -89,7 +89,8 @@ void PetAI::UpdateAI(uint32 diff)
if (me->GetVictim() && me->EnsureVictim()->IsAlive())
{
// is only necessary to stop casting, the pet must not exit combat
- if (me->EnsureVictim()->HasBreakableByDamageCrowdControlAura(me))
+ if (!me->GetCurrentSpell(CURRENT_CHANNELED_SPELL) && // ignore channeled spells (Pin, Seduction)
+ me->EnsureVictim()->HasBreakableByDamageCrowdControlAura(me))
{
me->InterruptNonMeleeSpells(false);
return;
diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp
index d8f61a22314..773e169e5c2 100644
--- a/src/server/game/Accounts/AccountMgr.cpp
+++ b/src/server/game/Accounts/AccountMgr.cpp
@@ -517,7 +517,7 @@ bool AccountMgr::HasPermission(uint32 accountId, uint32 permissionId, uint32 rea
return false;
}
- rbac::RBACData rbac(accountId, "", realmId);
+ rbac::RBACData rbac(accountId, "", realmId, GetSecurity(accountId));
rbac.LoadFromDB();
bool hasPermission = rbac.HasPermission(permissionId);
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index e0374db3ece..4cf7d34cc11 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -2013,6 +2013,10 @@ void GameObject::SetLootState(LootState state, Unit* unit)
m_lootStateUnitGUID = unit ? unit->GetGUID() : 0;
AI()->OnStateChanged(state, unit);
sScriptMgr->OnGameObjectLootStateChanged(this, state, unit);
+
+ if (GetGoType() == GAMEOBJECT_TYPE_DOOR) // only set collision for doors on SetGoState
+ return;
+
if (m_model)
{
bool collision = false;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index f1a1524f504..433551104b9 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -689,6 +689,8 @@ Player::Player(WorldSession* session): Unit(true)
m_areaUpdateId = 0;
m_team = 0;
+
+ m_needsZoneUpdate = false;
m_nextSave = sWorld->getIntConfig(CONFIG_INTERVAL_SAVE);
@@ -5938,32 +5940,31 @@ float Player::OCTRegenMPPerSpirit()
void Player::ApplyRatingMod(CombatRating cr, int32 value, bool apply)
{
+ float oldRating = m_baseRatingValue[cr];
m_baseRatingValue[cr]+=(apply ? value : -value);
-
// explicit affected values
- switch (cr)
- {
- case CR_HASTE_MELEE:
- {
- float RatingChange = value * GetRatingMultiplier(cr);
- ApplyAttackTimePercentMod(BASE_ATTACK, RatingChange, apply);
- ApplyAttackTimePercentMod(OFF_ATTACK, RatingChange, apply);
- break;
- }
- case CR_HASTE_RANGED:
- {
- float RatingChange = value * GetRatingMultiplier(cr);
- ApplyAttackTimePercentMod(RANGED_ATTACK, RatingChange, apply);
- break;
- }
- case CR_HASTE_SPELL:
- {
- float RatingChange = value * GetRatingMultiplier(cr);
- ApplyCastTimePercentMod(RatingChange, apply);
- break;
+ if (cr == CR_HASTE_MELEE || cr == CR_HASTE_RANGED || cr == CR_HASTE_SPELL)
+ {
+ float const mult = GetRatingMultiplier(cr);
+ float const oldVal = oldRating * mult;
+ float const newVal = m_baseRatingValue[cr] * mult;
+ switch (cr)
+ {
+ case CR_HASTE_MELEE:
+ ApplyAttackTimePercentMod(BASE_ATTACK, oldVal, false);
+ ApplyAttackTimePercentMod(OFF_ATTACK, oldVal, false);
+ ApplyAttackTimePercentMod(BASE_ATTACK, newVal, true);
+ ApplyAttackTimePercentMod(OFF_ATTACK, newVal, true);
+ break;
+ case CR_HASTE_RANGED:
+ ApplyAttackTimePercentMod(RANGED_ATTACK, oldVal, false);
+ ApplyAttackTimePercentMod(RANGED_ATTACK, newVal, true);
+ break;
+ case CR_HASTE_SPELL:
+ ApplyCastTimePercentMod(oldVal, false);
+ ApplyCastTimePercentMod(newVal, true);
+ break;
}
- default:
- break;
}
UpdateRating(cr);
@@ -6757,6 +6758,15 @@ bool Player::UpdatePosition(float x, float y, float z, float orientation, bool t
// mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING);
//AURA_INTERRUPT_FLAG_JUMP not sure
+ // Update player zone if needed
+ if (m_needsZoneUpdate)
+ {
+ uint32 newZone, newArea;
+ GetZoneAndAreaId(newZone, newArea);
+ UpdateZone(newZone, newArea);
+ m_needsZoneUpdate = false;
+ }
+
// group update
if (GetGroup())
SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POSITION);
@@ -7480,6 +7490,19 @@ void Player::UpdateArea(uint32 newArea)
}
else
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
+
+ uint32 const areaRestFlag = (GetTeam() == ALLIANCE) ? AREA_FLAG_REST_ZONE_ALLIANCE : AREA_FLAG_REST_ZONE_HORDE;
+ if (area && area->flags & areaRestFlag)
+ {
+ SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
+ SetRestType(REST_TYPE_IN_FACTION_AREA);
+ InnEnter(time(0), GetMapId(), 0, 0, 0);
+ }
+ else if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) && GetRestType() == REST_TYPE_IN_FACTION_AREA)
+ {
+ RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
+ SetRestType(REST_TYPE_NO);
+ }
}
void Player::UpdateZone(uint32 newZone, uint32 newArea)
@@ -7565,8 +7588,9 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
SetRestType(REST_TYPE_NO);
}
}
- else // Recently left a capital city
+ else if (GetRestType() != REST_TYPE_IN_FACTION_AREA) // handled in UpdateArea
{
+ // Recently left a capital city
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
SetRestType(REST_TYPE_NO);
}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 7e1d9be0f88..52674032c0a 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -729,9 +729,10 @@ class InstanceSave;
enum RestType
{
- REST_TYPE_NO = 0,
- REST_TYPE_IN_TAVERN = 1,
- REST_TYPE_IN_CITY = 2
+ REST_TYPE_NO = 0,
+ REST_TYPE_IN_TAVERN = 1,
+ REST_TYPE_IN_CITY = 2,
+ REST_TYPE_IN_FACTION_AREA = 3 // used with AREA_FLAG_REST_ZONE_*
};
enum TeleportToOptions
@@ -1674,7 +1675,8 @@ class Player : public Unit, public GridObject<Player>
void UpdatePvP(bool state, bool override=false);
void UpdateZone(uint32 newZone, uint32 newArea);
void UpdateArea(uint32 newArea);
-
+ void SetNeedsZoneUpdate(bool needsUpdate) { m_needsZoneUpdate = needsUpdate; }
+
void UpdateZoneDependentAuras(uint32 zone_id); // zones
void UpdateAreaDependentAuras(uint32 area_id); // subzones
@@ -2560,6 +2562,8 @@ class Player : public Unit, public GridObject<Player>
bool IsAlwaysDetectableFor(WorldObject const* seer) const;
uint8 m_grantableLevels;
+
+ bool m_needsZoneUpdate;
private:
// internal common parts for CanStore/StoreItem functions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index abc16256b73..8b09df988cf 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -774,7 +774,8 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
if (damagetype != NODAMAGE && damage)
{
- if (victim != this && victim->GetTypeId() == TYPEID_PLAYER) // does not support creature push_back
+ if (victim != this && victim->GetTypeId() == TYPEID_PLAYER && // does not support creature push_back
+ (!spellProto || !(spellProto->AttributesEx7 & SPELL_ATTR7_NO_PUSHBACK_ON_DAMAGE)))
{
if (damagetype != DOT)
if (Spell* spell = victim->m_currentSpells[CURRENT_GENERIC_SPELL])
@@ -1834,14 +1835,15 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
splitDamage = RoundToInterval(splitDamage, uint32(0), uint32(dmgInfo.GetDamage()));
dmgInfo.AbsorbDamage(splitDamage);
- uint32 splitted = splitDamage;
uint32 split_absorb = 0;
- DealDamageMods(caster, splitted, &split_absorb);
+ DealDamageMods(caster, splitDamage, &split_absorb);
- SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitted, schoolMask, split_absorb, 0, false, 0, false);
+ SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitDamage, schoolMask, split_absorb, 0, false, 0, false);
- CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
- DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellInfo(), false);
+ CleanDamage cleanDamage = CleanDamage(splitDamage, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
+ DealDamage(caster, splitDamage, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellInfo(), false);
+ // break 'Fear' and similar auras
+ caster->ProcDamageAndSpellFor(true, this, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_EX_NORMAL_HIT, BASE_ATTACK, (*itr)->GetSpellInfo(), splitDamage);
}
}
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index f4ea4971190..7d9d83abfde 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -243,8 +243,6 @@ 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);
@@ -681,7 +679,6 @@ 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("entities.player.character", "Account: %d (IP: %s) Create Character:[%s] (GUID: %u)", GetAccountId(), IP_str.c_str(), createInfo->Name.c_str(), newChar.GetGUIDLow());
sScriptMgr->OnPlayerCreate(&newChar);
@@ -758,8 +755,6 @@ 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)
@@ -767,6 +762,7 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket& recvData)
if (PlayerLoading() || GetPlayer() != NULL)
{
TC_LOG_ERROR("network", "Player tryes to login again, AccountId = %d", GetAccountId());
+ KickPlayer();
return;
}
@@ -1168,7 +1164,6 @@ void WorldSession::HandleCharRenameOpcode(WorldPacket& recvData)
void WorldSession::HandleChangePlayerNameOpcodeCallBack(PreparedQueryResult result, std::string const& newName)
{
- AntiDOS.AllowOpcode(CMSG_CHAR_ENUM, true);
if (!result)
{
WorldPacket data(SMSG_CHAR_RENAME, 1);
@@ -1426,8 +1421,6 @@ void WorldSession::HandleCharCustomize(WorldPacket& recvData)
stmt->setUInt32(0, GUID_LOPART(guid));
// TODO: Make async with callback
- // TODO 2: Allow opcode at end of callback
- AntiDOS.AllowOpcode(CMSG_CHAR_ENUM, true);
PreparedQueryResult result = CharacterDatabase.Query(stmt);
if (!result)
@@ -1682,8 +1675,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
uint8 playerClass = nameData->m_class;
uint8 level = nameData->m_level;
- // TO Do: Make async and allow opcode on callback
- AntiDOS.AllowOpcode(CMSG_CHAR_ENUM, true);
+ // TO Do: Make async
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_AT_LOGIN_TITLES);
stmt->setUInt32(0, lowGuid);
PreparedQueryResult result = CharacterDatabase.Query(stmt);
diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp
index c4b4b35bf37..0ca7885b82b 100644
--- a/src/server/game/Handlers/ItemHandler.cpp
+++ b/src/server/game/Handlers/ItemHandler.cpp
@@ -470,19 +470,6 @@ void WorldSession::HandleReadItem(WorldPacket& recvData)
_player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
}
-void WorldSession::HandlePageQuerySkippedOpcode(WorldPacket& recvData)
-{
- TC_LOG_DEBUG("network", "WORLD: Received CMSG_PAGE_TEXT_QUERY");
-
- uint32 itemid;
- uint64 guid;
-
- recvData >> itemid >> guid;
-
- TC_LOG_INFO("network", "Packet Info: itemid: %u guidlow: %u guidentry: %u guidhigh: %u",
- itemid, GUID_LOPART(guid), GUID_ENPART(guid), GUID_HIPART(guid));
-}
-
void WorldSession::HandleSellItemOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "WORLD: Received CMSG_SELL_ITEM");
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index df86c9b4b83..11fa89d9d6b 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -186,11 +186,6 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_WHO Message");
- time_t now = time(NULL);
- if (now - timeLastWhoCommand < 5)
- return;
- else timeLastWhoCommand = now;
-
uint32 matchcount = 0;
uint32 level_min, level_max, racemask, classmask, zones_count, str_count;
@@ -505,10 +500,9 @@ void WorldSession::HandleZoneUpdateOpcode(WorldPacket& recvData)
TC_LOG_DEBUG("network", "WORLD: Recvd ZONE_UPDATE: %u", newZone);
- // use server size data
- uint32 newzone, newarea;
- GetPlayer()->GetZoneAndAreaId(newzone, newarea);
- GetPlayer()->UpdateZone(newzone, newarea);
+ // use server side data, but only after update the player position. See Player::UpdatePosition().
+ GetPlayer()->SetNeedsZoneUpdate(true);
+
//GetPlayer()->SendInitWorldStates(true, newZone);
}
diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp
index de08392b86a..dbcfb1c4970 100644
--- a/src/server/game/Handlers/QueryHandler.cpp
+++ b/src/server/game/Handlers/QueryHandler.cpp
@@ -405,19 +405,23 @@ void WorldSession::HandleQuestPOIQuery(WorldPacket& recvData)
uint32 count;
recvData >> count; // quest count, max=25
- if (count >= MAX_QUEST_LOG_SIZE)
+ if (count > MAX_QUEST_LOG_SIZE)
{
recvData.rfinish();
return;
}
- WorldPacket data(SMSG_QUEST_POI_QUERY_RESPONSE, 4+(4+4)*count);
- data << uint32(count); // count
-
+ // Read quest ids and add the in a unordered_set so we don't send POIs for the same quest multiple times
+ std::unordered_set<uint32> questIds;
for (uint32 i = 0; i < count; ++i)
+ questIds.insert(recvData.read<uint32>()); // quest id
+
+ WorldPacket data(SMSG_QUEST_POI_QUERY_RESPONSE, 4 + (4 + 4)*questIds.size());
+ data << uint32(questIds.size()); // count
+
+ for (auto itr = questIds.begin(); itr != questIds.end(); ++itr)
{
- uint32 questId;
- recvData >> questId; // quest id
+ uint32 questId = *itr;
bool questOk = false;
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 0704c4eb9fe..fdf06a8f7e3 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -533,7 +533,7 @@ enum SpellAttr7
SPELL_ATTR7_IS_CHEAT_SPELL = 0x00000008, // 3 Cannot cast if caster doesn't have UnitFlag2 & UNIT_FLAG2_ALLOW_CHEAT_SPELLS
SPELL_ATTR7_UNK4 = 0x00000010, // 4 Only 47883 (Soulstone Resurrection) and test spell.
SPELL_ATTR7_SUMMON_PLAYER_TOTEM = 0x00000020, // 5 Only Shaman player totems.
- SPELL_ATTR7_UNK6 = 0x00000040, // 6 Dark Surge, Surge of Light, Burning Breath triggers (boss spells).
+ SPELL_ATTR7_NO_PUSHBACK_ON_DAMAGE = 0x00000040, // 6 Does not cause spell pushback on damage
SPELL_ATTR7_UNK7 = 0x00000080, // 7 66218 (Launch) spell.
SPELL_ATTR7_HORDE_ONLY = 0x00000100, // 8 Teleports, mounts and other spells.
SPELL_ATTR7_ALLIANCE_ONLY = 0x00000200, // 9 Teleports, mounts and other spells.
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index 850aecbf164..9f052b75386 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -121,7 +121,6 @@ WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8
m_TutorialsChanged(false),
recruiterId(recruiter),
isRecruiter(isARecruiter),
- timeLastWhoCommand(0),
_RBACData(NULL)
{
memset(m_Tutorials, 0, sizeof(m_Tutorials));
@@ -570,7 +569,6 @@ void WorldSession::LogoutPlayer(bool save)
m_playerLogout = false;
m_playerSave = false;
m_playerRecentlyLogout = true;
- AntiDOS.AllowOpcode(CMSG_CHAR_ENUM, true);
LogoutRequest(0);
}
@@ -1253,8 +1251,9 @@ bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) co
if (++packetCounter.amountCounter > maxPacketCounterAllowed)
{
dosTriggered = true;
- TC_LOG_WARN("network", "AntiDOS: Account %u, IP: %s, flooding packet (opc: %u, size: %u)",
- Session->GetAccountId(), Session->GetRemoteAddress().c_str(), p.GetOpcode(), (uint32)p.size());
+ TC_LOG_WARN("network", "AntiDOS: Account %u, IP: %s, Character: %s, flooding packet (opc: %s (0x%X), count: %u)",
+ Session->GetAccountId(), Session->GetRemoteAddress().c_str(), Session->GetPlayerName().c_str(),
+ opcodeTable[p.GetOpcode()].name, p.GetOpcode(), packetCounter.amountCounter);
}
// Then check if player is sending packets not allowed
@@ -1304,19 +1303,28 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
uint32 maxPacketCounterAllowed;
switch (opcode)
{
+ // These opcodes are spammed by few addons so a very high limit is required
+ case CMSG_QUEST_QUERY:
+ case CMSG_MESSAGECHAT:
case CMSG_ITEM_QUERY_SINGLE:
case CMSG_ITEM_NAME_QUERY:
- case CMSG_GUILD_QUERY:
+ case CMSG_GAMEOBJECT_QUERY:
case CMSG_NAME_QUERY:
case CMSG_PET_NAME_QUERY:
- case CMSG_GAMEOBJECT_QUERY:
case CMSG_CREATURE_QUERY:
case CMSG_NPC_TEXT_QUERY:
+ case CMSG_QUESTGIVER_STATUS_QUERY:
+ {
+ maxPacketCounterAllowed = 5000;
+ break;
+ }
+
+ case CMSG_ATTACKSTOP:
+ case CMSG_GUILD_QUERY:
case CMSG_ARENA_TEAM_QUERY:
case CMSG_TAXINODE_STATUS_QUERY:
case CMSG_TAXIQUERYAVAILABLENODES:
case CMSG_QUESTGIVER_QUERY_QUEST:
- case CMSG_QUEST_QUERY:
case CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY:
case CMSG_QUERY_QUESTS_COMPLETED:
case CMSG_QUEST_POI_QUERY:
@@ -1334,16 +1342,35 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
case MSG_QUERY_NEXT_MAIL_TIME:
case MSG_GUILD_EVENT_LOG_QUERY:
case MSG_MOVE_SET_FACING:
+ case CMSG_INSPECT:
{
- maxPacketCounterAllowed = 200;
+ maxPacketCounterAllowed = 500;
break;
}
- case CMSG_MESSAGECHAT:
+ case CMSG_REQUEST_PARTY_MEMBER_STATS:
case CMSG_WHO:
+ case CMSG_SETSHEATHED:
+ case CMSG_CONTACT_LIST:
+ case CMSG_GUILD_SET_PUBLIC_NOTE:
+ case CMSG_GUILD_SET_OFFICER_NOTE:
+ {
+ maxPacketCounterAllowed = 50;
+ break;
+ }
+
+ case CMSG_SPELLCLICK:
case CMSG_GAMEOBJ_USE:
case CMSG_GAMEOBJ_REPORT_USE:
- case CMSG_SPELLCLICK:
+ case MSG_RAID_TARGET_UPDATE:
+ case CMSG_QUESTGIVER_COMPLETE_QUEST:
+ case CMSG_PLAYER_VEHICLE_ENTER:
+ case CMSG_PETITION_SIGN:
+ {
+ maxPacketCounterAllowed = 20;
+ break;
+ }
+
case CMSG_PLAYER_LOGOUT:
case CMSG_LOGOUT_REQUEST:
case CMSG_LOGOUT_CANCEL:
@@ -1352,7 +1379,6 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
case CMSG_REQUEST_VEHICLE_NEXT_SEAT:
case CMSG_REQUEST_VEHICLE_SWITCH_SEAT:
case CMSG_TOGGLE_PVP:
- case CMSG_CONTACT_LIST:
case CMSG_ADD_FRIEND:
case CMSG_DEL_FRIEND:
case CMSG_SET_CONTACT_NOTES:
@@ -1387,7 +1413,6 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
case CMSG_REQUEST_VEHICLE_EXIT:
case CMSG_LEARN_PREVIEW_TALENTS:
case CMSG_LEARN_PREVIEW_TALENTS_PET:
- case CMSG_PLAYER_VEHICLE_ENTER:
case CMSG_CONTROLLER_EJECT_PASSENGER:
case CMSG_EQUIPMENT_SET_SAVE:
case CMSG_DELETEEQUIPMENT_SET:
@@ -1399,11 +1424,9 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
case CMSG_QUESTGIVER_CANCEL:
case CMSG_QUESTLOG_REMOVE_QUEST:
case CMSG_QUEST_CONFIRM_ACCEPT:
- case CMSG_QUESTGIVER_COMPLETE_QUEST:
case CMSG_DISMISS_CRITTER:
case CMSG_REPOP_REQUEST:
case CMSG_PETITION_BUY:
- case CMSG_PETITION_SIGN:
case CMSG_TURN_IN_PETITION:
case CMSG_COMPLETE_CINEMATIC:
case CMSG_ITEM_REFUND:
@@ -1419,14 +1442,12 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
case CMSG_GROUP_RAID_CONVERT:
case CMSG_GROUP_CHANGE_SUB_GROUP:
case CMSG_GROUP_ASSISTANT_LEADER:
- case CMSG_REQUEST_PARTY_MEMBER_STATS:
case CMSG_OPT_OUT_OF_LOOT:
case CMSG_BATTLEMASTER_JOIN_ARENA:
case CMSG_LEAVE_BATTLEFIELD:
case CMSG_REPORT_PVP_AFK:
case CMSG_DUEL_ACCEPTED:
case CMSG_DUEL_CANCELLED:
- case CMSG_SETSHEATHED:
case CMSG_CALENDAR_GET_CALENDAR:
case CMSG_CALENDAR_ADD_EVENT:
case CMSG_CALENDAR_UPDATE_EVENT:
@@ -1453,8 +1474,6 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
case CMSG_GUILD_DISBAND:
case CMSG_GUILD_LEADER:
case CMSG_GUILD_MOTD:
- case CMSG_GUILD_SET_PUBLIC_NOTE:
- case CMSG_GUILD_SET_OFFICER_NOTE:
case CMSG_GUILD_RANK:
case CMSG_GUILD_ADD_RANK:
case CMSG_GUILD_DEL_RANK:
@@ -1471,7 +1490,6 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
case MSG_SET_DUNGEON_DIFFICULTY:
case MSG_SET_RAID_DIFFICULTY:
case MSG_RANDOM_ROLL:
- case MSG_RAID_TARGET_UPDATE:
case MSG_PARTY_ASSIGNMENT:
case MSG_RAID_READY_CHECK:
{
@@ -1479,9 +1497,21 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
break;
}
+ case CMSG_SET_ACTION_BUTTON:
+ {
+ maxPacketCounterAllowed = MAX_ACTION_BUTTONS;
+ break;
+ }
+
+ case CMSG_ITEM_REFUND_INFO:
+ {
+ maxPacketCounterAllowed = PLAYER_SLOTS_COUNT;
+ break;
+ }
+
default:
{
- maxPacketCounterAllowed = 30;
+ maxPacketCounterAllowed = 100;
break;
}
}
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 7bea0ef9a85..968f5a229ba 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -32,6 +32,7 @@
#include "WorldPacket.h"
#include "Cryptography/BigNumber.h"
#include "AccountMgr.h"
+#include <unordered_set>
class Creature;
class GameObject;
@@ -728,7 +729,6 @@ class WorldSession
void HandleCompleteCinematic(WorldPacket& recvPacket);
void HandleNextCinematicCamera(WorldPacket& recvPacket);
- void HandlePageQuerySkippedOpcode(WorldPacket& recvPacket);
void HandlePageTextQueryOpcode(WorldPacket& recvPacket);
void HandleTutorialFlag (WorldPacket& recvData);
@@ -1020,7 +1020,6 @@ class WorldSession
uint32 recruiterId;
bool isRecruiter;
ACE_Based::LockedQueue<WorldPacket*, ACE_Thread_Mutex> _recvQueue;
- time_t timeLastWhoCommand;
rbac::RBACData* _RBACData;
WorldSession(WorldSession const& right) = delete;
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp
index e645dd383f2..b3a55e1fe4a 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp
@@ -26,7 +26,7 @@
#include "ScriptedCreature.h"
#include "blackrock_spire.h"
-uint32 const DragonspireRunes[7] = { GO_HALL_RUNE_1, GO_HALL_RUNE_2, GO_HALL_RUNE_3, GO_HALL_RUNE_4, GO_HALL_RUNE_5, GO_HALL_RUNE_6, GO_HALL_RUNE_7 };
+//uint32 const DragonspireRunes[7] = { GO_HALL_RUNE_1, GO_HALL_RUNE_2, GO_HALL_RUNE_3, GO_HALL_RUNE_4, GO_HALL_RUNE_5, GO_HALL_RUNE_6, GO_HALL_RUNE_7 };
uint32 const DragonspireMobs[3] = { NPC_BLACKHAND_DREADWEAVER, NPC_BLACKHAND_SUMMONER, NPC_BLACKHAND_VETERAN };
diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp
index 6fbe633dd45..a24e1d5d34f 100644
--- a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp
+++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp
@@ -143,7 +143,7 @@ uint32 m_auiSpellSummonWeapon[]=
};
const float CAPERNIAN_DISTANCE = 20.0f; //she casts away from the target
-const float KAEL_VISIBLE_RANGE = 50.0f;
+//const float KAEL_VISIBLE_RANGE = 50.0f;
const float afGravityPos[3] = {795.0f, 0.0f, 70.0f};
diff --git a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp
index ba20c7e020b..116beb3d081 100644
--- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp
+++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp
@@ -1867,13 +1867,6 @@ public:
{
npc_shadowmoon_tuber_nodeAI(Creature* creature) : ScriptedAI(creature) { }
- void Reset() override
- {
- tapped = false;
- tuberGUID = 0;
- resetTimer = 60000;
- }
-
void SetData(uint32 id, uint32 data) override
{
if (id == TYPE_BOAR && data == DATA_BOAR)
@@ -1884,49 +1877,23 @@ public:
// Despawn the tuber
if (GameObject* tuber = me->FindNearestGameObject(GO_SHADOWMOON_TUBER_MOUND, 5.0f))
{
- tuberGUID = tuber->GetGUID();
- // @Workaround: find how to properly despawn the GO
- tuber->SetPhaseMask(2, true);
+ tuber->SetLootState(GO_JUST_DEACTIVATED);
+ me->DespawnOrUnsummon();
}
}
}
void SpellHit(Unit* /*caster*/, const SpellInfo* spell) override
{
- if (!tapped && spell->Id == SPELL_WHISTLE)
+ if (spell->Id == SPELL_WHISTLE)
{
if (Creature* boar = me->FindNearestCreature(NPC_BOAR_ENTRY, 30.0f))
{
- // Disable trigger and force nearest boar to walk to him
- tapped = true;
boar->SetWalk(false);
boar->GetMotionMaster()->MovePoint(POINT_TUBER, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ());
}
}
}
-
- void UpdateAI(uint32 diff) override
- {
- if (tapped)
- {
- if (resetTimer <= diff)
- {
- // Respawn the tuber
- if (tuberGUID)
- if (GameObject* tuber = GameObject::GetGameObject(*me, tuberGUID))
- // @Workaround: find how to properly respawn the GO
- tuber->SetPhaseMask(1, true);
-
- Reset();
- }
- else
- resetTimer -= diff;
- }
- }
- private:
- bool tapped;
- uint64 tuberGUID;
- uint32 resetTimer;
};
CreatureAI* GetAI(Creature* creature) const override
diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp
index f96a30c903a..dea67b5222d 100644
--- a/src/server/scripts/Spells/spell_priest.cpp
+++ b/src/server/scripts/Spells/spell_priest.cpp
@@ -205,7 +205,7 @@ class spell_pri_divine_hymn : public SpellScriptLoader
void Register() override
{
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pri_divine_hymn_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pri_divine_hymn_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ALLY);
}
};
@@ -336,7 +336,7 @@ class spell_pri_hymn_of_hope : public SpellScriptLoader
void Register() override
{
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pri_hymn_of_hope_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pri_hymn_of_hope_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ALLY);
}
};
diff --git a/src/server/shared/Containers.h b/src/server/shared/Containers.h
index d6ba98e4ed4..9121fbe2a97 100644
--- a/src/server/shared/Containers.h
+++ b/src/server/shared/Containers.h
@@ -64,6 +64,34 @@ namespace Trinity
std::advance(it, urand(0, container.size() - 1));
return *it;
}
+
+ /**
+ * @fn bool Trinity::Containers::Intersects(Iterator first1, Iterator last1, Iterator first2, Iterator last2)
+ *
+ * @brief Checks if two SORTED containers have a common element
+ *
+ * @param first1 Iterator pointing to start of the first container
+ * @param last1 Iterator pointing to end of the first container
+ * @param first2 Iterator pointing to start of the second container
+ * @param last2 Iterator pointing to end of the second container
+ *
+ * @return true if containers have a common element, false otherwise.
+ */
+ template<class Iterator1, class Iterator2>
+ bool Intersects(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
+ {
+ while (first1 != last1 && first2 != last2)
+ {
+ if (*first1 < *first2)
+ ++first1;
+ else if (*first2 < *first1)
+ ++first2;
+ else
+ return true;
+ }
+
+ return false;
+ }
}
//! namespace Containers
}
diff --git a/src/server/shared/Packets/ByteBuffer.cpp b/src/server/shared/Packets/ByteBuffer.cpp
index b8cb5215665..f446592e922 100644
--- a/src/server/shared/Packets/ByteBuffer.cpp
+++ b/src/server/shared/Packets/ByteBuffer.cpp
@@ -27,11 +27,10 @@ ByteBufferPositionException::ByteBufferPositionException(bool add, size_t pos,
size_t size, size_t valueSize)
{
std::ostringstream ss;
- ACE_Stack_Trace trace;
ss << "Attempted to " << (add ? "put" : "get") << " value with size: "
<< valueSize << " in ByteBuffer (pos: " << pos << " size: " << size
- << ")\n\n" << trace.c_str();
+ << ")";
message().assign(ss.str());
}
@@ -40,12 +39,10 @@ ByteBufferSourceException::ByteBufferSourceException(size_t pos, size_t size,
size_t valueSize)
{
std::ostringstream ss;
- ACE_Stack_Trace trace;
ss << "Attempted to put a "
<< (valueSize > 0 ? "NULL-pointer" : "zero-sized value")
- << " in ByteBuffer (pos: " << pos << " size: " << size << ")\n\n"
- << trace.c_str();
+ << " in ByteBuffer (pos: " << pos << " size: " << size << ")";
message().assign(ss.str());
}
diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h
index dd0a9d5fdf4..9f766a72d19 100644
--- a/src/server/shared/Packets/ByteBuffer.h
+++ b/src/server/shared/Packets/ByteBuffer.h
@@ -31,6 +31,7 @@
#include <vector>
#include <cstring>
#include <time.h>
+#include <math.h>
// Root of ByteBuffer exception hierarchy
class ByteBufferException : public std::exception
@@ -241,12 +242,16 @@ class ByteBuffer
ByteBuffer &operator>>(float &value)
{
value = read<float>();
+ if (!std::isfinite(value))
+ throw ByteBufferException();
return *this;
}
ByteBuffer &operator>>(double &value)
{
value = read<double>();
+ if (!std::isfinite(value))
+ throw ByteBufferException();
return *this;
}