diff options
Diffstat (limited to 'src')
72 files changed, 440 insertions, 488 deletions
diff --git a/src/server/collision/Management/VMapManager2.cpp b/src/server/collision/Management/VMapManager2.cpp index f85fceb7b39..f9fcff96ad2 100644 --- a/src/server/collision/Management/VMapManager2.cpp +++ b/src/server/collision/Management/VMapManager2.cpp @@ -236,9 +236,11 @@ namespace VMAP { floor = info.ground_Z; ASSERT(floor < std::numeric_limits<float>::max()); + ASSERT(info.hitModel); type = info.hitModel->GetLiquidType(); // entry from LiquidType.dbc if (reqLiquidType && !(GetLiquidFlagsPtr(type) & reqLiquidType)) return false; + ASSERT(info.hitInstance); if (info.hitInstance->GetLiquidLevel(pos, info, level)) return true; } diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 4dd38face72..6586c5035ec 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -48,6 +48,7 @@ struct WMOAreaTableTripple }; typedef std::map<WMOAreaTableTripple, WMOAreaTableEntry const*> WMOAreaInfoByTripple; +typedef std::multimap<uint32, CharSectionsEntry const*> CharSectionsMap; DBCStorage <AreaTableEntry> sAreaStore(AreaTableEntryfmt); DBCStorage <AreaGroupEntry> sAreaGroupStore(AreaGroupEntryfmt); @@ -67,6 +68,8 @@ DBCStorage <BattlemasterListEntry> sBattlemasterListStore(BattlemasterListEntryf DBCStorage <BarberShopStyleEntry> sBarberShopStyleStore(BarberShopStyleEntryfmt); DBCStorage <CharStartOutfitEntry> sCharStartOutfitStore(CharStartOutfitEntryfmt); std::map<uint32, CharStartOutfitEntry const*> sCharStartOutfitMap; +DBCStorage <CharSectionsEntry> sCharSectionsStore(CharSectionsEntryfmt); +CharSectionsMap sCharSectionMap; DBCStorage <CharTitlesEntry> sCharTitlesStore(CharTitlesEntryfmt); DBCStorage <ChatChannelsEntry> sChatChannelsStore(ChatChannelsEntryfmt); DBCStorage <ChrClassesEntry> sChrClassesStore(ChrClassesEntryfmt); @@ -305,6 +308,12 @@ void LoadDBCStores(const std::string& dataPath) if (CharStartOutfitEntry const* outfit = sCharStartOutfitStore.LookupEntry(i)) sCharStartOutfitMap[outfit->Race | (outfit->Class << 8) | (outfit->Gender << 16)] = outfit; + LoadDBC(availableDbcLocales, bad_dbc_files, sCharSectionsStore, dbcPath, "CharSections.dbc"); + for (uint32 i = 0; i < sCharSectionsStore.GetNumRows(); ++i) + if (CharSectionsEntry const* entry = sCharSectionsStore.LookupEntry(i)) + if (entry->Race && ((1 << (entry->Race - 1)) & RACEMASK_ALL_PLAYABLE) != 0) //ignore Nonplayable races + sCharSectionMap.insert({ entry->GenType | (entry->Gender << 8) | (entry->Race << 16), entry }); + LoadDBC(availableDbcLocales, bad_dbc_files, sCharTitlesStore, dbcPath, "CharTitles.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sChatChannelsStore, dbcPath, "ChatChannels.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sChrClassesStore, dbcPath, "ChrClasses.dbc"); @@ -945,6 +954,18 @@ CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, ui return itr->second; } +CharSectionsEntry const* GetCharSectionEntry(uint8 race, CharSectionType genType, uint8 gender, uint8 type, uint8 color) +{ + std::pair<CharSectionsMap::const_iterator, CharSectionsMap::const_iterator> eqr = sCharSectionMap.equal_range(uint32(genType) | uint32(gender << 8) | uint32(race << 16)); + for (CharSectionsMap::const_iterator itr = eqr.first; itr != eqr.second; ++itr) + { + if (itr->second->Type == type && itr->second->Color == color) + return itr->second; + } + + return NULL; +} + /// Returns LFGDungeonEntry for a specific map and difficulty. Will return first found entry if multiple dungeons use the same map (such as Scarlet Monastery) LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty) { diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index 655de86b7e1..d955e9581ab 100644 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -69,6 +69,7 @@ PvPDifficultyEntry const* GetBattlegroundBracketByLevel(uint32 mapid, uint32 lev PvPDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattlegroundBracketId id); CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, uint8 gender); +CharSectionsEntry const* GetCharSectionEntry(uint8 race, CharSectionType genType, uint8 gender, uint8 type, uint8 color); LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty); @@ -91,6 +92,7 @@ extern DBCStorage <BarberShopStyleEntry> sBarberShopStyleStore; extern DBCStorage <BattlemasterListEntry> sBattlemasterListStore; extern DBCStorage <ChatChannelsEntry> sChatChannelsStore; extern DBCStorage <CharStartOutfitEntry> sCharStartOutfitStore; +extern DBCStorage <CharSectionsEntry> sCharSectionsStore; extern DBCStorage <CharTitlesEntry> sCharTitlesStore; extern DBCStorage <ChrClassesEntry> sChrClassesStore; extern DBCStorage <ChrRacesEntry> sChrRacesStore; diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index a6bddc7bd5e..5c784f3fe69 100644 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -647,6 +647,33 @@ struct CharStartOutfitEntry //int32 ItemInventorySlot[MAX_OUTFIT_ITEMS]; // 53-76 not required at server side }; +enum CharSectionFlags +{ + SECTION_FLAG_PLAYER = 0x01, + SECTION_FLAG_DEATH_KNIGHT = 0x04 +}; + +enum CharSectionType +{ + SECTION_TYPE_SKIN = 0, + SECTION_TYPE_FACE = 1, + SECTION_TYPE_FACIAL_HAIR = 2, + SECTION_TYPE_HAIR = 3, + SECTION_TYPE_UNDERWEAR = 4 +}; + +struct CharSectionsEntry +{ + //uint32 Id; + uint32 Race; + uint32 Gender; + uint32 GenType; + //char* TexturePath[3]; + uint32 Flags; + uint32 Type; + uint32 Color; +}; + struct CharTitlesEntry { uint32 ID; // 0, title ids, for example in Quest::GetCharTitleId() @@ -1521,7 +1548,7 @@ struct ScalingStatValuesEntry return 0; } - uint32 getFeralBonus(uint32 mask) const // removed in 3.2.x? + uint32 getFeralBonus(uint32 /*mask*/) const // removed in 3.2.x? { //if (mask & 0x00010000) return 0; // not used? return 0; diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h index 44db2a35d73..5c24e6f938a 100644 --- a/src/server/game/DataStores/DBCfmt.h +++ b/src/server/game/DataStores/DBCfmt.h @@ -33,6 +33,7 @@ char const BannedAddOnsfmt[] = "nxxxxxxxxxx"; char const BarberShopStyleEntryfmt[] = "nixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiii"; char const BattlemasterListEntryfmt[] = "niiiiiiiiixssssssssssssssssxiixx"; char const CharStartOutfitEntryfmt[] = "dbbbXiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +char const CharSectionsEntryfmt[] = "diiixxxiii"; char const CharTitlesEntryfmt[] = "nxssssssssssssssssxssssssssssssssssxi"; char const ChatChannelsEntryfmt[] = "nixssssssssssssssssxxxxxxxxxxxxxxxxxx"; char const ChrClassesEntryfmt[] = "nxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii"; diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index a2058fffeed..024002ab88f 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -780,10 +780,10 @@ void LFGMgr::GetCompatibleDungeons(LfgDungeonSet& dungeons, GuidSet const& playe } } } - + if (eraseDungeon) dungeons.erase(itDungeon); - + lockMap[guid][dungeonId] = it2->second; } } @@ -1266,6 +1266,14 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* if (player->GetMapId() == uint32(dungeon->map)) player->TeleportToBGEntryPoint(); + // in the case were we are the last in lfggroup then we must disband when porting out of the instance + if (group && group->GetMembersCount() == 1) + { + group->Disband(); + TC_LOG_DEBUG("lfg.teleport", "Player %s is last in lfggroup so we disband the group.", + player->GetName().c_str()); + } + return; } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 60cadab39fd..32fd5c53803 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -964,8 +964,6 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo) { //FIXME: outfitId not used in player creating /// @todo need more checks against packet modifications - // should check that skin, face, hair* are valid via DBC per race/class - // also do it in Player::BuildEnumData, Player::LoadFromDB Object::_Create(guidlow, 0, HIGHGUID_PLAYER); @@ -1007,6 +1005,13 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo) return false; } + if (!ValidateAppearance(createInfo->Race, createInfo->Class, createInfo->Gender, createInfo->HairStyle, createInfo->HairColor, createInfo->Face, createInfo->FacialHair, createInfo->Skin, true)) + { + TC_LOG_ERROR("entities.player", "Player::Create: Possible hacking-attempt: Account %u tried creating a character named '%s' with invalid appearance attributes - refusing to do so", + GetSession()->GetAccountId(), m_name.c_str()); + return false; + } + uint32 RaceClassGender = (createInfo->Race) | (createInfo->Class << 8) | (createInfo->Gender << 16); SetUInt32Value(UNIT_FIELD_BYTES_0, (RaceClassGender | (powertype << 24))); @@ -1979,12 +1984,29 @@ bool Player::BuildEnumData(PreparedQueryResult result, WorldPacket* data) *data << uint8(gender); // gender uint32 playerBytes = fields[5].GetUInt32(); + uint32 playerBytes2 = fields[6].GetUInt32(); + + uint16 atLoginFlags = fields[15].GetUInt16(); + + if (!ValidateAppearance(uint8(plrRace), uint8(plrClass), gender, uint8(playerBytes >> 16), uint8(playerBytes >> 24), uint8(playerBytes >> 8), uint8(playerBytes2), uint8(playerBytes))) + { + TC_LOG_ERROR("entities.player.loading", "Player %u has wrong Appearance values (Hair/Skin/Color), forcing recustomize", guid); + + if (!(atLoginFlags & AT_LOGIN_CUSTOMIZE)) + { + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); + stmt->setUInt16(0, uint16(AT_LOGIN_CUSTOMIZE)); + stmt->setUInt32(1, guid); + CharacterDatabase.Execute(stmt); + atLoginFlags |= AT_LOGIN_CUSTOMIZE; + } + } + *data << uint8(playerBytes); // skin *data << uint8(playerBytes >> 8); // face *data << uint8(playerBytes >> 16); // hair style *data << uint8(playerBytes >> 24); // hair color - uint32 playerBytes2 = fields[6].GetUInt32(); *data << uint8(playerBytes2 & 0xFF); // facial hair *data << uint8(fields[7].GetUInt8()); // level @@ -1999,7 +2021,6 @@ bool Player::BuildEnumData(PreparedQueryResult result, WorldPacket* data) uint32 charFlags = 0; uint32 playerFlags = fields[14].GetUInt32(); - uint16 atLoginFlags = fields[15].GetUInt16(); if (playerFlags & PLAYER_FLAGS_HIDE_HELM) charFlags |= CHARACTER_FLAG_HIDE_HELM; if (playerFlags & PLAYER_FLAGS_HIDE_CLOAK) @@ -17292,6 +17313,20 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) SetUInt32Value(PLAYER_BYTES_2, fields[10].GetUInt32()); SetByteValue(PLAYER_BYTES_3, 0, fields[5].GetUInt8()); SetByteValue(PLAYER_BYTES_3, 1, fields[49].GetUInt8()); + + if (!ValidateAppearance( + fields[3].GetUInt8(), // race + fields[4].GetUInt8(), // class + gender, GetByteValue(PLAYER_BYTES, 2), // hair type + GetByteValue(PLAYER_BYTES, 3), //hair color + uint8(fields[9].GetUInt32() >> 8), // face + GetByteValue(PLAYER_BYTES_2, 0), // facial hair + GetByteValue(PLAYER_BYTES, 0))) // skin color + { + TC_LOG_ERROR("entities.player", "Player %s has wrong Appearance values (Hair/Skin/Color), can't be loaded.", guid.ToString().c_str()); + return false; + } + SetUInt32Value(PLAYER_FLAGS, fields[11].GetUInt32()); SetInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, fields[48].GetUInt32()); @@ -21962,9 +21997,9 @@ void Player::SetPvP(bool state) (*itr)->SetPvP(state); } -void Player::UpdatePvP(bool state, bool override) +void Player::UpdatePvP(bool state, bool _override) { - if (!state || override) + if (!state || _override) { SetPvP(state); pvpInfo.EndTimer = 0; @@ -25050,11 +25085,11 @@ uint32 Player::CalculateTalentsPoints() const return uint32(talentPointsForLevel * sWorld->getRate(RATE_TALENT)); } -bool Player::IsKnowHowFlyIn(uint32 mapid, uint32 zone) const +bool Player::CanFlyInZone(uint32 mapid, uint32 zone) const { // continent checked in SpellInfo::CheckLocation at cast and area update uint32 v_map = GetVirtualMapForMapAndZone(mapid, zone); - return v_map != 571 || HasSpell(54197); // Cold Weather Flying + return v_map != 571 || HasSpell(54197); // 54197 = Cold Weather Flying } void Player::LearnSpellHighestRank(uint32 spellid) @@ -26947,3 +26982,57 @@ void Player::SendSupercededSpell(uint32 oldSpell, uint32 newSpell) GetSession()->SendPacket(&data); } +bool Player::ValidateAppearance(uint8 race, uint8 class_, uint8 gender, uint8 hairID, uint8 hairColor, uint8 faceID, uint8 facialHair, uint8 skinColor, bool create /*=false*/) +{ + // Check skin color + // For Skin type is always 0 + if (CharSectionsEntry const* entry = GetCharSectionEntry(race, SECTION_TYPE_SKIN, gender, 0, skinColor)) + { // Skin Color defined as Face color, too, we check skin & face in one pass + if (CharSectionsEntry const* entry2 = GetCharSectionEntry(race, SECTION_TYPE_FACE, gender, faceID, skinColor)) + { + // Check DeathKnight exclusive + if (((entry->Flags & SECTION_FLAG_DEATH_KNIGHT) || (entry2->Flags & SECTION_FLAG_DEATH_KNIGHT)) && class_ != CLASS_DEATH_KNIGHT) + return false; + if (create && !((entry->Flags & SECTION_FLAG_PLAYER) && (entry2->Flags & SECTION_FLAG_PLAYER))) + return false; + } + else + return false; + } + else + return false; + + // These combinations don't have an entry of Type SECTION_TYPE_FACIAL_HAIR, exclude them from that check + bool excludeCheck = (race == RACE_TAUREN) || (race == RACE_DRAENEI) || (gender == GENDER_FEMALE && race != RACE_NIGHTELF && race != RACE_UNDEAD_PLAYER); + + // Check Hair + if (CharSectionsEntry const* entry = GetCharSectionEntry(race, SECTION_TYPE_HAIR, gender, hairID, hairColor)) + { + if ((entry->Flags & SECTION_FLAG_DEATH_KNIGHT) && class_ != CLASS_DEATH_KNIGHT) + return false; + if (create && !(entry->Flags & SECTION_FLAG_PLAYER)) + return false; + + if (!excludeCheck) + { + if (CharSectionsEntry const* entry2 = GetCharSectionEntry(race, SECTION_TYPE_FACIAL_HAIR, gender, facialHair, hairColor)) + { + if ((entry2->Flags & SECTION_FLAG_DEATH_KNIGHT) && class_ != CLASS_DEATH_KNIGHT) + return false; + if (create && !(entry2->Flags & SECTION_FLAG_PLAYER)) + return false; + } + else + return false; + } + else + { + // @TODO: Bound checking for facialHair ID (used clientside for markings, tauren beard, etc.) + // Not present in DBC + } + } + else + return false; + + return true; +} diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 1e928c80f3c..e3a7f39b2ba 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1499,6 +1499,7 @@ class Player : public Unit, public GridObject<Player> static bool LoadPositionFromDB(uint32& mapid, float& x, float& y, float& z, float& o, bool& in_flight, ObjectGuid guid); static bool IsValidGender(uint8 Gender) { return Gender <= GENDER_FEMALE; } + static bool ValidateAppearance(uint8 race, uint8 class_, uint8 gender, uint8 hairID, uint8 hairColor, uint8 faceID, uint8 facialHair, uint8 skinColor, bool create = false); /*********************************************************/ /*** SAVE SYSTEM ***/ @@ -2135,7 +2136,7 @@ class Player : public Unit, public GridObject<Player> void SetFallInformation(uint32 time, float z); void HandleFall(MovementInfo const& movementInfo); - bool IsKnowHowFlyIn(uint32 mapid, uint32 zone) const; + bool CanFlyInZone(uint32 mapid, uint32 zone) const; void SetClientControl(Unit* target, bool allowMove); diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp index a3ed1209ce3..7b219e4dc15 100644 --- a/src/server/game/Entities/Transport/Transport.cpp +++ b/src/server/game/Entities/Transport/Transport.cpp @@ -331,6 +331,8 @@ GameObject* Transport::CreateGOPassenger(uint32 guid, GameObjectData const* data return NULL; } + ASSERT(data); + float x = data->posX; float y = data->posY; float z = data->posZ; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 3e4953a188c..5f864210e8f 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -5484,7 +5484,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere if (RandomSpells.empty()) // shouldn't happen return false; - uint8 rand_spell = irand(0, (RandomSpells.size() - 1)); + uint8 rand_spell = urand(0, (RandomSpells.size() - 1)); CastSpell(target, RandomSpells[rand_spell], true, castItem, triggeredByAura, originalCaster); for (std::vector<uint32>::iterator itr = RandomSpells.begin(); itr != RandomSpells.end(); ++itr) { @@ -5530,7 +5530,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere if (RandomSpells.empty()) // shouldn't happen return false; - uint8 rand_spell = irand(0, (RandomSpells.size() - 1)); + uint8 rand_spell = urand(0, (RandomSpells.size() - 1)); CastSpell(target, RandomSpells[rand_spell], true, castItem, triggeredByAura, originalCaster); for (std::vector<uint32>::iterator itr = RandomSpells.begin(); itr != RandomSpells.end(); ++itr) { @@ -5880,7 +5880,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere if (dummySpell->SpellIconID == 2218) { // Proc only from Abolish desease on self cast - if (procSpell->Id != 552 || victim != this || !roll_chance_i(triggerAmount)) + if (!procSpell || procSpell->Id != 552 || victim != this || !roll_chance_i(triggerAmount)) return false; triggered_spell_id = 64136; target = this; @@ -14173,6 +14173,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u uint32 Id = i->aura->GetId(); AuraApplication* aurApp = i->aura->GetApplicationOfTarget(GetGUID()); + ASSERT(aurApp); bool prepare = i->aura->CallScriptPrepareProcHandlers(aurApp, eventInfo); diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index f103537710f..e30a9601bdb 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -1253,6 +1253,9 @@ void WorldSession::HandleAlterAppearance(WorldPacket& recvData) if (bs_skinColor && (bs_skinColor->type != 3 || bs_skinColor->race != _player->getRace() || bs_skinColor->gender != _player->getGender())) return; + if (!Player::ValidateAppearance(_player->getRace(), _player->getClass(), _player->getGender(), bs_hair->hair_id, Color, uint8(_player->GetUInt32Value(PLAYER_FLAGS) >> 8), bs_facialHair->hair_id, bs_skinColor ? bs_skinColor->hair_id : 0)) + return; + GameObject* go = _player->FindNearestGameObjectOfType(GAMEOBJECT_TYPE_BARBER_CHAIR, 5.0f); if (!go) { @@ -1337,10 +1340,8 @@ void WorldSession::HandleCharCustomize(WorldPacket& recvData) >> customizeInfo.FacialHair >> customizeInfo.Face; - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_AT_LOGIN); - + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_NAME_DATA); stmt->setUInt32(0, customizeInfo.Guid.GetCounter()); - // TODO: Make async with callback PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) @@ -1350,6 +1351,29 @@ void WorldSession::HandleCharCustomize(WorldPacket& recvData) } Field* fields = result->Fetch(); + uint8 plrRace = fields[0].GetUInt8(); + uint8 plrClass = fields[1].GetUInt8(); + uint8 plrGender = fields[2].GetUInt8(); + + if (!Player::ValidateAppearance(plrRace, plrClass, plrGender, customizeInfo.HairStyle, customizeInfo.HairColor, customizeInfo.Face, customizeInfo.FacialHair, customizeInfo.Skin, true)) + { + SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo); + return; + } + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_AT_LOGIN); + + stmt->setUInt32(0, customizeInfo.Guid.GetCounter()); + // TODO: Make async with callback + result = CharacterDatabase.Query(stmt); + + if (!result) + { + SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo); + return; + } + + fields = result->Fetch(); uint32 at_loginFlags = fields[0].GetUInt16(); if (!(at_loginFlags & AT_LOGIN_CUSTOMIZE)) diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 1ff82aa7bf7..d79392177e4 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -225,6 +225,7 @@ void WorldSession::SendPacket(WorldPacket* packet) sScriptMgr->OnPacketSend(this, *packet); + TC_LOG_TRACE("network.opcode", "S->C: %s %s", GetPlayerInfo().c_str(), GetOpcodeNameForLogging(packet->GetOpcode()).c_str()); m_Socket->SendPacket(*packet); } diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 0bb864de0ed..cff423c71c6 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -28,7 +28,7 @@ using boost::asio::ip::tcp; WorldSocket::WorldSocket(tcp::socket&& socket) - : Socket(std::move(socket)), _authSeed(rand32()), _OverSpeedPings(0), _worldSession(nullptr) + : Socket(std::move(socket)), _authSeed(rand32()), _OverSpeedPings(0), _worldSession(nullptr), _authed(false) { _headerBuffer.Resize(sizeof(ClientPktHeader)); } @@ -53,7 +53,15 @@ void WorldSocket::HandleSendAuthSession() seed2.SetRand(16 * 8); packet.append(seed2.AsByteArray(16).get(), 16); // new encryption seeds - SendPacket(packet); + SendPacketAndLogOpcode(packet); +} + +void WorldSocket::OnClose() +{ + { + std::lock_guard<std::mutex> sessionGuard(_worldSessionLock); + _worldSession = nullptr; + } } void WorldSocket::ReadHandler() @@ -80,7 +88,10 @@ void WorldSocket::ReadHandler() // We just received nice new header if (!ReadHeaderHandler()) + { + CloseSocket(); return; + } } // We have full read header, now check the data payload @@ -101,7 +112,10 @@ void WorldSocket::ReadHandler() // just received fresh new payload if (!ReadDataHandler()) + { + CloseSocket(); return; + } _headerBuffer.Reset(); } @@ -121,17 +135,8 @@ bool WorldSocket::ReadHeaderHandler() if (!header->IsValidSize() || !header->IsValidOpcode()) { - if (_worldSession) - { - Player* player = _worldSession->GetPlayer(); - TC_LOG_ERROR("network", "WorldSocket::ReadHeaderHandler(): client (account: %u, char [GUID: %u, name: %s]) sent malformed packet (size: %hu, cmd: %u)", - _worldSession->GetAccountId(), player ? player->GetGUIDLow() : 0, player ? player->GetName().c_str() : "<none>", header->size, header->cmd); - } - else - TC_LOG_ERROR("network", "WorldSocket::ReadHeaderHandler(): client %s sent malformed packet (size: %hu, cmd: %u)", - GetRemoteIpAddress().to_string().c_str(), header->size, header->cmd); - - CloseSocket(); + TC_LOG_ERROR("network", "WorldSocket::ReadHeaderHandler(): client %s sent malformed packet (size: %hu, cmd: %u)", + GetRemoteIpAddress().to_string().c_str(), header->size, header->cmd); return false; } @@ -151,28 +156,32 @@ bool WorldSocket::ReadDataHandler() if (sPacketLog->CanLogPacket()) sPacketLog->LogPacket(packet, CLIENT_TO_SERVER, GetRemoteIpAddress(), GetRemotePort()); - TC_LOG_TRACE("network.opcode", "C->S: %s %s", (_worldSession ? _worldSession->GetPlayerInfo() : GetRemoteIpAddress().to_string()).c_str(), GetOpcodeNameForLogging(opcode).c_str()); + std::unique_lock<std::mutex> sessionGuard(_worldSessionLock, std::defer_lock); switch (opcode) { case CMSG_PING: - HandlePing(packet); - break; + LogOpcodeText(opcode, sessionGuard); + return HandlePing(packet); case CMSG_AUTH_SESSION: - if (_worldSession) + LogOpcodeText(opcode, sessionGuard); + if (_authed) { - TC_LOG_ERROR("network", "WorldSocket::ProcessIncoming: received duplicate CMSG_AUTH_SESSION from %s", _worldSession->GetPlayerInfo().c_str()); - break; + // locking just to safely log offending user is probably overkill but we are disconnecting him anyway + if (sessionGuard.try_lock()) + TC_LOG_ERROR("network", "WorldSocket::ProcessIncoming: received duplicate CMSG_AUTH_SESSION from %s", _worldSession->GetPlayerInfo().c_str()); + return false; } HandleAuthSession(packet); break; case CMSG_KEEP_ALIVE: - TC_LOG_DEBUG("network", "%s", GetOpcodeNameForLogging(opcode).c_str()); - sScriptMgr->OnPacketReceive(_worldSession, packet); + LogOpcodeText(opcode, sessionGuard); break; default: { + sessionGuard.lock(); + LogOpcodeText(opcode, sessionGuard); if (!_worldSession) { TC_LOG_ERROR("network.opcode", "ProcessIncoming: Client not authed opcode = %u", uint32(opcode)); @@ -193,7 +202,26 @@ bool WorldSocket::ReadDataHandler() return true; } -void WorldSocket::SendPacket(WorldPacket& packet) +void WorldSocket::LogOpcodeText(uint16 opcode, std::unique_lock<std::mutex> const& guard) const +{ + if (!guard) + { + TC_LOG_TRACE("network.opcode", "C->S: %s %s", GetRemoteIpAddress().to_string().c_str(), GetOpcodeNameForLogging(opcode).c_str()); + } + else + { + TC_LOG_TRACE("network.opcode", "C->S: %s %s", (_worldSession ? _worldSession->GetPlayerInfo() : GetRemoteIpAddress().to_string()).c_str(), + GetOpcodeNameForLogging(opcode).c_str()); + } +} + +void WorldSocket::SendPacketAndLogOpcode(WorldPacket const& packet) +{ + TC_LOG_TRACE("network.opcode", "S->C: %s %s", GetRemoteIpAddress().to_string().c_str(), GetOpcodeNameForLogging(packet.GetOpcode()).c_str()); + SendPacket(packet); +} + +void WorldSocket::SendPacket(WorldPacket const& packet) { if (!IsOpen()) return; @@ -201,8 +229,6 @@ void WorldSocket::SendPacket(WorldPacket& packet) if (sPacketLog->CanLogPacket()) sPacketLog->LogPacket(packet, SERVER_TO_CLIENT, GetRemoteIpAddress(), GetRemotePort()); - TC_LOG_TRACE("network.opcode", "S->C: %s %s", (_worldSession ? _worldSession->GetPlayerInfo() : GetRemoteIpAddress().to_string()).c_str(), GetOpcodeNameForLogging(packet.GetOpcode()).c_str()); - ServerPktHeader header(packet.size() + 2, packet.GetOpcode()); std::unique_lock<std::mutex> guard(_writeLock); @@ -459,6 +485,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket) // At this point, we can safely hook a successful login sScriptMgr->OnAccountLogin(id); + _authed = true; _worldSession = new WorldSession(id, shared_from_this(), AccountTypes(security), expansion, mutetime, locale, recruiter, isRecruiter); _worldSession->LoadGlobalAccountData(); _worldSession->LoadTutorialsData(); @@ -477,10 +504,10 @@ void WorldSocket::SendAuthResponseError(uint8 code) WorldPacket packet(SMSG_AUTH_RESPONSE, 1); packet << uint8(code); - SendPacket(packet); + SendPacketAndLogOpcode(packet); } -void WorldSocket::HandlePing(WorldPacket& recvPacket) +bool WorldSocket::HandlePing(WorldPacket& recvPacket) { uint32 ping; uint32 latency; @@ -509,13 +536,14 @@ void WorldSocket::HandlePing(WorldPacket& recvPacket) if (maxAllowed && _OverSpeedPings > maxAllowed) { + std::unique_lock<std::mutex> sessionGuard(_worldSessionLock); + if (_worldSession && !_worldSession->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_OVERSPEED_PING)) { TC_LOG_ERROR("network", "WorldSocket::HandlePing: %s kicked for over-speed pings (address: %s)", _worldSession->GetPlayerInfo().c_str(), GetRemoteIpAddress().to_string().c_str()); - CloseSocket(); - return; + return false; } } } @@ -523,20 +551,23 @@ void WorldSocket::HandlePing(WorldPacket& recvPacket) _OverSpeedPings = 0; } - if (_worldSession) { - _worldSession->SetLatency(latency); - _worldSession->ResetClientTimeDelay(); - } - else - { - TC_LOG_ERROR("network", "WorldSocket::HandlePing: peer sent CMSG_PING, but is not authenticated or got recently kicked, address = %s", GetRemoteIpAddress().to_string().c_str()); + std::lock_guard<std::mutex> sessionGuard(_worldSessionLock); - CloseSocket(); - return; + if (_worldSession) + { + _worldSession->SetLatency(latency); + _worldSession->ResetClientTimeDelay(); + } + else + { + TC_LOG_ERROR("network", "WorldSocket::HandlePing: peer sent CMSG_PING, but is not authenticated or got recently kicked, address = %s", GetRemoteIpAddress().to_string().c_str()); + return false; + } } WorldPacket packet(SMSG_PONG, 4); packet << ping; - return SendPacket(packet); + SendPacketAndLogOpcode(packet); + return true; } diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h index 89c335662a8..0f6acd0d72c 100644 --- a/src/server/game/Server/WorldSocket.h +++ b/src/server/game/Server/WorldSocket.h @@ -55,19 +55,25 @@ public: void Start() override; - void SendPacket(WorldPacket& packet); + void SendPacket(WorldPacket const& packet); protected: + void OnClose() override; void ReadHandler() override; bool ReadHeaderHandler(); bool ReadDataHandler(); private: + /// writes network.opcode log + /// accessing WorldSession is not threadsafe, only do it when holding _worldSessionLock + void LogOpcodeText(uint16 opcode, std::unique_lock<std::mutex> const& guard) const; + /// sends and logs network.opcode without accessing WorldSession + void SendPacketAndLogOpcode(WorldPacket const& packet); void HandleSendAuthSession(); void HandleAuthSession(WorldPacket& recvPacket); void SendAuthResponseError(uint8 code); - void HandlePing(WorldPacket& recvPacket); + bool HandlePing(WorldPacket& recvPacket); uint32 _authSeed; AuthCrypt _authCrypt; @@ -75,7 +81,9 @@ private: std::chrono::steady_clock::time_point _LastPingTime; uint32 _OverSpeedPings; + std::mutex _worldSessionLock; WorldSession* _worldSession; + bool _authed; MessageBuffer _headerBuffer; MessageBuffer _packetBuffer; diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index b1cb7d51b35..7651278346f 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -5977,7 +5977,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c if (isAreaAura) damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()) * caster->SpellDamagePctDone(target, m_spellInfo, DOT); else - damage = std::max(int32(damage * GetDonePct()), 0); + damage = std::max(int32(damage * GetDonePct()), 0); damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()); diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 862521a068c..75a48e36ded 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1482,12 +1482,16 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a case SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED: case SPELL_AURA_FLY: { - if (player && !player->IsKnowHowFlyIn(map_id, zone_id)) - return SPELL_FAILED_INCORRECT_AREA; + SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(Id); + for (SkillLineAbilityMap::const_iterator skillIter = bounds.first; skillIter != bounds.second; ++skillIter) + { + if (skillIter->second->skillId == SKILL_MOUNTS) + if (player && !player->CanFlyInZone(map_id, zone_id)) + return SPELL_FAILED_INCORRECT_AREA; + } } } } - return SPELL_CAST_OK; } diff --git a/src/server/scripts/Commands/cs_account.cpp b/src/server/scripts/Commands/cs_account.cpp index c6ddd73addd..5668c20d6b0 100644 --- a/src/server/scripts/Commands/cs_account.cpp +++ b/src/server/scripts/Commands/cs_account.cpp @@ -667,7 +667,7 @@ public: if (isAccountNameGiven) { targetAccountName = arg1; - if (!AccountMgr::normalizeString(targetAccountName)) + if (!AccountMgr::normalizeString(targetAccountName) || !AccountMgr::GetId(targetAccountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, targetAccountName.c_str()); handler->SetSentErrorMessage(true); diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 52cc20b9d3b..0b74eb6bee7 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -1980,7 +1980,7 @@ public: PreparedStatement *stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_MUTE_INFO); stmt->setUInt32(0, accountId); PreparedQueryResult result = LoginDatabase.Query(stmt); - + if (!result) { handler->PSendSysMessage(LANG_COMMAND_MUTEHISTORY_EMPTY, accountName); @@ -1991,16 +1991,16 @@ public: do { Field* fields = result->Fetch(); - + // we have to manually set the string for mutedate time_t sqlTime = fields[0].GetUInt32(); tm timeinfo; char buffer[80]; - + // set it to string localtime_r(&sqlTime, &timeinfo); strftime(buffer, sizeof(buffer),"%Y-%m-%d %I:%M%p", &timeinfo); - + handler->PSendSysMessage(LANG_COMMAND_MUTEHISTORY_OUTPUT, buffer, fields[1].GetUInt32(), fields[2].GetCString(), fields[3].GetCString()); } while (result->NextRow()); return true; diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp index 5e83c0c8653..8965b64767a 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp @@ -126,7 +126,7 @@ public: if (dist(xn, yn, xh, yh) >= dist(xn, yn, xp, yp) || dist(xp, yp, xh, yh) >= dist(xn, yn, xp, yp)) return false; // check distance from the beam - return (abs((xn-xp)*yh+(yp-yn)*xh-xn*yp+xp*yn)/dist(xn, yn, xp, yp) < 1.5f); + return (std::abs((xn-xp)*yh+(yp-yn)*xh-xn*yp+xp*yn)/dist(xn, yn, xp, yp) < 1.5f); } float dist(float xa, float ya, float xb, float yb) // auxiliary method for distance diff --git a/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp b/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp index 1302c618e6f..e3ab206ac21 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp @@ -268,7 +268,7 @@ public: return ObjectGuid::Empty; } - void Load(char const* chrIn) + void Load(char const* chrIn) override { if (!chrIn) { diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp index b21b2f8a73c..3df07562d50 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp @@ -1657,7 +1657,7 @@ public: { npc_the_lich_king_tirion_dawnAI(Creature* creature) : ScriptedAI(creature) { Reset(); } void Reset() override { } - void AttackStart(Unit* /*who*/) { } // very sample, just don't make them aggreesive override + void AttackStart(Unit* /*who*/) override { } // very sample, just don't make them aggreesive void UpdateAI(uint32 /*diff*/) override { } void JustDied(Unit* /*killer*/) override { } }; diff --git a/src/server/scripts/EasternKingdoms/ShadowfangKeep/instance_shadowfang_keep.cpp b/src/server/scripts/EasternKingdoms/ShadowfangKeep/instance_shadowfang_keep.cpp index be544449b67..a085463f7ce 100644 --- a/src/server/scripts/EasternKingdoms/ShadowfangKeep/instance_shadowfang_keep.cpp +++ b/src/server/scripts/EasternKingdoms/ShadowfangKeep/instance_shadowfang_keep.cpp @@ -236,7 +236,7 @@ public: OUT_LOAD_INST_DATA_COMPLETE; } - void Update(uint32 uiDiff) + void Update(uint32 uiDiff) override { if (GetData(TYPE_FENRUS) != DONE) return; diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp index 1a98c081570..a9abb2c045d 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp @@ -694,7 +694,7 @@ class boss_gazakroth : public CreatureScript public: boss_gazakroth() : CreatureScript("boss_gazakroth") { } - + struct boss_gazakrothAI : public boss_hexlord_addAI { boss_gazakrothAI(Creature* creature) : boss_hexlord_addAI(creature) @@ -706,7 +706,7 @@ class boss_gazakroth : public CreatureScript { firebolt_timer = 2 * IN_MILLISECONDS; } - + void Reset() override { Initialize(); diff --git a/src/server/scripts/EasternKingdoms/zone_arathi_highlands.cpp b/src/server/scripts/EasternKingdoms/zone_arathi_highlands.cpp index 7c4190a648d..ac261f29287 100644 --- a/src/server/scripts/EasternKingdoms/zone_arathi_highlands.cpp +++ b/src/server/scripts/EasternKingdoms/zone_arathi_highlands.cpp @@ -114,7 +114,7 @@ class npc_professor_phizzlethorpe : public CreatureScript Talk(SAY_AGGRO); } - void sQuestAccept(Player* player, Quest const* quest) + void sQuestAccept(Player* player, Quest const* quest) override { if (quest->GetQuestId() == QUEST_SUNKEN_TREASURE) { diff --git a/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp b/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp index a29bb9b75b3..5b63c509eaa 100644 --- a/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp +++ b/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp @@ -75,7 +75,7 @@ public: summoned->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); } - void sQuestAccept(Player* player, Quest const* quest) + void sQuestAccept(Player* player, Quest const* quest) override { if (quest->GetQuestId() == QUEST_RESQUE_OOX_09) { diff --git a/src/server/scripts/EasternKingdoms/zone_undercity.cpp b/src/server/scripts/EasternKingdoms/zone_undercity.cpp index ca281bab60a..d7d06a2e3ab 100644 --- a/src/server/scripts/EasternKingdoms/zone_undercity.cpp +++ b/src/server/scripts/EasternKingdoms/zone_undercity.cpp @@ -50,7 +50,7 @@ enum Sylvanas SAY_SUNSORROW_WHISPER = 0, SOUND_CREDIT = 10896, - + NPC_HIGHBORNE_LAMENTER = 21628, NPC_HIGHBORNE_BUNNY = 21641, NPC_AMBASSADOR_SUNSORROW = 16287, diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp index f672871922a..b5d2931377f 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp @@ -421,7 +421,7 @@ public: gossipStep = 0; } - void AttackStart(Unit* who) + void AttackStart(Unit* who) override { if (who && !who->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC)) npc_escortAI::AttackStart(who); diff --git a/src/server/scripts/Kalimdor/RazorfenKraul/instance_razorfen_kraul.cpp b/src/server/scripts/Kalimdor/RazorfenKraul/instance_razorfen_kraul.cpp index 2b00254167d..d8966ec76c1 100644 --- a/src/server/scripts/Kalimdor/RazorfenKraul/instance_razorfen_kraul.cpp +++ b/src/server/scripts/Kalimdor/RazorfenKraul/instance_razorfen_kraul.cpp @@ -76,7 +76,7 @@ public: } } - void Update(uint32 /*diff*/) + void Update(uint32 /*diff*/) override { if (WardKeeperDeath == WARD_KEEPERS_NR) if (GameObject* go = instance->GetGameObject(DoorWardGUID)) diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp index f8873b06a75..d16a86f350f 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp @@ -57,7 +57,7 @@ class instance_ruins_of_ahnqiraj : public InstanceMapScript } } - bool SetBossState(uint32 bossId, EncounterState state) + bool SetBossState(uint32 bossId, EncounterState state) override { if (!InstanceScript::SetBossState(bossId, state)) return false; diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp index 50fd94e66ee..65ffb7fd696 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp @@ -99,7 +99,7 @@ struct boss_twinemperorsAI : public ScriptedAI uint32 EnrageTimer; virtual bool IAmVeklor() = 0; - virtual void Reset() = 0; + virtual void Reset() override = 0; virtual void CastSpellOnBug(Creature* target) = 0; void TwinReset() @@ -400,7 +400,7 @@ public: struct boss_veknilashAI : public boss_twinemperorsAI { - bool IAmVeklor() {return false;} + bool IAmVeklor() override {return false;} boss_veknilashAI(Creature* creature) : boss_twinemperorsAI(creature) { Initialize(); @@ -425,7 +425,7 @@ public: me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); } - void CastSpellOnBug(Creature* target) + void CastSpellOnBug(Creature* target) override { target->setFaction(14); target->AI()->AttackStart(me->getThreatManager().getHostilTarget()); @@ -488,7 +488,7 @@ public: struct boss_veklorAI : public boss_twinemperorsAI { - bool IAmVeklor() {return true;} + bool IAmVeklor() override {return true;} boss_veklorAI(Creature* creature) : boss_twinemperorsAI(creature) { Initialize(); @@ -516,7 +516,7 @@ public: me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); } - void CastSpellOnBug(Creature* target) + void CastSpellOnBug(Creature* target) override { target->setFaction(14); target->AddAura(SPELL_EXPLODEBUG, target); diff --git a/src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp b/src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp index 244261a86c1..46e831b0f83 100644 --- a/src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp +++ b/src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp @@ -220,7 +220,7 @@ public: }; } - virtual void Update(uint32 diff) + virtual void Update(uint32 diff) override { switch (PyramidPhase) { diff --git a/src/server/scripts/Kalimdor/zone_ashenvale.cpp b/src/server/scripts/Kalimdor/zone_ashenvale.cpp index 76b43729517..b8e6bfb85e8 100644 --- a/src/server/scripts/Kalimdor/zone_ashenvale.cpp +++ b/src/server/scripts/Kalimdor/zone_ashenvale.cpp @@ -24,7 +24,6 @@ SDCategory: Ashenvale Forest EndScriptData */ /* ContentData -npc_torek npc_ruul_snowhoof EndContentData */ @@ -34,132 +33,6 @@ EndContentData */ #include "Player.h" /*#### -# npc_torek -####*/ - -enum Torek -{ - SAY_READY = 0, - SAY_MOVE = 1, - SAY_PREPARE = 2, - SAY_WIN = 3, - SAY_END = 4, - SPELL_REND = 11977, - SPELL_THUNDERCLAP = 8078, - QUEST_TOREK_ASSULT = 6544, - NPC_SPLINTERTREE_RAIDER = 12859, - NPC_DURIEL = 12860, - NPC_SILVERWING_SENTINEL = 12896, - NPC_SILVERWING_WARRIOR = 12897, - FACTION_QUEST = 113 -}; - -class npc_torek : public CreatureScript -{ -public: - npc_torek() : CreatureScript("npc_torek") { } - - struct npc_torekAI : public npc_escortAI - { - npc_torekAI(Creature* creature) : npc_escortAI(creature) - { - Initialize(); - } - - void Initialize() - { - rend_Timer = 5000; - thunderclap_Timer = 8000; - _completed = false; - } - - void Reset() override - { - Initialize(); - } - - void EnterCombat(Unit* /*who*/) override { } - - void JustSummoned(Creature* summoned) override - { - summoned->AI()->AttackStart(me); - } - - void sQuestAccept(Player* player, Quest const* quest) - { - if (quest->GetQuestId() == QUEST_TOREK_ASSULT) - { - /// @todo find companions, make them follow Torek, at any time (possibly done by core/database in future?) - Talk(SAY_READY, player); - me->setFaction(FACTION_QUEST); - npc_escortAI::Start(true, true, player->GetGUID()); - } - } - - void WaypointReached(uint32 waypointId) override - { - if (Player* player = GetPlayerForEscort()) - { - switch (waypointId) - { - case 1: - Talk(SAY_MOVE, player); - break; - case 8: - Talk(SAY_PREPARE, player); - break; - case 19: - /// @todo verify location and creatures amount. - me->SummonCreature(NPC_DURIEL, 1776.73f, -2049.06f, 109.83f, 1.54f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - me->SummonCreature(NPC_SILVERWING_SENTINEL, 1774.64f, -2049.41f, 109.83f, 1.40f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - me->SummonCreature(NPC_SILVERWING_WARRIOR, 1778.73f, -2049.50f, 109.83f, 1.67f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - break; - case 20: - Talk(SAY_WIN, player); - _completed = true; - player->GroupEventHappens(QUEST_TOREK_ASSULT, me); - break; - case 21: - Talk(SAY_END, player); - break; - } - } - } - - void UpdateAI(uint32 diff) override - { - npc_escortAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; - - if (rend_Timer <= diff) - { - DoCastVictim(SPELL_REND); - rend_Timer = 20000; - } else rend_Timer -= diff; - - if (thunderclap_Timer <= diff) - { - DoCast(me, SPELL_THUNDERCLAP); - thunderclap_Timer = 30000; - } else thunderclap_Timer -= diff; - } - - private: - uint32 rend_Timer; - uint32 thunderclap_Timer; - bool _completed; - - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_torekAI(creature); - } -}; - -/*#### # npc_ruul_snowhoof ####*/ @@ -169,6 +42,7 @@ enum RuulSnowhoof NPC_THISTLEFUR_TOTEMIC = 3922, NPC_THISTLEFUR_PATHFINDER = 3926, QUEST_FREEDOM_TO_RUUL = 6482, + FACTION_QUEST = 113, GO_CAGE = 178147 }; @@ -204,7 +78,7 @@ public: summoned->AI()->AttackStart(me); } - void sQuestAccept(Player* player, Quest const* quest) + void sQuestAccept(Player* player, Quest const* quest) override { if (quest->GetQuestId() == QUEST_FREEDOM_TO_RUUL) { @@ -346,7 +220,7 @@ public: summoned->AI()->AttackStart(me); } - void sQuestAccept(Player* player, Quest const* quest) + void sQuestAccept(Player* player, Quest const* quest) override { if (quest->GetQuestId() == QUEST_VORSHA) { @@ -472,7 +346,6 @@ class go_naga_brazier : public GameObjectScript void AddSC_ashenvale() { - new npc_torek(); new npc_ruul_snowhoof(); new npc_muglash(); new go_naga_brazier(); diff --git a/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp b/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp index 1eb600cce99..5c9a57acec7 100644 --- a/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp +++ b/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp @@ -351,7 +351,7 @@ public: Talk(SAY_AGGRO, who); } - void sQuestAccept(Player* player, Quest const* quest) + void sQuestAccept(Player* player, Quest const* quest) override { if (quest->GetQuestId() == QUEST_A_CRY_FOR_SAY_HELP) { diff --git a/src/server/scripts/Kalimdor/zone_winterspring.cpp b/src/server/scripts/Kalimdor/zone_winterspring.cpp index 194daf21807..ec1291c6d18 100644 --- a/src/server/scripts/Kalimdor/zone_winterspring.cpp +++ b/src/server/scripts/Kalimdor/zone_winterspring.cpp @@ -451,7 +451,7 @@ public: } } - void JustDidDialogueStep(int32 entry) + void JustDidDialogueStep(int32 entry) override { switch (entry) { @@ -550,7 +550,7 @@ public: } } - Creature* GetSpeakerByEntry(int32 entry) + Creature* GetSpeakerByEntry(int32 entry) override { switch (entry) { diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp index 1482e884614..bb190e94cc8 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp @@ -108,7 +108,7 @@ class boss_prince_taldaram : public CreatureScript events.ScheduleEvent(EVENT_CONJURE_FLAME_SPHERES, 5000); } - void JustSummoned(Creature* summon) + void JustSummoned(Creature* summon) override { BossAI::JustSummoned(summon); diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp index ec668952a68..3130bf20a0c 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp @@ -44,7 +44,7 @@ class instance_ruby_sanctum : public InstanceMapScript BaltharusSharedHealth = 0; } - void OnPlayerEnter(Player* /*player*/) + void OnPlayerEnter(Player* /*player*/) override { if (!GetGuidData(DATA_HALION_CONTROLLER) && GetBossState(DATA_HALION) != DONE && GetBossState(DATA_GENERAL_ZARITHRIAN) == DONE) { diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp index 927ebfbc55c..12a745a34bc 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp @@ -2412,14 +2412,14 @@ enum QuelDelarMisc Position const QuelDelarCenterPos = { 5309.259f, 2006.390f, 718.046f, 0.0f }; Position const QuelDelarSummonPos = { 5298.473f, 1994.852f, 709.424f, 3.979351f }; Position const QuelDelarMovement[] = -{ +{ { 5292.870f, 1998.950f, 718.046f, 0.0f }, { 5295.819f, 1991.912f, 707.707f, 0.0f }, { 5295.301f, 1989.782f, 708.696f, 0.0f } }; Position const UtherQuelDelarMovement[] = -{ +{ { 5336.830f, 1981.700f, 709.319f, 0.0f }, { 5314.350f, 1993.440f, 707.726f, 0.0f } }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp index 5f27830fd07..15bdedc75db 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp @@ -1873,7 +1873,7 @@ class spell_igb_rocket_pack_useable : public SpellScriptLoader { PrepareAuraScript(spell_igb_rocket_pack_useable_AuraScript); - bool Load() + bool Load() override { return GetOwner()->GetInstanceScript() != nullptr; } @@ -2001,7 +2001,7 @@ class spell_igb_cannon_blast : public SpellScriptLoader { PrepareSpellScript(spell_igb_cannon_blast_SpellScript); - bool Load() + bool Load() override { return GetCaster()->GetTypeId() == TYPEID_UNIT; } @@ -2343,7 +2343,7 @@ class spell_igb_gunship_fall_teleport : public SpellScriptLoader { PrepareSpellScript(spell_igb_gunship_fall_teleport_SpellScript); - bool Load() + bool Load() override { return GetCaster()->GetInstanceScript() != nullptr; } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index f2236061f88..61848070170 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -317,7 +317,7 @@ class instance_icecrown_citadel : public InstanceMapScript } // Weekly quest spawn prevention - uint32 GetCreatureEntry(uint32 /*guidLow*/, CreatureData const* data) + uint32 GetCreatureEntry(uint32 /*guidLow*/, CreatureData const* data) override { uint32 entry = data->id; switch (entry) diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp index 173c6618cb0..3a431ab3ac0 100644 --- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp +++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp @@ -564,7 +564,7 @@ class instance_naxxramas : public InstanceMapScript return true; } - bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target = NULL*/, uint32 /*miscvalue1 = 0*/) + bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target = NULL*/, uint32 /*miscvalue1 = 0*/) override { switch (criteria_id) { diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp index 74be65c62c2..41645a6ebb8 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp @@ -78,7 +78,7 @@ public: frenzy = false; } - void Reset() + void Reset() override { BossAI::Reset(); Initialize(); diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp index 384694cdd40..453423bd287 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp @@ -197,7 +197,7 @@ public: ++_healthAmountModifier; } } - + private: uint32 _healthAmountModifier; bool _isIntroDone; diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp index 536cae08483..3853b0aedfc 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp @@ -89,7 +89,7 @@ class boss_volkhan : public CreatureScript { public: boss_volkhan() : CreatureScript("boss_volkhan") { } - + struct boss_volkhanAI : public BossAI { boss_volkhanAI(Creature* creature) : BossAI(creature, DATA_VOLKHAN) @@ -104,7 +104,7 @@ public: m_bCanShatterGolem = false; m_uiDelay_Timer = 1000; m_uiSummonPhase = 0; - GolemsShattered = 0; + GolemsShattered = 0; m_uiHealthAmountModifier = 1; } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp index 4841950d9d3..64403ad40ca 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp @@ -458,7 +458,7 @@ class spell_general_vezax_mark_of_the_faceless : public SpellScriptLoader { PrepareAuraScript(spell_general_vezax_mark_of_the_faceless_AuraScript); - bool Validate(SpellInfo const* /*spellInfo*/) + bool Validate(SpellInfo const* /*spellInfo*/) override { if (!sSpellMgr->GetSpellInfo(SPELL_MARK_OF_THE_FACELESS_DAMAGE)) return false; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index 49ed9609a03..ca3ea3a60ed 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp @@ -448,7 +448,7 @@ class instance_ulduar : public InstanceMapScript } } - void OnGameObjectCreate(GameObject* gameObject) + void OnGameObjectCreate(GameObject* gameObject) override { switch (gameObject->GetEntry()) { diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp index 571f73ea628..483beda43ee 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp @@ -141,7 +141,7 @@ class boss_ingvar_the_plunderer : public CreatureScript damage = 0; } - void DoAction(int32 actionId) + void DoAction(int32 actionId) override { if (actionId == ACTION_START_PHASE_2) StartZombiePhase(); diff --git a/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp index a462c68e084..ea50969ecb8 100644 --- a/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp +++ b/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp @@ -802,7 +802,7 @@ public: } } - void ProcessEvent(WorldObject* /*go*/, uint32 uiEventId) + void ProcessEvent(WorldObject* /*go*/, uint32 uiEventId) override { switch (uiEventId) { diff --git a/src/server/scripts/Northrend/zone_grizzly_hills.cpp b/src/server/scripts/Northrend/zone_grizzly_hills.cpp index 15fa6d836cd..83fd3859716 100644 --- a/src/server/scripts/Northrend/zone_grizzly_hills.cpp +++ b/src/server/scripts/Northrend/zone_grizzly_hills.cpp @@ -826,11 +826,11 @@ class spell_infected_worgen_bite : public SpellScriptLoader { public: spell_infected_worgen_bite() : SpellScriptLoader("spell_infected_worgen_bite") { } - + class spell_infected_worgen_bite_AuraScript : public AuraScript { PrepareAuraScript(spell_infected_worgen_bite_AuraScript); - + void HandleAfterEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { Unit* target = GetTarget(); @@ -841,7 +841,7 @@ class spell_infected_worgen_bite : public SpellScriptLoader target->CastSpell(target, SPELL_WORGENS_CALL, true); } } - + void Register() override { AfterEffectApply += AuraEffectApplyFn(spell_infected_worgen_bite_AuraScript::HandleAfterEffectApply, EFFECT_1, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAPPLY); diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.h b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.h index a08e141294d..9c76b35937e 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.h +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.h @@ -184,9 +184,9 @@ class OPvPCapturePointZM_GraveYard : public OPvPCapturePoint public: OPvPCapturePointZM_GraveYard(OutdoorPvP* pvp); - bool Update(uint32 diff); + bool Update(uint32 diff) override; - void ChangeState() { } + void ChangeState() override { } void FillInitialWorldStates(WorldPacket & data); @@ -196,11 +196,11 @@ class OPvPCapturePointZM_GraveYard : public OPvPCapturePoint void SetBeaconState(uint32 controlling_team); // not good atm - bool HandleGossipOption(Player* player, ObjectGuid guid, uint32 gossipid); + bool HandleGossipOption(Player* player, ObjectGuid guid, uint32 gossipid) override; - bool HandleDropFlag(Player* player, uint32 spellId); + bool HandleDropFlag(Player* player, uint32 spellId) override; - bool CanTalkTo(Player* player, Creature* creature, GossipMenuItems const& gso); + bool CanTalkTo(Player* player, Creature* creature, GossipMenuItems const& gso) override; uint32 GetGraveYardState() const; diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp index 2b5ad18022a..9667b4e3bb0 100644 --- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp @@ -93,7 +93,7 @@ class boss_ambassador_hellmaw : public CreatureScript { } - void DoAction(int32 actionId) + void DoAction(int32 actionId) override { if (actionId == ACTION_AMBASSADOR_HELLMAW_INTRO) DoIntro(); diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp index 9d2737c8ba5..f984272f4d5 100644 --- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp @@ -92,7 +92,7 @@ class instance_shadow_labyrinth : public InstanceMapScript } } - void OnUnitDeath(Unit* unit) + void OnUnitDeath(Unit* unit) override { Creature* creature = unit->ToCreature(); if (!creature) diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp index 2750476db76..096777163a6 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp @@ -280,7 +280,7 @@ public: Map::PlayerList const &PlayerList = map->GetPlayers(); for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) { - if (i->GetSource() && i->GetSource()->IsAlive() && me->HasInArc(float(diff/20000*M_PI*2), i->GetSource()) && me->IsWithinDist(i->GetSource(), SPOUT_DIST) && !i->GetSource()->IsInWater()) + if (i->GetSource() && i->GetSource()->IsAlive() && me->HasInArc(diff/20000.f*float(M_PI)*2.f, i->GetSource()) && me->IsWithinDist(i->GetSource(), SPOUT_DIST) && !i->GetSource()->IsInWater()) DoCast(i->GetSource(), SPELL_SPOUT, true); // only knock back players in arc, in 100yards, not in water } } diff --git a/src/server/scripts/Outland/CoilfangReservoir/SteamVault/instance_steam_vault.cpp b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/instance_steam_vault.cpp index 30444caa496..4cc522c7523 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SteamVault/instance_steam_vault.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/instance_steam_vault.cpp @@ -43,7 +43,7 @@ class go_main_chambers_access_panel : public GameObjectScript } }; -ObjectData const gameObjectData[] = +ObjectData const gameObjectData[] = { { GO_ACCESS_PANEL_HYDRO, DATA_ACCESS_PANEL_HYDRO }, { GO_ACCESS_PANEL_MEK, DATA_ACCESS_PANEL_MEK }, diff --git a/src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp b/src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp index 374ce3cd957..88dbeff09f5 100644 --- a/src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp +++ b/src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp @@ -123,7 +123,7 @@ public: instance->SetBossState(DATA_MAULGAR, DONE); } - void DoAction(int32 actionId) + void DoAction(int32 actionId) override { if (actionId == ACTION_ADD_DEATH) Talk(SAY_OGRE_DEATH); diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp index 0d7fe11956b..7d00cd97126 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp @@ -416,7 +416,7 @@ class npc_omrogg_heads : public CreatureScript void EnterCombat(Unit* /*who*/) override { } - void SetData(uint32 data, uint32 value) + void SetData(uint32 data, uint32 value) override { if (data == SETDATA_DATA && value == SETDATA_YELL) { diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp index ee12d8c4d0d..6021e38d3cf 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp @@ -316,10 +316,10 @@ class boss_high_astromancer_solarian : public CreatureScript Portals[i][2] = PORTAL_Z; } } - if ((abs(Portals[2][0] - Portals[1][0]) < 7) && (abs(Portals[2][1] - Portals[1][1]) < 7)) + if ((std::abs(Portals[2][0] - Portals[1][0]) < 7) && (std::abs(Portals[2][1] - Portals[1][1]) < 7)) { int i=1; - if (abs(CENTER_X + 26.0f - Portals[2][0]) < 7) + if (std::abs(CENTER_X + 26.0f - Portals[2][0]) < 7) i = -1; Portals[2][0] = Portals[2][0]+7*i; Portals[2][1] = Portal_Y(Portals[2][0], LARGE_PORTAL_RADIUS); diff --git a/src/server/scripts/Outland/TempestKeep/Mechanar/instance_mechanar.cpp b/src/server/scripts/Outland/TempestKeep/Mechanar/instance_mechanar.cpp index 4955a2201e5..b2d63315029 100644 --- a/src/server/scripts/Outland/TempestKeep/Mechanar/instance_mechanar.cpp +++ b/src/server/scripts/Outland/TempestKeep/Mechanar/instance_mechanar.cpp @@ -42,7 +42,7 @@ class instance_mechanar : public InstanceMapScript LoadDoorData(doorData); } - void OnGameObjectCreate(GameObject* gameObject) + void OnGameObjectCreate(GameObject* gameObject) override { switch (gameObject->GetEntry()) { diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/boss_harbinger_skyriss.cpp b/src/server/scripts/Outland/TempestKeep/arcatraz/boss_harbinger_skyriss.cpp index 213f31b280f..03e2154792b 100644 --- a/src/server/scripts/Outland/TempestKeep/arcatraz/boss_harbinger_skyriss.cpp +++ b/src/server/scripts/Outland/TempestKeep/arcatraz/boss_harbinger_skyriss.cpp @@ -283,7 +283,7 @@ class boss_harbinger_skyriss_illusion : public CreatureScript { boss_harbinger_skyriss_illusionAI(Creature* creature) : ScriptedAI(creature) { } - void Reset() override + void Reset() override { me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } diff --git a/src/server/scripts/Outland/zone_blades_edge_mountains.cpp b/src/server/scripts/Outland/zone_blades_edge_mountains.cpp index 72355b05ec1..aaf006f6c5f 100644 --- a/src/server/scripts/Outland/zone_blades_edge_mountains.cpp +++ b/src/server/scripts/Outland/zone_blades_edge_mountains.cpp @@ -24,12 +24,9 @@ SDCategory: Blade's Edge Mountains EndScriptData */ /* ContentData -npc_bloodmaul_brutebane -npc_bloodmaul_brute npc_nether_drake npc_daranelle go_legion_obelisk -go_thunderspike EndContentData */ #include "ScriptMgr.h" @@ -45,171 +42,6 @@ EndContentData */ #include "SpellAuraEffects.h" /*###### -## npc_bloodmaul_brutebane -######*/ - -enum Bloodmaul -{ - NPC_OGRE_BRUTE = 19995, - NPC_QUEST_CREDIT = 21241, - GO_KEG = 184315, - QUEST_GETTING_THE_BLADESPIRE_TANKED = 10512, - QUEST_BLADESPIRE_KEGGER = 10545 -}; - -class npc_bloodmaul_brutebane : public CreatureScript -{ -public: - npc_bloodmaul_brutebane() : CreatureScript("npc_bloodmaul_brutebane") { } - - struct npc_bloodmaul_brutebaneAI : public ScriptedAI - { - npc_bloodmaul_brutebaneAI(Creature* creature) : ScriptedAI(creature) - { - if (Creature* Ogre = me->FindNearestCreature(NPC_OGRE_BRUTE, 50, true)) - { - Ogre->SetReactState(REACT_DEFENSIVE); - Ogre->GetMotionMaster()->MovePoint(1, me->GetPositionX()-1, me->GetPositionY()+1, me->GetPositionZ()); - } - } - - void UpdateAI(uint32 /*diff*/) override { } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_bloodmaul_brutebaneAI(creature); - } -}; - -/*###### -## npc_bloodmaul_brute -######*/ - -enum BloodmaulBrute -{ - EVENT_CLEAVE = 1, - EVENT_DEBILITATING_STRIKE = 2, - SAY_AGGRO = 0, - SAY_DEATH = 1, - SAY_ENRAGE = 2, - SPELL_CLEAVE = 15496, - SPELL_DEBILITATING_STRIKE = 37577, - SPELL_ENRAGE = 8599, - QUEST_INTO_THE_SOULGRINDER = 11000 -}; - -class npc_bloodmaul_brute : public CreatureScript -{ -public: - npc_bloodmaul_brute() : CreatureScript("npc_bloodmaul_brute") { } - - struct npc_bloodmaul_bruteAI : public ScriptedAI - { - npc_bloodmaul_bruteAI(Creature* creature) : ScriptedAI(creature) - { - hp30 = false; - } - - void Reset() override - { - PlayerGUID.Clear(); - hp30 = false; - } - - void EnterCombat(Unit* /*who*/) override - { - if (urand (0, 100) < 35) - Talk(SAY_AGGRO); - - events.ScheduleEvent(EVENT_CLEAVE, urand(9000,12000)); - events.ScheduleEvent(EVENT_DEBILITATING_STRIKE, 15000); - } - - void JustDied(Unit* killer) override - { - if (killer->GetTypeId() == TYPEID_PLAYER) - if (killer->ToPlayer()->GetQuestRewardStatus(QUEST_INTO_THE_SOULGRINDER)) - Talk(SAY_DEATH); - } - - void MoveInLineOfSight(Unit* who) override - { - if (!who || (!who->IsAlive())) - return; - - if (me->IsWithinDistInMap(who, 50.0f)) - { - if (who->GetTypeId() == TYPEID_PLAYER) - if (who->ToPlayer()->GetQuestStatus(QUEST_GETTING_THE_BLADESPIRE_TANKED) == QUEST_STATUS_INCOMPLETE - || who->ToPlayer()->GetQuestStatus(QUEST_BLADESPIRE_KEGGER) == QUEST_STATUS_INCOMPLETE) - PlayerGUID = who->GetGUID(); - } - } - - void MovementInform(uint32 /*type*/, uint32 id) override - { - if (id == 1) - { - if (GameObject* Keg = me->FindNearestGameObject(GO_KEG, 20)) - Keg->Delete(); - - me->HandleEmoteCommand(7); - me->SetReactState(REACT_AGGRESSIVE); - me->GetMotionMaster()->MoveTargetedHome(); - - Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID); - Creature* Credit = me->FindNearestCreature(NPC_QUEST_CREDIT, 50, true); - if (player && Credit) - player->KilledMonster(Credit->GetCreatureTemplate(), Credit->GetGUID()); - } - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_CLEAVE: - DoCast(me, SPELL_CLEAVE); - events.ScheduleEvent(EVENT_CLEAVE, urand(9000,12000)); - break; - case EVENT_DEBILITATING_STRIKE: - DoCastVictim(SPELL_DEBILITATING_STRIKE); - events.ScheduleEvent(EVENT_DEBILITATING_STRIKE, urand(18000,22000)); - break; - } - } - - if (!hp30 && HealthBelowPct(30)) - { - hp30 = true; - Talk(SAY_ENRAGE); - DoCast(me, SPELL_ENRAGE); - } - - DoMeleeAttackIfReady(); - } - - private: - EventMap events; - ObjectGuid PlayerGUID; - bool hp30; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_bloodmaul_bruteAI(creature); - } -}; - -/*###### ## npc_nether_drake ######*/ @@ -507,31 +339,6 @@ public: } }; -/*###### -## go_thunderspike -######*/ - -enum TheThunderspike -{ - NPC_GOR_GRIMGUT = 21319, - QUEST_THUNDERSPIKE = 10526, -}; - -class go_thunderspike : public GameObjectScript -{ - public: - go_thunderspike() : GameObjectScript("go_thunderspike") { } - - bool OnGossipHello(Player* player, GameObject* go) override - { - if (player->GetQuestStatus(QUEST_THUNDERSPIKE) == QUEST_STATUS_INCOMPLETE && !go->FindNearestCreature(NPC_GOR_GRIMGUT, 25.0f, true)) - if (Creature* gorGrimgut = go->SummonCreature(NPC_GOR_GRIMGUT, -2413.4f, 6914.48f, 25.01f, 3.67f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 300000)) - gorGrimgut->AI()->AttackStart(player); - - return true; - } -}; - enum SimonGame { NPC_SIMON_BUNNY = 22923, @@ -1219,12 +1026,9 @@ class spell_oscillating_field : public SpellScriptLoader void AddSC_blades_edge_mountains() { - new npc_bloodmaul_brutebane(); - new npc_bloodmaul_brute(); new npc_nether_drake(); new npc_daranelle(); new go_legion_obelisk(); - new go_thunderspike(); new npc_simon_bunny(); new go_simon_cluster(); new go_apexis_relic(); diff --git a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp index 97777cd5f6e..2a568a84a7c 100644 --- a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp +++ b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp @@ -289,7 +289,7 @@ public: summoned->AI()->AttackStart(me); } - void sQuestAccept(Player* player, Quest const* quest) + void sQuestAccept(Player* player, Quest const* quest) override { if (quest->GetQuestId() == QUEST_ROAD_TO_FALCON_WATCH) { diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index 9843a472971..b290cb75a2b 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -477,7 +477,7 @@ class spell_item_flask_of_the_north : public SpellScriptLoader break; } - caster->CastSpell(caster, possibleSpells[irand(0, (possibleSpells.size() - 1))], true, NULL); + caster->CastSpell(caster, possibleSpells[urand(0, (possibleSpells.size() - 1))], true, NULL); } void Register() override diff --git a/src/server/shared/Dynamic/ObjectRegistry.h b/src/server/shared/Dynamic/ObjectRegistry.h index be253f947a7..1eb9368be61 100644 --- a/src/server/shared/Dynamic/ObjectRegistry.h +++ b/src/server/shared/Dynamic/ObjectRegistry.h @@ -47,12 +47,12 @@ class ObjectRegistry } /// Inserts a registry item - bool InsertItem(T *obj, Key key, bool override = false) + bool InsertItem(T *obj, Key key, bool _override = false) { typename RegistryMapType::iterator iter = i_registeredObjects.find(key); if ( iter != i_registeredObjects.end() ) { - if ( !override ) + if ( !_override ) return false; delete iter->second; i_registeredObjects.erase(iter); diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h index d4653960b15..e22a06e635e 100644 --- a/src/server/shared/Logging/Log.h +++ b/src/server/shared/Logging/Log.h @@ -64,7 +64,7 @@ class Log template<typename... Args> inline void outMessage(std::string const& filter, LogLevel const level, const char* fmt, Args const&... args) { - write(std::move(std::unique_ptr<LogMessage>(new LogMessage(level, filter, std::move(Trinity::StringFormat(fmt, args...)))))); + write(std::unique_ptr<LogMessage>(new LogMessage(level, filter, Trinity::StringFormat(fmt, args...)))); } template<typename... Args> diff --git a/src/server/shared/Networking/Socket.h b/src/server/shared/Networking/Socket.h index f7a1b954cb0..396d4bb3aab 100644 --- a/src/server/shared/Networking/Socket.h +++ b/src/server/shared/Networking/Socket.h @@ -62,7 +62,7 @@ public: return false; #ifndef TC_SOCKET_USE_IOCP - std::unique_lock<std::mutex> guard(_writeLock, std::try_to_lock); + std::unique_lock<std::mutex> guard(_writeLock); if (!guard) return true; @@ -140,6 +140,8 @@ public: if (shutdownError) TC_LOG_DEBUG("network", "Socket::CloseSocket: %s errored when shutting down socket: %i (%s)", GetRemoteIpAddress().to_string().c_str(), shutdownError.value(), shutdownError.message().c_str()); + + OnClose(); } /// Marks the socket for closing after write buffer becomes empty @@ -148,6 +150,8 @@ public: MessageBuffer& GetReadBuffer() { return _readBuffer; } protected: + virtual void OnClose() { } + virtual void ReadHandler() = 0; bool AsyncProcessQueue(std::unique_lock<std::mutex>&) diff --git a/src/server/shared/Updater/DBUpdater.cpp b/src/server/shared/Updater/DBUpdater.cpp index 5918fe06b55..e5c571e4517 100644 --- a/src/server/shared/Updater/DBUpdater.cpp +++ b/src/server/shared/Updater/DBUpdater.cpp @@ -239,11 +239,19 @@ bool DBUpdater<T>::Update(DatabaseWorkerPool<T>& pool) [&](Path const& file) { DBUpdater<T>::ApplyFile(pool, file); }, [&](std::string const& query) -> QueryResult { return DBUpdater<T>::Retrieve(pool, query); }); - uint32 const count = updateFetcher.Update( - sConfigMgr->GetBoolDefault("Updates.Redundancy", true), - sConfigMgr->GetBoolDefault("Updates.AllowRehash", true), - sConfigMgr->GetBoolDefault("Updates.ArchivedRedundancy", false), - sConfigMgr->GetIntDefault("Updates.CleanDeadRefMaxCount", 3)); + uint32 count; + try + { + count = updateFetcher.Update( + sConfigMgr->GetBoolDefault("Updates.Redundancy", true), + sConfigMgr->GetBoolDefault("Updates.AllowRehash", true), + sConfigMgr->GetBoolDefault("Updates.ArchivedRedundancy", false), + sConfigMgr->GetIntDefault("Updates.CleanDeadRefMaxCount", 3)); + } + catch (UpdateException&) + { + return false; + } if (!count) TC_LOG_INFO("sql.updates", ">> %s database is up-to-date!", DBUpdater<T>::GetTableName().c_str()); @@ -298,7 +306,14 @@ bool DBUpdater<T>::Populate(DatabaseWorkerPool<T>& pool) // Update database TC_LOG_INFO("sql.updates", ">> Applying \'%s\'...", base.generic_string().c_str()); - ApplyFile(pool, base); + try + { + ApplyFile(pool, base); + } + catch (UpdateException&) + { + return false; + } TC_LOG_INFO("sql.updates", ">> Done!"); return true; diff --git a/src/server/shared/Updater/UpdateFetcher.cpp b/src/server/shared/Updater/UpdateFetcher.cpp index 2b12f39780c..a4bdd193743 100644 --- a/src/server/shared/Updater/UpdateFetcher.cpp +++ b/src/server/shared/Updater/UpdateFetcher.cpp @@ -158,7 +158,7 @@ uint32 UpdateFetcher::Update(bool const redundancyChecks, bool const allowRehash { LocaleFileStorage const available = GetFileList(); AppliedFileStorage applied = ReceiveAppliedFiles(); - + // Fill hash to name cache HashToFileNameStorage hashToName; for (auto entry : applied) diff --git a/src/server/shared/Updater/UpdateFetcher.h b/src/server/shared/Updater/UpdateFetcher.h index 094e353f274..fa142547873 100644 --- a/src/server/shared/Updater/UpdateFetcher.h +++ b/src/server/shared/Updater/UpdateFetcher.h @@ -27,7 +27,7 @@ class UpdateFetcher { - using Path = boost::filesystem::path; + typedef boost::filesystem::path Path; public: UpdateFetcher(Path const& updateDirectory, @@ -53,6 +53,9 @@ private: struct AppliedFileEntry { + AppliedFileEntry(std::string const& name_, std::string const& hash_, State state_, uint64 timestamp_) + : name(name_), hash(hash_), state(state_), timestamp(timestamp_) { } + std::string const name; std::string const hash; @@ -79,12 +82,14 @@ private: struct DirectoryEntry { + DirectoryEntry(Path const& path_, State state_) : path(path_), state(state_) { } + Path const path; State const state; }; - using LocaleFileEntry = std::pair<Path, State>; + typedef std::pair<Path, State> LocaleFileEntry; struct PathCompare { @@ -94,11 +99,11 @@ private: } }; - using LocaleFileStorage = std::set<LocaleFileEntry, PathCompare>; - using HashToFileNameStorage = std::unordered_map<std::string, std::string>; - using AppliedFileStorage = std::unordered_map<std::string, AppliedFileEntry>; - using DirectoryStorage = std::vector<UpdateFetcher::DirectoryEntry>; - using SQLUpdate = std::shared_ptr<std::string>; + typedef std::set<LocaleFileEntry, PathCompare> LocaleFileStorage; + typedef std::unordered_map<std::string, std::string> HashToFileNameStorage; + typedef std::unordered_map<std::string, AppliedFileEntry> AppliedFileStorage; + typedef std::vector<UpdateFetcher::DirectoryEntry> DirectoryStorage; + typedef std::shared_ptr<std::string> SQLUpdate; LocaleFileStorage GetFileList() const; void FillFileListRecursively(Path const& path, LocaleFileStorage& storage, State const state, uint32 const depth) const; diff --git a/src/server/shared/Utilities/ServiceWin32.cpp b/src/server/shared/Utilities/ServiceWin32.cpp index c73949fc6a3..3e5e416b1a3 100644 --- a/src/server/shared/Utilities/ServiceWin32.cpp +++ b/src/server/shared/Utilities/ServiceWin32.cpp @@ -255,7 +255,7 @@ bool WinServiceRun() if (!StartServiceCtrlDispatcher(serviceTable)) { - TC_LOG_ERROR("server.worldserver", "StartService Failed. Error [%u]", ::GetLastError()); + TC_LOG_ERROR("server.worldserver", "StartService Failed. Error [%u]", uint32(::GetLastError())); return false; } return true; diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index fbf2c74ac0b..430c3ce4d73 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -308,7 +308,7 @@ void ShutdownCLIThread(std::thread* cliThread) errorBuffer = "Unknown error"; TC_LOG_DEBUG("server.worldserver", "Error cancelling I/O of CliThread, error code %u, detail: %s", - errorCode, errorBuffer); + uint32(errorCode), errorBuffer); LocalFree(errorBuffer); // send keyboard input to safely unblock the CLI thread diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp index a573f9fecc8..dcaa3ba0a76 100644 --- a/src/tools/map_extractor/System.cpp +++ b/src/tools/map_extractor/System.cpp @@ -63,8 +63,9 @@ typedef struct map_id *map_ids; uint16 *areas; uint16 *LiqType; -char output_path[128] = "."; -char input_path[128] = "."; +#define MAX_PATH_LENGTH 128 +char output_path[MAX_PATH_LENGTH] = "."; +char input_path[MAX_PATH_LENGTH] = "."; uint32 maxAreaId = 0; // ************************************************** @@ -143,11 +144,11 @@ void Usage(char* prg) printf( "Usage:\n"\ "%s -[var] [value]\n"\ - "-i set input path\n"\ - "-o set output path\n"\ + "-i set input path (max %d characters)\n"\ + "-o set output path (max %d characters)\n"\ "-e extract only MAP(1)/DBC(2) - standard: both(3)\n"\ "-f height stored as int (less map size but lost some accuracy) 1 by default\n"\ - "Example: %s -f 0 -i \"c:\\games\\game\"", prg, prg); + "Example: %s -f 0 -i \"c:\\games\\game\"", prg, MAX_PATH_LENGTH - 1, MAX_PATH_LENGTH - 1, prg); exit(1); } @@ -166,14 +167,20 @@ void HandleArgs(int argc, char * arg[]) switch(arg[c][1]) { case 'i': - if(c + 1 < argc) // all ok - strcpy(input_path, arg[(c++) + 1]); + if (c + 1 < argc && strlen(arg[c + 1]) < MAX_PATH_LENGTH) // all ok + { + strncpy(input_path, arg[c++ + 1], MAX_PATH_LENGTH); + input_path[MAX_PATH_LENGTH - 1] = '\0'; + } else Usage(arg[0]); break; case 'o': - if(c + 1 < argc) // all ok - strcpy(output_path, arg[(c++) + 1]); + if (c + 1 < argc && strlen(arg[c + 1]) < MAX_PATH_LENGTH) // all ok + { + strncpy(output_path, arg[c++ + 1], MAX_PATH_LENGTH); + output_path[MAX_PATH_LENGTH - 1] = '\0'; + } else Usage(arg[0]); break; @@ -250,7 +257,17 @@ uint32 ReadMapDBC() for(uint32 x = 0; x < map_count; ++x) { map_ids[x].id = dbc.getRecord(x).getUInt(0); - strcpy(map_ids[x].name, dbc.getRecord(x).getString(1)); + + const char* map_name = dbc.getRecord(x).getString(1); + size_t max_map_name_length = sizeof(map_ids[x].name); + if (strlen(map_name) >= max_map_name_length) + { + printf("Fatal error: Map name too long!\n"); + exit(1); + } + + strncpy(map_ids[x].name, map_name, max_map_name_length); + map_ids[x].name[max_map_name_length - 1] = '\0'; } printf("Done! (%u maps loaded)\n", (uint32)map_count); return map_count; diff --git a/src/tools/vmap4_assembler/CMakeLists.txt b/src/tools/vmap4_assembler/CMakeLists.txt index c0ff9e9a153..dfd6c7d4dd4 100644 --- a/src/tools/vmap4_assembler/CMakeLists.txt +++ b/src/tools/vmap4_assembler/CMakeLists.txt @@ -16,7 +16,6 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/server/collision ${CMAKE_SOURCE_DIR}/src/server/collision/Maps ${CMAKE_SOURCE_DIR}/src/server/collision/Models - ${ACE_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ) diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp index 4cec49ef333..7a12897563e 100644 --- a/src/tools/vmap4_extractor/vmapexport.cpp +++ b/src/tools/vmap4_extractor/vmapexport.cpp @@ -197,7 +197,7 @@ bool ExtractSingleWmo(std::string& fname) for (uint32 i = 0; i < froot.nGroups; ++i) { char temp[1024]; - strcpy(temp, fname.c_str()); + strncpy(temp, fname.c_str(), 1024); temp[fname.length()-4] = 0; char groupFileName[1024]; sprintf(groupFileName, "%s_%03u.wmo", temp, i); @@ -395,7 +395,9 @@ bool processArgv(int argc, char ** argv, const char *versionString) if((i+1)<argc) { hasInputPathParam = true; - strcpy(input_path, argv[i+1]); + strncpy(input_path, argv[i + 1], sizeof(input_path)); + input_path[sizeof(input_path) - 1] = '\0'; + if (input_path[strlen(input_path) - 1] != '\\' && input_path[strlen(input_path) - 1] != '/') strcat(input_path, "/"); ++i; @@ -511,11 +513,22 @@ int main(int argc, char ** argv) map_ids=new map_id[map_count]; for (unsigned int x=0;x<map_count;++x) { - map_ids[x].id=dbc->getRecord (x).getUInt(0); - strcpy(map_ids[x].name,dbc->getRecord(x).getString(1)); - printf("Map - %s\n",map_ids[x].name); - } + map_ids[x].id = dbc->getRecord(x).getUInt(0); + + const char* map_name = dbc->getRecord(x).getString(1); + size_t max_map_name_length = sizeof(map_ids[x].name); + if (strlen(map_name) >= max_map_name_length) + { + delete dbc; + delete[] map_ids; + printf("FATAL ERROR: Map name too long.\n"); + return 1; + } + strncpy(map_ids[x].name, map_name, max_map_name_length); + map_ids[x].name[max_map_name_length - 1] = '\0'; + printf("Map - %s\n", map_ids[x].name); + } delete dbc; ParsMapFiles(); |