From dc96ddfbfb18649f5afc34897749d3031bb56dd8 Mon Sep 17 00:00:00 2001 From: balrok Date: Wed, 7 Oct 2009 15:35:52 +0200 Subject: [PATCH 01/20] [8599] removed now unneeded parameter from GetBattleGroundQueueIdFromLevel cause alterac valley is not handled special since 3.2.2 this function also works without bgtypeid parameter --- src/game/BattleGroundHandler.cpp | 12 ++++++------ src/game/BattleGroundMgr.cpp | 6 +++--- src/game/Group.cpp | 4 ++-- src/game/Player.cpp | 2 +- src/game/Player.h | 2 +- src/shared/revision_nr.h | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index 56576a6d7..004f5e050 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -146,7 +146,7 @@ void WorldSession::HandleBattlemasterJoinOpcode( WorldPacket & recv_data ) // _player->GetGroup() was already checked, grp is already initialized GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, isPremade, 0); - uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId)); + uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundQueueIdFromLevel()); if (joinAsGroup /* && _player->GetGroup()*/) { sLog.outDebug("Battleground: the following players are joining as group:"); @@ -181,7 +181,7 @@ void WorldSession::HandleBattlemasterJoinOpcode( WorldPacket & recv_data ) sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } - sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId)); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel()); if (!ginfo->IsInvitedToBGInstanceGUID) sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true); } @@ -477,7 +477,7 @@ void WorldSession::HandleBattleFieldPortOpcode( WorldPacket &recv_data ) sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), true); // player left queue, we should update it - do not update Arena Queue if (!arenaType) - sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId), arenaType, isRated, rating); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenaType, isRated, rating); SendPacket(&data); sLog.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player->GetName(), _player->GetGUIDLow(), bg->GetTypeID(), bgQueueTypeId); break; @@ -560,7 +560,7 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); if (!bg) continue; - uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(itrPlayerStatus->second.GroupInfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId)); + uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(itrPlayerStatus->second.GroupInfo, _player->GetBattleGroundQueueIdFromLevel()); // send status in BattleGround Queue sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, avgTime, getMSTimeDiff(itrPlayerStatus->second.GroupInfo->JoinTime, getMSTime()), arenaType); SendPacket(&data); @@ -723,7 +723,7 @@ void WorldSession::HandleBattlemasterJoinArena( WorldPacket & recv_data ) } GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating, ateamId); - uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId)); + uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundQueueIdFromLevel()); if (asGroup) { sLog.outDebug("Battleground: arena join as group start"); @@ -760,7 +760,7 @@ void WorldSession::HandleBattlemasterJoinArena( WorldPacket & recv_data ) sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); sLog.outDebug("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } - sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId), arenatype, isRated, arenaRating); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated, arenaRating); } void WorldSession::HandleReportPvPAFK( WorldPacket & recv_data ) diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index b885595aa..b40dcd2b6 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -150,7 +150,7 @@ bool BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo *ginfo, uint32 de // add group to bg queue with the given leader and bg specifications GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, BattleGroundTypeId BgTypeId, uint8 ArenaType, bool isRated, bool isPremade, uint32 arenaRating, uint32 arenateamid) { - BGQueueIdBasedOnLevel queue_id = leader->GetBattleGroundQueueIdFromLevel(BgTypeId); + BGQueueIdBasedOnLevel queue_id = leader->GetBattleGroundQueueIdFromLevel(); // create new ginfo // cannot use the method like in addplayer, because that could modify an in-queue group's stats @@ -391,7 +391,7 @@ void BattleGroundQueue::AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playe if (!bg || !plr) return; - BGQueueIdBasedOnLevel queue_id = plr->GetBattleGroundQueueIdFromLevel(bg->GetTypeID()); + BGQueueIdBasedOnLevel queue_id = plr->GetBattleGroundQueueIdFromLevel(); char const* bgName = bg->GetName(); uint32 MinPlayers = bg->GetMinPlayersPerTeam(); uint32 qHorde = 0; @@ -1871,7 +1871,7 @@ void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, const uint6 uint32 count = 0; *data << uint32(0x00); // number of bg instances - uint32 queue_id = plr->GetBattleGroundQueueIdFromLevel(bgTypeId); + uint32 queue_id = plr->GetBattleGroundQueueIdFromLevel(); for(std::set::iterator itr = m_ClientBattleGroundIds[bgTypeId][queue_id].begin(); itr != m_ClientBattleGroundIds[bgTypeId][queue_id].end();++itr) { *data << uint32(*itr); diff --git a/src/game/Group.cpp b/src/game/Group.cpp index 7edee6eb1..b3f77f529 100644 --- a/src/game/Group.cpp +++ b/src/game/Group.cpp @@ -1427,7 +1427,7 @@ uint32 Group::CanJoinBattleGroundQueue(BattleGroundTypeId bgTypeId, BattleGround if(!reference) return BG_JOIN_ERR_OFFLINE_MEMBER; - BGQueueIdBasedOnLevel queue_id = reference->GetBattleGroundQueueIdFromLevel(bgTypeId); + BGQueueIdBasedOnLevel queue_id = reference->GetBattleGroundQueueIdFromLevel(); uint32 arenaTeamId = reference->GetArenaTeamId(arenaSlot); uint32 team = reference->GetTeam(); @@ -1442,7 +1442,7 @@ uint32 Group::CanJoinBattleGroundQueue(BattleGroundTypeId bgTypeId, BattleGround if(member->GetTeam() != team) return BG_JOIN_ERR_MIXED_FACTION; // not in the same battleground level braket, don't let join - if(member->GetBattleGroundQueueIdFromLevel(bgTypeId) != queue_id) + if(member->GetBattleGroundQueueIdFromLevel() != queue_id) return BG_JOIN_ERR_MIXED_LEVELS; // don't let join rated matches if the arena team id doesn't match if(isRated && member->GetArenaTeamId(arenaSlot) != arenaTeamId) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 185551340..43bf9d85a 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18651,7 +18651,7 @@ bool Player::GetBGAccessByLevel(BattleGroundTypeId bgTypeId) const return true; } -BGQueueIdBasedOnLevel Player::GetBattleGroundQueueIdFromLevel(BattleGroundTypeId bgTypeId) const +BGQueueIdBasedOnLevel Player::GetBattleGroundQueueIdFromLevel() const { // for ranges 0 - 19, 20 - 29, 30 - 39, 40 - 49, 50 - 59, 60 - 69, 70 - 79, 80 uint32 queue_id = ( getLevel() / 10) - 1; diff --git a/src/game/Player.h b/src/game/Player.h index 503cd4836..5d0a4fbcf 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1958,7 +1958,7 @@ class MANGOS_DLL_SPEC Player : public Unit BattleGround* GetBattleGround() const; - BGQueueIdBasedOnLevel GetBattleGroundQueueIdFromLevel(BattleGroundTypeId bgTypeId) const; + BGQueueIdBasedOnLevel GetBattleGroundQueueIdFromLevel() const; bool InBattleGroundQueue() const { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index b4b494711..32c85f480 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8598" + #define REVISION_NR "8599" #endif // __REVISION_NR_H__ From 49c52ddf9c91ad1a882918b72df72a48a6ccec16 Mon Sep 17 00:00:00 2001 From: balrok Date: Thu, 8 Oct 2009 00:17:55 +0200 Subject: [PATCH 02/20] [8600] allow unbinding instances also per map so command can be called as .instance unbind all or .instance unbind #mapid now output also the mapname next to the mapid for the humanoid users among us ;) --- sql/mangos.sql | 4 +- sql/updates/8600_01_mangos_command.sql | 8 +++ sql/updates/Makefile.am | 2 + src/game/Level3.cpp | 69 +++++++++++++++++++------- src/shared/revision_nr.h | 2 +- src/shared/revision_sql.h | 2 +- 6 files changed, 65 insertions(+), 22 deletions(-) create mode 100644 sql/updates/8600_01_mangos_command.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index ef4f2ce41..055418eeb 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -24,7 +24,7 @@ CREATE TABLE `db_version` ( `version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL, `cache_id` int(10) default '0', - `required_8589_10_mangos_spell_proc_event` bit(1) default NULL + `required_8600_01_mangos_command` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -434,7 +434,7 @@ INSERT INTO `command` VALUES ('honor addkill',2,'Syntax: .honor addkikll\r\n\r\nAdd the targeted unit as one of your pvp kills today (you only get honor if it\'s a racial leader or a player)'), ('honor update',2,'Syntax: .honor update\r\n\r\nForce the yesterday\'s honor fields to be updated with today\'s data, which will get reset for the selected player.'), ('hover',3,'Syntax: .hover #flag\r\n\r\nEnable or disable hover mode for your character.\r\n\r\nUse a #flag of value 1 to enable, use a #flag value of 0 to disable hover.'), -('instance unbind',3,'Syntax: .instance unbind all\r\n All of the selected player\'s binds will be cleared.'), +('instance unbind',3,'Syntax: .instance unbind all\r\n All of the selected player\'s binds will be cleared.\r\n.instance unbind #mapid\r\n Only the specified #mapid instance will be cleared.'), ('instance listbinds',3,'Syntax: .instance listbinds\r\n Lists the binds of the selected player.'), ('instance stats',3,'Syntax: .instance stats\r\n Shows statistics about instances.'), ('instance savedata',3,'Syntax: .instance savedata\r\n Save the InstanceData for the current player\'s map to the DB.'), diff --git a/sql/updates/8600_01_mangos_command.sql b/sql/updates/8600_01_mangos_command.sql new file mode 100644 index 000000000..af77965fd --- /dev/null +++ b/sql/updates/8600_01_mangos_command.sql @@ -0,0 +1,8 @@ +ALTER TABLE db_version CHANGE COLUMN required_8589_10_mangos_spell_proc_event required_8600_01_mangos_command bit; + +DELETE FROM command where name='instance unbind'; + +INSERT INTO `command` VALUES +('instance unbind',3,'Syntax: .instance unbind all\r\n All of the selected +player\'s binds will be cleared.\r\n.instance unbind #mapid\r\n Only the +specified #mapid instance will be cleared.'); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 3295f9571..5a18403b4 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -129,6 +129,7 @@ pkgdata_DATA = \ 8589_10_mangos_spell_proc_event.sql \ 8589_11_characters_characters.sql \ 8596_01_characters_bugreport.sql \ + 8600_01_mangos_command.sql \ README ## Additional files to include when running 'make dist' @@ -238,4 +239,5 @@ EXTRA_DIST = \ 8589_10_mangos_spell_proc_event.sql \ 8589_11_characters_characters.sql \ 8596_01_characters_bugreport.sql \ + 8600_01_mangos_command.sql \ README diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 3e3e65082..35164c1b7 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -5920,7 +5920,14 @@ bool ChatHandler::HandleInstanceListBindsCommand(const char* /*args*/) { InstanceSave *save = itr->second.save; std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); - PSendSysMessage("map: %d inst: %d perm: %s diff: %s canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty() == DUNGEON_DIFFICULTY_NORMAL ? "normal" : "heroic", save->CanReset() ? "yes" : "no", timeleft.c_str()); + if (const MapEntry* entry = sMapStore.LookupEntry(itr->first)) + { + PSendSysMessage("map: %d (%s) inst: %d perm: %s diff: %s canReset: %s TTR: %s", + itr->first, entry->name[m_session->GetSessionDbcLocale()], save->GetInstanceId(), itr->second.perm ? "yes" : "no", + save->GetDifficulty() == DUNGEON_DIFFICULTY_NORMAL ? "normal" : "heroic", save->CanReset() ? "yes" : "no", timeleft.c_str()); + } + else + PSendSysMessage("bound for a nonexistant map %u", itr->first); counter++; } } @@ -5936,7 +5943,14 @@ bool ChatHandler::HandleInstanceListBindsCommand(const char* /*args*/) { InstanceSave *save = itr->second.save; std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); - PSendSysMessage("map: %d inst: %d perm: %s diff: %s canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty() == DUNGEON_DIFFICULTY_NORMAL ? "normal" : "heroic", save->CanReset() ? "yes" : "no", timeleft.c_str()); + if (const MapEntry* entry = sMapStore.LookupEntry(itr->first)) + { + PSendSysMessage("map: %d (%s) inst: %d perm: %s diff: %s canReset: %s TTR: %s", + itr->first, entry->name[m_session->GetSessionDbcLocale()], save->GetInstanceId(), itr->second.perm ? "yes" : "no", + save->GetDifficulty() == DUNGEON_DIFFICULTY_NORMAL ? "normal" : "heroic", save->CanReset() ? "yes" : "no", timeleft.c_str()); + } + else + PSendSysMessage("bound for a nonexistant map %u", itr->first); counter++; } } @@ -5951,31 +5965,50 @@ bool ChatHandler::HandleInstanceUnbindCommand(const char* args) if(!*args) return false; - std::string cmd = args; - if(cmd == "all") + Player* player = getSelectedPlayer(); + if (!player) + player = m_session->GetPlayer(); + uint32 counter = 0; + uint32 mapid = 0; + bool got_map = false; + + if (args != "all") { - Player* player = getSelectedPlayer(); - if (!player) player = m_session->GetPlayer(); - uint32 counter = 0; - for(uint8 i = 0; i < MAX_DIFFICULTY; ++i) + got_map = true; + mapid = atoi(args); + } + + for(uint8 i = 0; i < MAX_DIFFICULTY; ++i) + { + Player::BoundInstancesMap &binds = player->GetBoundInstances(Difficulty(i)); + for(Player::BoundInstancesMap::iterator itr = binds.begin(); itr != binds.end();) { - Player::BoundInstancesMap &binds = player->GetBoundInstances(Difficulty(i)); - for(Player::BoundInstancesMap::iterator itr = binds.begin(); itr != binds.end();) + if (got_map && mapid != itr->first) { - if(itr->first != player->GetMapId()) + ++itr; + continue; + } + if(itr->first != player->GetMapId()) + { + InstanceSave *save = itr->second.save; + std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); + + if (const MapEntry* entry = sMapStore.LookupEntry(itr->first)) { - InstanceSave *save = itr->second.save; - std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); - PSendSysMessage("unbinding map: %d inst: %d perm: %s diff: %s canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty() == DUNGEON_DIFFICULTY_NORMAL ? "normal" : "heroic", save->CanReset() ? "yes" : "no", timeleft.c_str()); - player->UnbindInstance(itr, Difficulty(i)); - counter++; + PSendSysMessage("unbinding map: %d (%s) inst: %d perm: %s diff: %s canReset: %s TTR: %s", + itr->first, entry->name[m_session->GetSessionDbcLocale()], save->GetInstanceId(), itr->second.perm ? "yes" : "no", + save->GetDifficulty() == DUNGEON_DIFFICULTY_NORMAL ? "normal" : "heroic", save->CanReset() ? "yes" : "no", timeleft.c_str()); } else - ++itr; + PSendSysMessage("bound for a nonexistant map %u", itr->first); + player->UnbindInstance(itr, Difficulty(i)); + counter++; } + else + ++itr; } - PSendSysMessage("instances unbound: %d", counter); } + PSendSysMessage("instances unbound: %d", counter); return true; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 32c85f480..94f860d26 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8599" + #define REVISION_NR "8600" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index a58fe07e0..93bae364c 100644 --- a/src/shared/revision_sql.h +++ b/src/shared/revision_sql.h @@ -1,6 +1,6 @@ #ifndef __REVISION_SQL_H__ #define __REVISION_SQL_H__ #define REVISION_DB_CHARACTERS "required_8596_01_characters_bugreport" - #define REVISION_DB_MANGOS "required_8589_10_mangos_spell_proc_event" + #define REVISION_DB_MANGOS "required_8600_01_mangos_command" #define REVISION_DB_REALMD "required_8332_01_realmd_realmcharacters" #endif // __REVISION_SQL_H__ From 308439a33561a10d86fbbd4793cb5b8243dc2ee6 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Thu, 8 Oct 2009 15:59:54 +0400 Subject: [PATCH 03/20] [8601] Fixed some movement *_ACK packets structure after switch. --- src/game/MiscHandler.cpp | 5 ++++- src/game/MovementHandler.cpp | 18 ++++++++++++------ src/game/SpellHandler.cpp | 6 ++++-- src/shared/revision_nr.h | 2 +- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 696563474..624169fe8 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -1519,7 +1519,10 @@ void WorldSession::HandleMoveSetCanFlyAckOpcode( WorldPacket & recv_data ) sLog.outDebug("WORLD: CMSG_MOVE_SET_CAN_FLY_ACK"); //recv_data.hexlike(); - recv_data.read_skip(); // guid + uint64 guid; // guid - unused + if(!recv_data.readPackGUID(guid)) + return; + recv_data.read_skip(); // unk MovementInfo movementInfo; diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 3d10973c6..b1e578893 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -526,8 +526,10 @@ void WorldSession::HandleMoveKnockBackAck( WorldPacket & recv_data ) { sLog.outDebug("CMSG_MOVE_KNOCK_BACK_ACK"); - uint64 guid; - recv_data.readPackGUID(guid); + uint64 guid; // guid - unused + if(!recv_data.readPackGUID(guid)) + return; + recv_data.read_skip(); // unk MovementInfo movementInfo; @@ -538,8 +540,10 @@ void WorldSession::HandleMoveHoverAck( WorldPacket& recv_data ) { sLog.outDebug("CMSG_MOVE_HOVER_ACK"); - uint64 guid; - recv_data.readPackGUID(guid); + uint64 guid; // guid - unused + if(!recv_data.readPackGUID(guid)) + return; + recv_data.read_skip(); // unk MovementInfo movementInfo; @@ -552,8 +556,10 @@ void WorldSession::HandleMoveWaterWalkAck(WorldPacket& recv_data) { sLog.outDebug("CMSG_MOVE_WATER_WALK_ACK"); - uint64 guid; - recv_data.readPackGUID(guid); + uint64 guid; // guid - unused + if(!recv_data.readPackGUID(guid)) + return; + recv_data.read_skip(); // unk MovementInfo movementInfo; diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index 2372dfd4b..85d600e7b 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -345,8 +345,10 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) if(unk1) { recvPacket.read_skip(); // >> MSG_MOVE_STOP - uint64 guid; - recvPacket.readPackGUID(guid); + uint64 guid; // guid - unused + if(!recvPacket.readPackGUID(guid)) + return; + MovementInfo movementInfo; ReadMovementInfo(recvPacket, &movementInfo); } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 94f860d26..00c978acb 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8600" + #define REVISION_NR "8601" #endif // __REVISION_NR_H__ From 5a48fe3c967544a1d04480b2c45a4f465ff08cf1 Mon Sep 17 00:00:00 2001 From: balrok Date: Thu, 8 Oct 2009 18:35:20 +0200 Subject: [PATCH 04/20] [8602] update movement packet when unit dies this avoids, that feared creatures walk away after dead (happens often if a creature dies in fear) --- src/game/Unit.cpp | 3 +++ src/shared/revision_nr.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 55cca34bd..0460972f1 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -10014,6 +10014,9 @@ void Unit::setDeathState(DeathState s) RemoveGuardians(); UnsummonAllTotems(); + // avoid that corpses run in fear + StopMoving(); + ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); // remove aurastates allowing special moves diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 00c978acb..d1ee24f5a 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8601" + #define REVISION_NR "8602" #endif // __REVISION_NR_H__ From c999490aa22aa22582ee35247192194204df40d8 Mon Sep 17 00:00:00 2001 From: balrok Date: Fri, 9 Oct 2009 01:15:50 +0200 Subject: [PATCH 05/20] [8603] corrected comment of last commit the problem was in Unit::setFeared which got called after removing a fearaura inside setFeared there is a check for isAlive() which will return true in this case, cause m_deathState is updated only after RemoveAllAurasOnDeath() a fix could be to set m_deathState earlier, but then auras which require a spellcast on remove won't work anymore.. (not sure if we actualy have such auras) but if in future more functions will require special code there, moving the m_deathState setting should be considered big thx to Naicisum for explanation and investigation --- src/game/Unit.cpp | 3 ++- src/shared/revision_nr.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 0460972f1..6d706c484 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -10014,7 +10014,8 @@ void Unit::setDeathState(DeathState s) RemoveGuardians(); UnsummonAllTotems(); - // avoid that corpses run in fear + // after removing a Fearaura (in RemoveAllAurasOnDeath) + // Unit::SetFeared is called and makes that creatures attack player again StopMoving(); ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index d1ee24f5a..6890630a3 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8602" + #define REVISION_NR "8603" #endif // __REVISION_NR_H__ From 3e6b4b529e2104b22980c063a9e0eee0f26dee2c Mon Sep 17 00:00:00 2001 From: arrai Date: Thu, 8 Oct 2009 21:28:16 +0200 Subject: [PATCH 06/20] fixed considering chatmessages with a pipe character to be invalid problem appeared only with ChatStrictLinkChecking.Severity = 2 --- src/game/Chat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index c024989ff..7c404cdb6 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -1036,7 +1036,7 @@ valid examples: else ++validSequenceIterator; } - else + else if(commandChar != '|') return false; } } From fe1560a4830fe66ca1a75921bd1b8e0ece47deb3 Mon Sep 17 00:00:00 2001 From: arrai Date: Fri, 9 Oct 2009 02:03:42 +0200 Subject: [PATCH 07/20] [8604] Consider random enchants in chatmessage validation --- src/game/Chat.cpp | 80 +++++++++++++++++++++++++++++++++------- src/game/DBCStructure.h | 4 +- src/game/DBCfmt.h | 4 +- src/shared/revision_nr.h | 2 +- 4 files changed, 72 insertions(+), 18 deletions(-) diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 7c404cdb6..5cb96bdec 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -1052,6 +1052,8 @@ valid examples: Quest const* linkedQuest; SpellEntry const *linkedSpell; AchievementEntry const* linkedAchievement; + ItemRandomPropertiesEntry const* itemProperty; + ItemRandomSuffixEntry const* itemSuffix; while(!reader.eof()) { @@ -1061,6 +1063,8 @@ valid examples: linkedQuest = NULL; linkedSpell = NULL; linkedAchievement = NULL; + itemProperty = NULL; + itemSuffix = NULL; reader.ignore(255, '|'); } @@ -1177,9 +1181,47 @@ valid examples: return false; } - char c = reader.peek(); + // the itementry is followed by several integers which describe an instance of this item - // ignore enchants etc. + // position relative after itemEntry + const uint8 randomPropertyPosition = 6; + + int32 propertyId = 0; + bool negativeNumber = false; + char c; + for(uint8 i=0; i='0' && c<='9') + { + propertyId*=10; + propertyId += c-'0'; + } else if(c == '-') + negativeNumber = true; + else + return false; + } + } + if (negativeNumber) + propertyId *= -1; + + if (propertyId > 0) + { + itemProperty = sItemRandomPropertiesStore.LookupEntry(propertyId); + if (!itemProperty) + return false; + } + else if(propertyId < 0) + { + itemSuffix = sItemRandomSuffixStore.LookupEntry(-propertyId); + if (!itemSuffix) + return false; + } + + // ignore other integers while ((c >= '0' && c <= '9') || c== ':') { reader.ignore(1); @@ -1448,22 +1490,34 @@ valid examples: } else if(linkedItem) { - if (strcmp(linkedItem->Name1, buffer) != 0) + char* const* suffix = itemSuffix?itemSuffix->nameSuffix:(itemProperty?itemProperty->nameSuffix:NULL); + + std::string expectedName = std::string(linkedItem->Name1); + if (suffix) + { + expectedName += " "; + expectedName += suffix[LOCALE_enUS]; + } + + if (expectedName != buffer) { ItemLocale const *il = objmgr.GetItemLocale(linkedItem->ItemId); - if (!il) - { -#ifdef MANGOS_DEBUG - sLog.outBasic("ChatHandler::isValidChatMessage linked item name doesn't is wrong and there is no localization"); -#endif - return false; - } - bool foundName = false; - for(uint8 i=0; iName.size(); ++i) + for(uint8 i=LOCALE_koKR; iName[i] == buffer) + int8 dbIndex = objmgr.GetIndexForLocale(LocaleConstant(i)); + if (dbIndex == -1 || il == NULL || dbIndex >= il->Name.size()) + // using strange database/client combinations can lead to this case + expectedName = linkedItem->Name1; + else + expectedName = il->Name[dbIndex]; + if (suffix) + { + expectedName += " "; + expectedName += suffix[i]; + } + if ( expectedName == buffer) { foundName = true; break; diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index ce364eba9..d017c6b78 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -1027,14 +1027,14 @@ struct ItemRandomPropertiesEntry uint32 ID; // 0 m_ID //char* internalName // 1 m_Name uint32 enchant_id[5]; // 2-6 m_Enchantment - //char* nameSuffix[16] // 7-22 m_name_lang + char* nameSuffix[16]; // 7-22 m_name_lang // 23 name flags }; struct ItemRandomSuffixEntry { uint32 ID; // 0 m_ID - //char* name[16] // 1-16 m_name_lang + char* nameSuffix[16]; // 1-16 m_name_lang // 17, name flags // 18 m_internalName uint32 enchant_id[5]; // 19-21 m_enchantment diff --git a/src/game/DBCfmt.h b/src/game/DBCfmt.h index 32c18ecfa..6073fb663 100644 --- a/src/game/DBCfmt.h +++ b/src/game/DBCfmt.h @@ -67,8 +67,8 @@ const char ItemBagFamilyfmt[]="nxxxxxxxxxxxxxxxxx"; //const char ItemCondExtCostsEntryfmt[]="xiii"; const char ItemExtendedCostEntryfmt[]="niixiiiiiiiiiiix"; const char ItemLimitCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxix"; -const char ItemRandomPropertiesfmt[]="nxiiiiixxxxxxxxxxxxxxxxx"; -const char ItemRandomSuffixfmt[]="nxxxxxxxxxxxxxxxxxxiiiiiiiiii"; +const char ItemRandomPropertiesfmt[]="nxiiiiissssssssssssssssx"; +const char ItemRandomSuffixfmt[]="nssssssssssssssssxxiiiiiiiiii"; const char ItemSetEntryfmt[]="dssssssssssssssssxxxxxxxxxxxxxxxxxxiiiiiiiiiiiiiiiiii"; const char LockEntryfmt[]="niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx"; const char MailTemplateEntryfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 6890630a3..ec8060f5c 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8603" + #define REVISION_NR "8604" #endif // __REVISION_NR_H__ From c5bda77fe2039c9ef0135c5f18cdc064fee37a90 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 9 Oct 2009 10:21:53 +0400 Subject: [PATCH 08/20] [8605] Check unused text/summon data in EventAI scripts. --- src/game/CreatureEventAI.cpp | 19 ++--- src/game/CreatureEventAI.h | 7 +- src/game/CreatureEventAIMgr.cpp | 120 ++++++++++++++++++++++++++------ src/game/CreatureEventAIMgr.h | 7 +- src/game/Level3.cpp | 4 +- src/game/World.cpp | 4 +- src/shared/revision_nr.h | 2 +- 7 files changed, 119 insertions(+), 44 deletions(-) diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp index 4db0796b2..ef344fe87 100644 --- a/src/game/CreatureEventAI.cpp +++ b/src/game/CreatureEventAI.cpp @@ -345,24 +345,17 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32 { case ACTION_T_TEXT: { - if (!action.text.TextId1) + if (!action.text.TextId[0]) return; int32 temp = 0; - if (action.text.TextId2 && action.text.TextId3) - { - switch( rand()%3 ) - { - case 0: temp = action.text.TextId1; break; - case 1: temp = action.text.TextId2; break; - case 2: temp = action.text.TextId3; break; - } - } - else if (action.text.TextId2 && urand(0,1)) - temp = action.text.TextId2; + if (action.text.TextId[1] && action.text.TextId[2]) + temp = action.text.TextId[rand()%3]; + else if (action.text.TextId[1] && urand(0,1)) + temp = action.text.TextId[1]; else - temp = action.text.TextId1; + temp = action.text.TextId[0]; if (temp) { diff --git a/src/game/CreatureEventAI.h b/src/game/CreatureEventAI.h index 603d88974..092ea1a67 100644 --- a/src/game/CreatureEventAI.h +++ b/src/game/CreatureEventAI.h @@ -185,9 +185,7 @@ struct CreatureEventAI_Action // ACTION_T_TEXT = 1 struct { - int32 TextId1; - int32 TextId2; - int32 TextId3; + int32 TextId[3]; } text; // ACTION_T_SET_FACTION = 2 struct @@ -534,7 +532,8 @@ struct CreatureEventAI_Event CreatureEventAI_Action action[MAX_ACTIONS]; }; //Event_Map -typedef UNORDERED_MAP > CreatureEventAI_Event_Map; +typedef std::vector CreatureEventAI_Event_Vec; +typedef UNORDERED_MAP CreatureEventAI_Event_Map; struct CreatureEventAI_Summon { diff --git a/src/game/CreatureEventAIMgr.cpp b/src/game/CreatureEventAIMgr.cpp index 8a920be00..aa3e219ea 100644 --- a/src/game/CreatureEventAIMgr.cpp +++ b/src/game/CreatureEventAIMgr.cpp @@ -30,7 +30,7 @@ INSTANTIATE_SINGLETON_1(CreatureEventAIMgr); // ------------------- -void CreatureEventAIMgr::LoadCreatureEventAI_Texts() +void CreatureEventAIMgr::LoadCreatureEventAI_Texts(bool check_entry_use) { // Drop Existing Text Map, only done once and we are ready to add data from multiple sources. m_CreatureEventAI_TextMap.clear(); @@ -97,6 +97,9 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Texts() delete result; + if(check_entry_use) + CheckUnusedAITexts(); + sLog.outString(); sLog.outString(">> Loaded %u additional CreatureEventAI Texts data.", count); } @@ -107,11 +110,46 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Texts() sLog.outString(); sLog.outString(">> Loaded 0 additional CreatureEventAI Texts data. DB table `creature_ai_texts` is empty."); } +} +void CreatureEventAIMgr::CheckUnusedAITexts() +{ + std::set idx_set; + // check not used strings this is negative range + for(CreatureEventAI_TextMap::const_iterator itr = m_CreatureEventAI_TextMap.begin(); itr != m_CreatureEventAI_TextMap.end(); ++itr) + idx_set.insert(itr->first); + + for(CreatureEventAI_Event_Map::const_iterator itr = m_CreatureEventAI_Event_Map.begin(); itr != m_CreatureEventAI_Event_Map.end(); ++itr) + { + for(size_t i = 0; i < itr->second.size(); ++i) + { + CreatureEventAI_Event const& event = itr->second[i]; + + for(int j = 0; j < MAX_ACTIONS; ++j) + { + CreatureEventAI_Action const& action = event.action[j]; + switch(action.type) + { + case ACTION_T_TEXT: + { + for(int k = 0; k < 3; ++k) + if (action.text.TextId[k]) + idx_set.erase(action.text.TextId[k]); + break; + } + default: break; + } + + } + } + } + + for(std::set::const_iterator itr = idx_set.begin(); itr != idx_set.end(); ++itr) + sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` but not used in EventAI scripts.",*itr); } // ------------------- -void CreatureEventAIMgr::LoadCreatureEventAI_Summons() +void CreatureEventAIMgr::LoadCreatureEventAI_Summons(bool check_entry_use) { //Drop Existing EventSummon Map @@ -151,6 +189,9 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Summons() delete result; + if(check_entry_use) + CheckUnusedAISummons(); + sLog.outString(); sLog.outString(">> Loaded %u CreatureEventAI summon definitions", Count); }else @@ -160,7 +201,41 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Summons() sLog.outString(); sLog.outString(">> Loaded 0 CreatureEventAI Summon definitions. DB table `creature_ai_summons` is empty."); } +} +void CreatureEventAIMgr::CheckUnusedAISummons() +{ + std::set idx_set; + // check not used strings this is negative range + for(CreatureEventAI_Summon_Map::const_iterator itr = m_CreatureEventAI_Summon_Map.begin(); itr != m_CreatureEventAI_Summon_Map.end(); ++itr) + idx_set.insert(itr->first); + + for(CreatureEventAI_Event_Map::const_iterator itr = m_CreatureEventAI_Event_Map.begin(); itr != m_CreatureEventAI_Event_Map.end(); ++itr) + { + for(size_t i = 0; i < itr->second.size(); ++i) + { + CreatureEventAI_Event const& event = itr->second[i]; + + for(int j = 0; j < MAX_ACTIONS; ++j) + { + CreatureEventAI_Action const& action = event.action[j]; + switch(action.type) + { + case ACTION_T_SUMMON_ID: + { + if (action.summon_id.spawnId) + idx_set.erase(action.summon_id.spawnId); + break; + } + default: break; + } + + } + } + } + + for(std::set::const_iterator itr = idx_set.begin(); itr != idx_set.end(); ++itr) + sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_summons` but not used in EventAI scripts.",*itr); } // ------------------- @@ -421,26 +496,28 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() break; case ACTION_T_TEXT: { - if (action.text.TextId1 < 0) + bool not_set = false; + for(int k = 0; k < 3; ++k) { - if (m_CreatureEventAI_TextMap.find(action.text.TextId1) == m_CreatureEventAI_TextMap.end()) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 refrences non-existing entry in texts table.", i, j+1); - } - if (action.text.TextId2 < 0) - { - if (m_CreatureEventAI_TextMap.find(action.text.TextId2) == m_CreatureEventAI_TextMap.end()) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u param2 refrences non-existing entry in texts table.", i, j+1); + if (action.text.TextId[k]) + { + if (k > 0 && not_set) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u has param%d, but it follow after not set param. Required for randomized text.", i, j+1, k+1); - if (!action.text.TextId1) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u has param2, but param1 is not set. Required for randomized text.", i, j+1); - } - if (action.text.TextId3 < 0) - { - if (m_CreatureEventAI_TextMap.find(action.text.TextId3) == m_CreatureEventAI_TextMap.end()) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u param3 refrences non-existing entry in texts table.", i, j+1); - - if (!action.text.TextId1 || !action.text.TextId2) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u has param3, but param1 and/or param2 is not set. Required for randomized text.", i, j+1); + if(!action.text.TextId[k]) + not_set = true; + // range negative + else if(action.text.TextId[k] > MIN_CREATURE_AI_TEXT_STRING_ID || action.text.TextId[k] <= MAX_CREATURE_AI_TEXT_STRING_ID) + { + sLog.outErrorDb("CreatureEventAI: Event %u Action %u param%d references out-of-range entry (%i) in texts table.", i, j+1, k+1, action.text.TextId[k]); + action.text.TextId[k] = 0; + } + else if (m_CreatureEventAI_TextMap.find(action.text.TextId[k]) == m_CreatureEventAI_TextMap.end()) + { + sLog.outErrorDb("CreatureEventAI: Event %u Action %u param%d references non-existing entry (%i) in texts table.", i, j+1, k+1, action.text.TextId[k]); + action.text.TextId[k] = 0; + } + } } break; } @@ -700,6 +777,9 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() delete result; + CheckUnusedAITexts(); + CheckUnusedAISummons(); + sLog.outString(); sLog.outString(">> Loaded %u CreatureEventAI scripts", Count); }else diff --git a/src/game/CreatureEventAIMgr.h b/src/game/CreatureEventAIMgr.h index b4672460c..1345774e6 100644 --- a/src/game/CreatureEventAIMgr.h +++ b/src/game/CreatureEventAIMgr.h @@ -28,8 +28,8 @@ class CreatureEventAIMgr CreatureEventAIMgr(){}; ~CreatureEventAIMgr(){}; - void LoadCreatureEventAI_Texts(); - void LoadCreatureEventAI_Summons(); + void LoadCreatureEventAI_Texts(bool check_entry_use); + void LoadCreatureEventAI_Summons(bool check_entry_use); void LoadCreatureEventAI_Scripts(); CreatureEventAI_Event_Map const& GetCreatureEventAIMap() const { return m_CreatureEventAI_Event_Map; } @@ -37,6 +37,9 @@ class CreatureEventAIMgr CreatureEventAI_TextMap const& GetCreatureEventAITextMap() const { return m_CreatureEventAI_TextMap; } private: + void CheckUnusedAITexts(); + void CheckUnusedAISummons(); + CreatureEventAI_Event_Map m_CreatureEventAI_Event_Map; CreatureEventAI_Summon_Map m_CreatureEventAI_Summon_Map; CreatureEventAI_TextMap m_CreatureEventAI_TextMap; diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 35164c1b7..27abeb0eb 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -647,7 +647,7 @@ bool ChatHandler::HandleReloadEventAITextsCommand(const char* arg) { sLog.outString( "Re-Loading Texts from `creature_ai_texts`..."); - CreatureEAI_Mgr.LoadCreatureEventAI_Texts(); + CreatureEAI_Mgr.LoadCreatureEventAI_Texts(true); SendGlobalSysMessage("DB table `creature_ai_texts` reloaded."); return true; } @@ -655,7 +655,7 @@ bool ChatHandler::HandleReloadEventAITextsCommand(const char* arg) bool ChatHandler::HandleReloadEventAISummonsCommand(const char* arg) { sLog.outString( "Re-Loading Summons from `creature_ai_summons`..."); - CreatureEAI_Mgr.LoadCreatureEventAI_Summons(); + CreatureEAI_Mgr.LoadCreatureEventAI_Summons(true); SendGlobalSysMessage("DB table `creature_ai_summons` reloaded."); return true; } diff --git a/src/game/World.cpp b/src/game/World.cpp index b3260ddf4..fb5fb2cd1 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1426,10 +1426,10 @@ void World::SetInitialWorldSettings() objmgr.LoadDbScriptStrings(); sLog.outString( "Loading CreatureEventAI Texts..."); - CreatureEAI_Mgr.LoadCreatureEventAI_Texts(); + CreatureEAI_Mgr.LoadCreatureEventAI_Texts(false); // false, will checked in LoadCreatureEventAI_Scripts sLog.outString( "Loading CreatureEventAI Summons..."); - CreatureEAI_Mgr.LoadCreatureEventAI_Summons(); + CreatureEAI_Mgr.LoadCreatureEventAI_Summons(false); // false, will checked in LoadCreatureEventAI_Scripts sLog.outString( "Loading CreatureEventAI Scripts..."); CreatureEAI_Mgr.LoadCreatureEventAI_Scripts(); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index ec8060f5c..44f845580 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8604" + #define REVISION_NR "8605" #endif // __REVISION_NR_H__ From f591211538803d59cf5d255d77b2469e295e655d Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 9 Oct 2009 13:06:08 +0400 Subject: [PATCH 09/20] [8606] Restore seelction point around dest coordinates for TARGET_RANDOM_NEARBY_DEST Thanks to qsa for pointing to problem. --- src/game/Spell.cpp | 6 ++++-- src/shared/revision_nr.h | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 8a68ea7ff..435f7d205 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1371,8 +1371,10 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) { radius *= sqrt(rand_norm()); // Get a random point in circle. Use sqrt(rand) to correct distribution when converting polar to Cartesian coordinates. float angle = 2.0 * M_PI * rand_norm(); - float dest_x, dest_y, dest_z; - m_caster->GetClosePoint(dest_x, dest_y, dest_z, 0.0f, radius, angle); + float dest_x = m_targets.m_destX + cos(angle) * radius; + float dest_y = m_targets.m_destY + sin(angle) * radius; + float dest_z = m_caster->GetPositionZ(); + m_caster->UpdateGroundPositionZ(dest_x, dest_y, dest_z); m_targets.setDestination(dest_x, dest_y, dest_z); if (radius > 0.0f) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 44f845580..58e972144 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8605" + #define REVISION_NR "8606" #endif // __REVISION_NR_H__ From ed5130c1c1a19f3ece72a40d7437f3667d75bf3a Mon Sep 17 00:00:00 2001 From: balrok Date: Fri, 9 Oct 2009 14:31:44 +0200 Subject: [PATCH 10/20] [8607] more userfriendly eventcommands .event start/stop will now output the started/stopped eventame+id .event activelist got renamed to .event list with optional parameter "all" so .event list - will list all active events and .event list all - will list all events including inactive ones --- sql/mangos.sql | 6 ++++-- sql/updates/8607_01_mangos_string.sql | 6 ++++++ sql/updates/8607_02_mangos_command.sql | 6 ++++++ sql/updates/Makefile.am | 4 ++++ src/game/Chat.cpp | 2 +- src/game/Chat.h | 2 +- src/game/Language.h | 4 +++- src/game/Level2.cpp | 26 +++++++++++++++++++++----- src/shared/revision_nr.h | 2 +- src/shared/revision_sql.h | 2 +- 10 files changed, 48 insertions(+), 12 deletions(-) create mode 100644 sql/updates/8607_01_mangos_string.sql create mode 100644 sql/updates/8607_02_mangos_command.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index 055418eeb..08f7f2bd8 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -24,7 +24,7 @@ CREATE TABLE `db_version` ( `version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL, `cache_id` int(10) default '0', - `required_8600_01_mangos_command` bit(1) default NULL + `required_8607_02_mangos_command` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -392,7 +392,7 @@ INSERT INTO `command` VALUES ('dismount',0,'Syntax: .dismount\r\n\r\nDismount you, if you are mounted.'), ('distance',3,'Syntax: .distance [$name/$link]\r\n\r\nDisplay the distance from your character to the selected creature/player, or player with name $name, or player/creature/gameobject pointed to shift-link with guid.'), ('event',2,'Syntax: .event #event_id\r\nShow details about event with #event_id.'), -('event activelist',2,'Syntax: .event activelist\r\nShow list of currently active events.'), +('event list',2,'Syntax: .event list\r\nShow list of currently active events.\r\nShow list of all events'), ('event start',2,'Syntax: .event start #event_id\r\nStart event #event_id. Set start time for event to current moment (change not saved in DB).'), ('event stop',2,'Syntax: .event stop #event_id\r\nStop event #event_id. Set start time for event to time in past that make current moment is event stop time (change not saved in DB).'), ('explorecheat',3,'Syntax: .explorecheat #flag\r\n\r\nReveal or hide all maps for the selected player. If no player is selected, hide or reveal maps to you.\r\n\r\nUse a #flag of value 1 to reveal, use a #flag value of 0 to hide all maps.'), @@ -3215,6 +3215,8 @@ INSERT INTO `mangos_string` VALUES (1127,'Talents of %s\'s pet reset.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1128,'%d - |cffffffff|Htaxinode:%u|h[%s %s]|h|r (Map:%u X:%f Y:%f Z:%f)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1129,'%d - %s %s (Map:%u X:%f Y:%f Z:%f)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1130,'event started %u "%s"',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1131,'event stopped %u "%s"',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1200,'You try to view cinemitic %u but it doesn\'t exist.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1201,'You try to view movie %u but it doesn\'t exist.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); /*!40000 ALTER TABLE `mangos_string` ENABLE KEYS */; diff --git a/sql/updates/8607_01_mangos_string.sql b/sql/updates/8607_01_mangos_string.sql new file mode 100644 index 000000000..1120d6d4e --- /dev/null +++ b/sql/updates/8607_01_mangos_string.sql @@ -0,0 +1,6 @@ +ALTER TABLE db_version CHANGE COLUMN required_8600_01_mangos_command required_8607_01_mangos_string bit; + +DELETE FROM mangos_string WHERE entry IN(1130, 1131); +INSERT INTO mangos_string VALUES +(1130,'event started %u "%s"',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1131,'event stopped %u "%s"',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/8607_02_mangos_command.sql b/sql/updates/8607_02_mangos_command.sql new file mode 100644 index 000000000..f04ddf1a5 --- /dev/null +++ b/sql/updates/8607_02_mangos_command.sql @@ -0,0 +1,6 @@ +ALTER TABLE db_version CHANGE COLUMN required_8607_01_mangos_string required_8607_02_mangos_command bit; + +DELETE FROM command where name='event activelist'; + +INSERT INTO `command` VALUES +('event list',2,'Syntax: .event list\r\nShow list of currently active events.\r\nShow list of all events'); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 5a18403b4..6f25972b9 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -130,6 +130,8 @@ pkgdata_DATA = \ 8589_11_characters_characters.sql \ 8596_01_characters_bugreport.sql \ 8600_01_mangos_command.sql \ + 8607_01_mangos_string.sql \ + 8607_02_mangos_command.sql \ README ## Additional files to include when running 'make dist' @@ -240,4 +242,6 @@ EXTRA_DIST = \ 8589_11_characters_characters.sql \ 8596_01_characters_bugreport.sql \ 8600_01_mangos_command.sql \ + 8607_01_mangos_string.sql \ + 8607_02_mangos_command.sql \ README diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 5cb96bdec..a66c65ca4 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -173,7 +173,7 @@ ChatCommand * ChatHandler::getCommandTable() static ChatCommand eventCommandTable[] = { - { "activelist", SEC_GAMEMASTER, true, &ChatHandler::HandleEventActiveListCommand, "", NULL }, + { "list", SEC_GAMEMASTER, true, &ChatHandler::HandleEventListCommand, "", NULL }, { "start", SEC_GAMEMASTER, true, &ChatHandler::HandleEventStartCommand, "", NULL }, { "stop", SEC_GAMEMASTER, true, &ChatHandler::HandleEventStopCommand, "", NULL }, { "", SEC_GAMEMASTER, true, &ChatHandler::HandleEventInfoCommand, "", NULL }, diff --git a/src/game/Chat.h b/src/game/Chat.h index 45a029346..6e7ee3e89 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -160,7 +160,7 @@ class ChatHandler bool HandleDebugSendSetPhaseShiftCommand(const char * args); bool HandleDebugSendSpellFailCommand(const char* args); - bool HandleEventActiveListCommand(const char* args); + bool HandleEventListCommand(const char* args); bool HandleEventStartCommand(const char* args); bool HandleEventStopCommand(const char* args); bool HandleEventInfoCommand(const char* args); diff --git a/src/game/Language.h b/src/game/Language.h index ae3c251d2..fbf33d2a5 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -765,7 +765,9 @@ enum MangosStrings LANG_RESET_PET_TALENTS_ONLINE = 1127, LANG_TAXINODE_ENTRY_LIST_CHAT = 1128, LANG_TAXINODE_ENTRY_LIST_CONSOLE = 1129, - // Room for more level 3 1130-1199 not used + LANG_EVENT_STARTED = 1130, + LANG_EVENT_STOPPED = 1131, + // Room for more level 3 1132-1199 not used // Debug commands LANG_CINEMATIC_NOT_EXIST = 1200, diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 96b05fc93..fcff303e7 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -3717,24 +3717,38 @@ bool ChatHandler::HandleLookupEventCommand(const char* args) return true; } -bool ChatHandler::HandleEventActiveListCommand(const char* /*args*/) +bool ChatHandler::HandleEventListCommand(const char* args) { uint32 counter = 0; + bool all = false; + std::string arg = args; + if (arg == "all") + all = true; GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); char const* active = GetMangosString(LANG_ACTIVE); + char const* inactive = GetMangosString(LANG_FACTION_INACTIVE); + char const* state = ""; - for(GameEventMgr::ActiveEvents::const_iterator itr = activeEvents.begin(); itr != activeEvents.end(); ++itr ) + for (uint32 event_id = 0; event_id < events.size(); ++event_id) { - uint32 event_id = *itr; + if (activeEvents.find(event_id) == activeEvents.end()) + { + if (!all) + continue; + state = inactive; + } + else + state = active; + GameEventData const& eventData = events[event_id]; if(m_session) - PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,event_id,event_id,eventData.description.c_str(),active ); + PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT, event_id, event_id, eventData.description.c_str(), state); else - PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,event_id,eventData.description.c_str(),active ); + PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE, event_id, eventData.description.c_str(), state); ++counter; } @@ -3831,6 +3845,7 @@ bool ChatHandler::HandleEventStartCommand(const char* args) return false; } + PSendSysMessage(LANG_EVENT_STARTED, event_id, eventData.description.c_str()); gameeventmgr.StartEvent(event_id,true); return true; } @@ -3873,6 +3888,7 @@ bool ChatHandler::HandleEventStopCommand(const char* args) return false; } + PSendSysMessage(LANG_EVENT_STOPPED, event_id, eventData.description.c_str()); gameeventmgr.StopEvent(event_id,true); return true; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 58e972144..619411466 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8606" + #define REVISION_NR "8607" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index 93bae364c..d2277b7bb 100644 --- a/src/shared/revision_sql.h +++ b/src/shared/revision_sql.h @@ -1,6 +1,6 @@ #ifndef __REVISION_SQL_H__ #define __REVISION_SQL_H__ #define REVISION_DB_CHARACTERS "required_8596_01_characters_bugreport" - #define REVISION_DB_MANGOS "required_8600_01_mangos_command" + #define REVISION_DB_MANGOS "required_8607_02_mangos_command" #define REVISION_DB_REALMD "required_8332_01_realmd_realmcharacters" #endif // __REVISION_SQL_H__ From 45f6a474bf9d56905de4b4672c562f0b3900ebcc Mon Sep 17 00:00:00 2001 From: balrok Date: Wed, 7 Oct 2009 11:57:28 +0200 Subject: [PATCH 11/20] [8608] implement BattleGround Alterac Valley sql won't be included - please look at your database providers forum also note, that creature_loot_template id 0 is used for the loot of dead players in this bg (after a player died and you remove insignia from him.. he not only drops money - he drops some random items too) further work must be done in better code for adjusting right levels to creatures - maybe using something similar like it's done in heroic instances also quests and creatures needs some scripts in future thanks to: netsky - initial start of this patch bogie - 2nd person writing on this patch triply, kapatejib, vladimir - code review and suggestions arrai - for his great tool and help and all testers / code contributers - I won't write down a list, else I would forget most probably one ^^ --- sql/mangos.sql | 205 ++++- sql/updates/8608_01_mangos_mangos_string.sql | 41 + .../8608_02_mangos_battleground_events.sql | 182 +++++ sql/updates/Makefile.am | 4 + src/game/BattleGround.cpp | 116 ++- src/game/BattleGround.h | 12 +- src/game/BattleGroundAB.cpp | 7 +- src/game/BattleGroundAV.cpp | 765 +++++++++++++++++- src/game/BattleGroundAV.h | 335 +++++++- src/game/BattleGroundMgr.cpp | 2 +- src/game/Creature.cpp | 3 + src/game/GameObject.cpp | 8 + src/game/Language.h | 51 +- src/game/LootHandler.cpp | 10 + src/game/MiscHandler.cpp | 4 +- src/game/Player.cpp | 173 ++-- src/game/SpellEffects.cpp | 2 +- src/game/Unit.cpp | 10 +- src/shared/revision_nr.h | 2 +- src/shared/revision_sql.h | 2 +- 20 files changed, 1795 insertions(+), 139 deletions(-) create mode 100644 sql/updates/8608_01_mangos_mangos_string.sql create mode 100644 sql/updates/8608_02_mangos_battleground_events.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index 08f7f2bd8..18824e931 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -24,7 +24,7 @@ CREATE TABLE `db_version` ( `version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL, `cache_id` int(10) default '0', - `required_8607_02_mangos_command` bit(1) default NULL + `required_8608_02_mangos_battleground_events` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -256,6 +256,175 @@ INSERT INTO battleground_events (map, event1, event2, description) VALUES (572, 254, 0, 'doors'), (562, 253, 0, 'buffs'), (562, 254, 0, 'doors'); +-- alterac valley +(30, 254, 0, 'Doors'), + +(30, 0, 0, 'Firstaid Station - Alliance assaulted'), +(30, 0, 1, 'Firstaid Station - ALliance control'), +(30, 0, 2, 'Firstaid Station - Horde assaulted'), +(30, 0, 3, 'Firstaid Station - Horde control'), + +(30, 1, 0, 'Stormpike Grave - Alliance assaulted'), +(30, 1, 1, 'Stormpike Grave - ALliance control'), +(30, 1, 2, 'Stormpike Grave - Horde assaulted'), +(30, 1, 3, 'Stormpike Grave - Horde control'), + +(30, 2, 0, 'Stoneheart Grave - Alliance assaulted'), +(30, 2, 1, 'Stoneheart Grave - ALliance control'), +(30, 2, 2, 'Stoneheart Grave - Horde assaulted'), +(30, 2, 3, 'Stoneheart Grave - Horde control'), + +(30, 3, 0, 'Snowfall Grave - Alliance assaulted'), +(30, 3, 1, 'Snowfall Grave - ALliance control'), +(30, 3, 2, 'Snowfall Grave - Horde assaulted'), +(30, 3, 3, 'Snowfall Grave - Horde control'), +(30, 3, 5, 'Snowfall Grave - Neutral control'), + +(30, 4, 0, 'Iceblood Grave - Alliance assaulted'), +(30, 4, 1, 'Iceblood Grave - ALliance control'), +(30, 4, 2, 'Iceblood Grave - Horde assaulted'), +(30, 4, 3, 'Iceblood Grave - Horde control'), + +(30, 5, 0, 'Frostwolf Grave - Alliance assaulted'), +(30, 5, 1, 'Frostwolf Grave - ALliance control'), +(30, 5, 2, 'Frostwolf Grave - Horde assaulted'), +(30, 5, 3, 'Frostwolf Grave - Horde control'), + +(30, 6, 0, 'Frostwolf Hut - Alliance assaulted'), +(30, 6, 1, 'Frostwolf Hut - ALliance control'), +(30, 6, 2, 'Frostwolf Hut - Horde assaulted'), +(30, 6, 3, 'Frostwolf Hut - Horde control'), + +(30, 7, 1, 'Dunbaldar South - ALliance control'), +(30, 7, 2, 'Dunbaldar South - Horde assaulted'), +(30, 7, 3, 'Dunbaldar South - Horde control'), + +(30, 8, 1, 'Dunbaldar North - ALliance control'), +(30, 8, 2, 'Dunbaldar North - Horde assaulted'), +(30, 8, 3, 'Dunbaldar North - Horde control'), + +(30, 9, 1, 'Icewing Bunker - ALliance control'), +(30, 9, 2, 'Icewing Bunker - Horde assaulted'), +(30, 9, 3, 'Icewing Bunker - Horde control'), + +(30, 10, 1, 'Stoneheart Bunker - ALliance control'), +(30, 10, 2, 'Stoneheart Bunker - Horde assaulted'), +(30, 10, 3, 'Stoneheart Bunker - Horde control'), + +(30, 11, 0, 'Iceblood Tower - Alliance assaulted'), +(30, 11, 1, 'Iceblood Tower - ALliance control'), +(30, 11, 3, 'Iceblood Tower - Horde control'), + +(30, 12, 0, 'Tower Point - Alliance assaulted'), +(30, 12, 1, 'Tower Point - ALliance control'), +(30, 12, 3, 'Tower Point - Horde control'), + +(30, 13, 0, 'Frostwolf east Tower - Alliance assaulted'), +(30, 13, 1, 'Frostwolf east Tower - ALliance control'), +(30, 13, 3, 'Frostwolf east Tower - Horde control'), + +(30, 14, 0, 'Frostwolf west Tower - Alliance assaulted'), +(30, 14, 1, 'Frostwolf west Tower - ALliance control'), +(30, 14, 3, 'Frostwolf west Tower - Horde control'), + + +(30, 15, 0, 'Firstaid Station - Alliance Defender Quest0'), +(30, 15, 1, 'Firstaid Station - Alliance Defender Quest1'), +(30, 15, 2, 'Firstaid Station - Alliance Defender Quest2'), +(30, 15, 3, 'Firstaid Station - Alliance Defender Quest3'), +(30, 15, 4, 'Firstaid Station - Horde Defender Quest0'), +(30, 15, 5, 'Firstaid Station - Horde Defender Quest1'), +(30, 15, 6, 'Firstaid Station - Horde Defender Quest2'), +(30, 15, 7, 'Firstaid Station - Horde Defender Quest3'), + +(30, 16, 0, 'Stormpike Grave - Alliance Defender Quest0'), +(30, 16, 1, 'Stormpike Grave - Alliance Defender Quest1'), +(30, 16, 2, 'Stormpike Grave - Alliance Defender Quest2'), +(30, 16, 3, 'Stormpike Grave - Alliance Defender Quest3'), +(30, 16, 4, 'Stormpike Grave - Horde Defender Quest0'), +(30, 16, 5, 'Stormpike Grave - Horde Defender Quest1'), +(30, 16, 6, 'Stormpike Grave - Horde Defender Quest2'), +(30, 16, 7, 'Stormpike Grave - Horde Defender Quest3'), + +(30, 17, 0, 'Stoneheart Grave - Alliance Defender Quest0'), +(30, 17, 1, 'Stoneheart Grave - Alliance Defender Quest1'), +(30, 17, 2, 'Stoneheart Grave - Alliance Defender Quest2'), +(30, 17, 3, 'Stoneheart Grave - Alliance Defender Quest3'), +(30, 17, 4, 'Stoneheart Grave - Horde Defender Quest0'), +(30, 17, 5, 'Stoneheart Grave - Horde Defender Quest1'), +(30, 17, 6, 'Stoneheart Grave - Horde Defender Quest2'), +(30, 17, 7, 'Stoneheart Grave - Horde Defender Quest3'), + +(30, 18, 0, 'Snowfall Grave - Alliance Defender Quest0'), +(30, 18, 1, 'Snowfall Grave - Alliance Defender Quest1'), +(30, 18, 2, 'Snowfall Grave - Alliance Defender Quest2'), +(30, 18, 3, 'Snowfall Grave - Alliance Defender Quest3'), +(30, 18, 4, 'Snowfall Grave - Horde Defender Quest0'), +(30, 18, 5, 'Snowfall Grave - Horde Defender Quest1'), +(30, 18, 6, 'Snowfall Grave - Horde Defender Quest2'), +(30, 18, 7, 'Snowfall Grave - Horde Defender Quest3'), + +(30, 19, 0, 'Iceblood Grave - Alliance Defender Quest0'), +(30, 19, 1, 'Iceblood Grave - Alliance Defender Quest1'), +(30, 19, 2, 'Iceblood Grave - Alliance Defender Quest2'), +(30, 19, 3, 'Iceblood Grave - Alliance Defender Quest3'), +(30, 19, 4, 'Iceblood Grave - Horde Defender Quest0'), +(30, 19, 5, 'Iceblood Grave - Horde Defender Quest1'), +(30, 19, 6, 'Iceblood Grave - Horde Defender Quest2'), +(30, 19, 7, 'Iceblood Grave - Horde Defender Quest3'), + +(30, 20, 0, 'Frostwolf Grave - Alliance Defender Quest0'), +(30, 20, 1, 'Frostwolf Grave - Alliance Defender Quest1'), +(30, 20, 2, 'Frostwolf Grave - Alliance Defender Quest2'), +(30, 20, 3, 'Frostwolf Grave - Alliance Defender Quest3'), +(30, 20, 4, 'Frostwolf Grave - Horde Defender Quest0'), +(30, 20, 5, 'Frostwolf Grave - Horde Defender Quest1'), +(30, 20, 6, 'Frostwolf Grave - Horde Defender Quest2'), +(30, 20, 7, 'Frostwolf Grave - Horde Defender Quest3'), + +(30, 21, 0, 'Frostwolf Hut - Alliance Defender Quest0'), +(30, 21, 1, 'Frostwolf Hut - Alliance Defender Quest1'), +(30, 21, 2, 'Frostwolf Hut - Alliance Defender Quest2'), +(30, 21, 3, 'Frostwolf Hut - Alliance Defender Quest3'), +(30, 21, 4, 'Frostwolf Hut - Horde Defender Quest0'), +(30, 21, 5, 'Frostwolf Hut - Horde Defender Quest1'), +(30, 21, 6, 'Frostwolf Hut - Horde Defender Quest2'), +(30, 21, 7, 'Frostwolf Hut - Horde Defender Quest3'), + +(30, 46, 0, 'North Mine - Alliance Boss'), +(30, 46, 1, 'North Mine - Horde Boss'), +(30, 46, 2, 'North Mine - Neutral Boss'), +(30, 47, 0, 'South Mine - Alliance Boss'), +(30, 47, 1, 'South Mine - Horde Boss'), +(30, 47, 2, 'South Mine - Neutral Boss'), + +(30, 48, 0, 'Alliance Captain'), +(30, 49, 0, 'Horde Captain'), + +(30, 50, 0, 'North Mine - Alliance Control'), +(30, 50, 1, 'North Mine - Horde Control'), +(30, 50, 2, 'North Mine - Neutral Control'), +(30, 51, 0, 'South Mine - Alliance Control'), +(30, 51, 1, 'South Mine - Horde Control'), +(30, 51, 2, 'South Mine - Neutral Control'), + +(30, 52, 0, 'Alliance Marshal - Dunbaldar South'), +(30, 53, 0, 'Alliance Marshal - Dunbaldar North'), +(30, 54, 0, 'Alliance Marshal - Icewing Bunker'), +(30, 55, 0, 'Alliance Marshal - Stoneheart Bunker'), + +(30, 56, 0, 'Horde Marshal - Iceblood Tower'), +(30, 57, 0, 'Horde Marshal - Towerpoint'), +(30, 58, 0, 'Horde Marshal - East Frostwolf Tower'), +(30, 59, 0, 'Horde Marshal - West Frostwolf Tower'), + +(30, 60, 0, 'Herald - that guy who yells all the time ;)'), + +(30, 61, 0, 'Alliance - Boss'), +(30, 62, 0, 'Horde - Boss'), + +(30, 63, 0, 'Alliance - Captain Dead'), +(30, 64, 0, 'Horde - Captain Dead'); /*!40000 ALTER TABLE `battleground_events` ENABLE KEYS */; UNLOCK TABLES; @@ -3155,6 +3324,40 @@ INSERT INTO `mangos_string` VALUES (753,'The battle for Warsong Gulch begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (754,'The battle for Arathi Basin begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (755,'The battle begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(757,'Alliance',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(758,'Horde',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(759,'%s was destroyed by the %s!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(760,'The %s is under attack! If left unchecked, the %s will destroy it!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(761,'The %s was taken by the %s!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(762,'The %s was taken by the %s!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(763,'The %s was taken by the %s!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(764,'The %s is under attack! If left unchecked, the %s will capture it!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(765,'The %s has taken the %s! Its supplies will now be used for reinforcements!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(766,'Irondeep Mine',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(767,'Coldtooth Mine',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(768,'Stormpike Aid Station',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(769,'Dun Baldar South Bunker',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(770,'Dun Baldar North Bunker',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(771,'Stormpike Graveyard',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(772,'Icewing Bunker',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(773,'Stonehearth Graveyard',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(774,'Stonehearth Bunker',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(775,'Snowfall Graveyard',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(776,'Iceblood Tower',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(777,'Iceblood Graveyard',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(778,'Tower Point',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(779,'Frostwolf Graveyard',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(780,'East Frostwolf Tower',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(781,'West Frostwolf Tower',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(782,'Frostwolf Relief Hut',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(783,'2 minutes until the battle for Alterac Valley begins.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(784,'1 minute until the battle for Alterac Valley begins.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(785,'30 seconds until the battle for Alterac Valley begins. Prepare yourselves!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(786,'The battle for Alterac Valley has begun!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(787,'The Alliance Team is running out of reinforcements!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(788,'The Horde Team is running out of reinforcements!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(789,'The Frostwolf General is Dead!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(790,'The Stormpike General is Dead!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (801,'You do not have enough gold',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (802,'You do not have enough free slots',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (803,'Your partner does not have enough free bag slots',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), diff --git a/sql/updates/8608_01_mangos_mangos_string.sql b/sql/updates/8608_01_mangos_mangos_string.sql new file mode 100644 index 000000000..c402c0f8d --- /dev/null +++ b/sql/updates/8608_01_mangos_mangos_string.sql @@ -0,0 +1,41 @@ +ALTER TABLE db_version CHANGE COLUMN required_8607_02_mangos_command required_8608_01_mangos_mangos_string bit; + +DELETE FROM mangos_string WHERE entry>756 and entry<791; +DELETE FROM mangos_string WHERE entry=752 or entry=753; +INSERT INTO mangos_string VALUES +(752,'Only the Alliance can use that portal',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(753,'Only the Horde can use that portal',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(757,'Alliance',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(758,'Horde',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(759,'%s was destroyed by the %s!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(760,'The %s is under attack! If left unchecked, the %s will destroy it!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(761,'The %s was taken by the %s!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(762,'The %s was taken by the %s!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(763,'The %s was taken by the %s!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(764,'The %s is under attack! If left unchecked, the %s will capture it!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(765,'The %s has taken the %s! Its supplies will now be used for reinforcements!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(766,'Irondeep Mine',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(767,'Coldtooth Mine',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(768,'Stormpike Aid Station',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(769,'Dun Baldar South Bunker',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(770,'Dun Baldar North Bunker',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(771,'Stormpike Graveyard',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(772,'Icewing Bunker',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(773,'Stonehearth Graveyard',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(774,'Stonehearth Bunker',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(775,'Snowfall Graveyard',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(776,'Iceblood Tower',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(777,'Iceblood Graveyard',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(778,'Tower Point',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(779,'Frostwolf Graveyard',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(780,'East Frostwolf Tower',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(781,'West Frostwolf Tower',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(782,'Frostwolf Relief Hut',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(783,'2 minutes until the battle for Alterac Valley begins.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(784,'1 minute until the battle for Alterac Valley begins.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(785,'30 seconds until the battle for Alterac Valley begins. Prepare yourselves!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(786,'The battle for Alterac Valley has begun!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(787,'The Alliance Team is running out of reinforcements!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(788,'The Horde Team is running out of reinforcements!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(789,'The Frostwolf General is Dead!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(790,'The Stormpike General is Dead!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/8608_02_mangos_battleground_events.sql b/sql/updates/8608_02_mangos_battleground_events.sql new file mode 100644 index 000000000..3d75c5b8d --- /dev/null +++ b/sql/updates/8608_02_mangos_battleground_events.sql @@ -0,0 +1,182 @@ +ALTER TABLE db_version CHANGE COLUMN required_8608_01_mangos_mangos_string required_8608_02_mangos_battleground_events bit; + +DELETE FROM battleground_events WHERE map = 30; +INSERT INTO battleground_events (map, event1, event2, description) VALUES +-- alterac valley + (30, 254, 0, 'Doors'), + + (30, 0, 0, 'Firstaid Station - Alliance assaulted'), + (30, 0, 1, 'Firstaid Station - ALliance control'), + (30, 0, 2, 'Firstaid Station - Horde assaulted'), + (30, 0, 3, 'Firstaid Station - Horde control'), + + (30, 1, 0, 'Stormpike Grave - Alliance assaulted'), + (30, 1, 1, 'Stormpike Grave - ALliance control'), + (30, 1, 2, 'Stormpike Grave - Horde assaulted'), + (30, 1, 3, 'Stormpike Grave - Horde control'), + + (30, 2, 0, 'Stoneheart Grave - Alliance assaulted'), + (30, 2, 1, 'Stoneheart Grave - ALliance control'), + (30, 2, 2, 'Stoneheart Grave - Horde assaulted'), + (30, 2, 3, 'Stoneheart Grave - Horde control'), + + (30, 3, 0, 'Snowfall Grave - Alliance assaulted'), + (30, 3, 1, 'Snowfall Grave - ALliance control'), + (30, 3, 2, 'Snowfall Grave - Horde assaulted'), + (30, 3, 3, 'Snowfall Grave - Horde control'), + (30, 3, 5, 'Snowfall Grave - Neutral control'), + + (30, 4, 0, 'Iceblood Grave - Alliance assaulted'), + (30, 4, 1, 'Iceblood Grave - ALliance control'), + (30, 4, 2, 'Iceblood Grave - Horde assaulted'), + (30, 4, 3, 'Iceblood Grave - Horde control'), + + (30, 5, 0, 'Frostwolf Grave - Alliance assaulted'), + (30, 5, 1, 'Frostwolf Grave - ALliance control'), + (30, 5, 2, 'Frostwolf Grave - Horde assaulted'), + (30, 5, 3, 'Frostwolf Grave - Horde control'), + + (30, 6, 0, 'Frostwolf Hut - Alliance assaulted'), + (30, 6, 1, 'Frostwolf Hut - ALliance control'), + (30, 6, 2, 'Frostwolf Hut - Horde assaulted'), + (30, 6, 3, 'Frostwolf Hut - Horde control'), + + -- (30, 7, 0, 'Dunbaldar South - Alliance assaulted'), + (30, 7, 1, 'Dunbaldar South - ALliance control'), + (30, 7, 2, 'Dunbaldar South - Horde assaulted'), + (30, 7, 3, 'Dunbaldar South - Horde control'), + + -- (30, 8, 0, 'Dunbaldar North - Alliance assaulted'), + (30, 8, 1, 'Dunbaldar North - ALliance control'), + (30, 8, 2, 'Dunbaldar North - Horde assaulted'), + (30, 8, 3, 'Dunbaldar North - Horde control'), + + -- (30, 9, 0, 'Icewing Bunker - Alliance assaulted'), + (30, 9, 1, 'Icewing Bunker - ALliance control'), + (30, 9, 2, 'Icewing Bunker - Horde assaulted'), + (30, 9, 3, 'Icewing Bunker - Horde control'), + + -- (30, 10, 0, 'Stoneheart Bunker - Alliance assaulted'), + (30, 10, 1, 'Stoneheart Bunker - ALliance control'), + (30, 10, 2, 'Stoneheart Bunker - Horde assaulted'), + (30, 10, 3, 'Stoneheart Bunker - Horde control'), + + (30, 11, 0, 'Iceblood Tower - Alliance assaulted'), + (30, 11, 1, 'Iceblood Tower - ALliance control'), + -- (30, 11, 2, 'Iceblood Tower - Horde assaulted'), + (30, 11, 3, 'Iceblood Tower - Horde control'), + + (30, 12, 0, 'Tower Point - Alliance assaulted'), + (30, 12, 1, 'Tower Point - ALliance control'), + -- (30, 12, 2, 'Tower Point - Horde assaulted'), + (30, 12, 3, 'Tower Point - Horde control'), + + (30, 13, 0, 'Frostwolf east Tower - Alliance assaulted'), + (30, 13, 1, 'Frostwolf east Tower - ALliance control'), + -- (30, 13, 2, 'Frostwolf east Tower - Horde assaulted'), + (30, 13, 3, 'Frostwolf east Tower - Horde control'), + + (30, 14, 0, 'Frostwolf west Tower - Alliance assaulted'), + (30, 14, 1, 'Frostwolf west Tower - ALliance control'), + -- (30, 14, 2, 'Frostwolf west Tower - Horde assaulted'), + (30, 14, 3, 'Frostwolf west Tower - Horde control'), + + + (30, 15, 0, 'Firstaid Station - Alliance Defender Quest0'), + (30, 15, 1, 'Firstaid Station - Alliance Defender Quest1'), + (30, 15, 2, 'Firstaid Station - Alliance Defender Quest2'), + (30, 15, 3, 'Firstaid Station - Alliance Defender Quest3'), + (30, 15, 4, 'Firstaid Station - Horde Defender Quest0'), + (30, 15, 5, 'Firstaid Station - Horde Defender Quest1'), + (30, 15, 6, 'Firstaid Station - Horde Defender Quest2'), + (30, 15, 7, 'Firstaid Station - Horde Defender Quest3'), + + (30, 16, 0, 'Stormpike Grave - Alliance Defender Quest0'), + (30, 16, 1, 'Stormpike Grave - Alliance Defender Quest1'), + (30, 16, 2, 'Stormpike Grave - Alliance Defender Quest2'), + (30, 16, 3, 'Stormpike Grave - Alliance Defender Quest3'), + (30, 16, 4, 'Stormpike Grave - Horde Defender Quest0'), + (30, 16, 5, 'Stormpike Grave - Horde Defender Quest1'), + (30, 16, 6, 'Stormpike Grave - Horde Defender Quest2'), + (30, 16, 7, 'Stormpike Grave - Horde Defender Quest3'), + + (30, 17, 0, 'Stoneheart Grave - Alliance Defender Quest0'), + (30, 17, 1, 'Stoneheart Grave - Alliance Defender Quest1'), + (30, 17, 2, 'Stoneheart Grave - Alliance Defender Quest2'), + (30, 17, 3, 'Stoneheart Grave - Alliance Defender Quest3'), + (30, 17, 4, 'Stoneheart Grave - Horde Defender Quest0'), + (30, 17, 5, 'Stoneheart Grave - Horde Defender Quest1'), + (30, 17, 6, 'Stoneheart Grave - Horde Defender Quest2'), + (30, 17, 7, 'Stoneheart Grave - Horde Defender Quest3'), + + (30, 18, 0, 'Snowfall Grave - Alliance Defender Quest0'), + (30, 18, 1, 'Snowfall Grave - Alliance Defender Quest1'), + (30, 18, 2, 'Snowfall Grave - Alliance Defender Quest2'), + (30, 18, 3, 'Snowfall Grave - Alliance Defender Quest3'), + (30, 18, 4, 'Snowfall Grave - Horde Defender Quest0'), + (30, 18, 5, 'Snowfall Grave - Horde Defender Quest1'), + (30, 18, 6, 'Snowfall Grave - Horde Defender Quest2'), + (30, 18, 7, 'Snowfall Grave - Horde Defender Quest3'), + + (30, 19, 0, 'Iceblood Grave - Alliance Defender Quest0'), + (30, 19, 1, 'Iceblood Grave - Alliance Defender Quest1'), + (30, 19, 2, 'Iceblood Grave - Alliance Defender Quest2'), + (30, 19, 3, 'Iceblood Grave - Alliance Defender Quest3'), + (30, 19, 4, 'Iceblood Grave - Horde Defender Quest0'), + (30, 19, 5, 'Iceblood Grave - Horde Defender Quest1'), + (30, 19, 6, 'Iceblood Grave - Horde Defender Quest2'), + (30, 19, 7, 'Iceblood Grave - Horde Defender Quest3'), + + (30, 20, 0, 'Frostwolf Grave - Alliance Defender Quest0'), + (30, 20, 1, 'Frostwolf Grave - Alliance Defender Quest1'), + (30, 20, 2, 'Frostwolf Grave - Alliance Defender Quest2'), + (30, 20, 3, 'Frostwolf Grave - Alliance Defender Quest3'), + (30, 20, 4, 'Frostwolf Grave - Horde Defender Quest0'), + (30, 20, 5, 'Frostwolf Grave - Horde Defender Quest1'), + (30, 20, 6, 'Frostwolf Grave - Horde Defender Quest2'), + (30, 20, 7, 'Frostwolf Grave - Horde Defender Quest3'), + + (30, 21, 0, 'Frostwolf Hut - Alliance Defender Quest0'), + (30, 21, 1, 'Frostwolf Hut - Alliance Defender Quest1'), + (30, 21, 2, 'Frostwolf Hut - Alliance Defender Quest2'), + (30, 21, 3, 'Frostwolf Hut - Alliance Defender Quest3'), + (30, 21, 4, 'Frostwolf Hut - Horde Defender Quest0'), + (30, 21, 5, 'Frostwolf Hut - Horde Defender Quest1'), + (30, 21, 6, 'Frostwolf Hut - Horde Defender Quest2'), + (30, 21, 7, 'Frostwolf Hut - Horde Defender Quest3'), + + + (30, 46, 0, 'North Mine - Alliance Boss'), + (30, 46, 1, 'North Mine - Horde Boss'), + (30, 46, 2, 'North Mine - Neutral Boss'), + (30, 47, 0, 'South Mine - Alliance Boss'), + (30, 47, 1, 'South Mine - Horde Boss'), + (30, 47, 2, 'South Mine - Neutral Boss'), + + (30, 48, 0, 'Alliance Captain'), + (30, 49, 0, 'Horde Captain'), + + (30, 50, 0, 'North Mine - Alliance Control'), + (30, 50, 1, 'North Mine - Horde Control'), + (30, 50, 2, 'North Mine - Neutral Control'), + (30, 51, 0, 'South Mine - Alliance Control'), + (30, 51, 1, 'South Mine - Horde Control'), + (30, 51, 2, 'South Mine - Neutral Control'), + + (30, 52, 0, 'Alliance Marshal - Dunbaldar South'), + (30, 53, 0, 'Alliance Marshal - Dunbaldar North'), + (30, 54, 0, 'Alliance Marshal - Icewing Bunker'), + (30, 55, 0, 'Alliance Marshal - Stoneheart Bunker'), + + (30, 56, 0, 'Horde Marshal - Iceblood Tower'), + (30, 57, 0, 'Horde Marshal - Towerpoint'), + (30, 58, 0, 'Horde Marshal - East Frostwolf Tower'), + (30, 59, 0, 'Horde Marshal - West Frostwolf Tower'), + + (30, 60, 0, 'Herald - that guy who yells all the time ;)'), + + (30, 61, 0, 'Alliance - Boss'), + (30, 62, 0, 'Horde - Boss'), + + (30, 63, 0, 'Alliance - Captain Dead'), + (30, 64, 0, 'Horde - Captain Dead'); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 6f25972b9..ce06e24c8 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -132,6 +132,8 @@ pkgdata_DATA = \ 8600_01_mangos_command.sql \ 8607_01_mangos_string.sql \ 8607_02_mangos_command.sql \ + 8608_01_mangos_mangos_string.sql \ + 8608_02_mangos_battleground_events.sql \ README ## Additional files to include when running 'make dist' @@ -244,4 +246,6 @@ EXTRA_DIST = \ 8600_01_mangos_command.sql \ 8607_01_mangos_string.sql \ 8607_02_mangos_command.sql \ + 8608_01_mangos_mangos_string.sql \ + 8608_02_mangos_battleground_events.sql \ README diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 7e3bc1cf8..e72d77cf7 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -80,6 +80,53 @@ namespace MaNGOS va_list* i_args; }; + class BattleGroundYellBuilder + { + public: + BattleGroundYellBuilder(uint32 language, int32 textId, Creature const* source, va_list* args = NULL) + : i_language(language), i_textId(textId), i_source(source), i_args(args) {} + void operator()(WorldPacket& data, int32 loc_idx) + { + char const* text = objmgr.GetMangosString(i_textId,loc_idx); + + if(i_args) + { + // we need copy va_list before use or original va_list will corrupted + va_list ap; + va_copy(ap,*i_args); + + char str [2048]; + vsnprintf(str,2048,text, ap ); + va_end(ap); + + do_helper(data,&str[0]); + } + else + do_helper(data,text); + } + private: + void do_helper(WorldPacket& data, char const* text) + { + //copyied from BuildMonsterChat + data << (uint8)CHAT_MSG_MONSTER_YELL; + data << (uint32)i_language; + data << (uint64)i_source->GetGUID(); + data << (uint32)0; //2.1.0 + data << (uint32)(strlen(i_source->GetName())+1); + data << i_source->GetName(); + data << (uint64)0; //Unit Target - isn't important for bgs + data << (uint32)strlen(text)+1; + data << text; + data << (uint8)0; // ChatTag - for bgs allways 0? + } + + uint32 i_language; + int32 i_textId; + Creature const* i_source; + va_list* i_args; + }; + + class BattleGround2ChatBuilder { public: @@ -113,6 +160,40 @@ namespace MaNGOS int32 i_arg1; int32 i_arg2; }; + + class BattleGround2YellBuilder + { + public: + BattleGround2YellBuilder(uint32 language, int32 textId, Creature const* source, int32 arg1, int32 arg2) + : i_language(language), i_textId(textId), i_source(source), i_arg1(arg1), i_arg2(arg2) {} + void operator()(WorldPacket& data, int32 loc_idx) + { + char const* text = objmgr.GetMangosString(i_textId,loc_idx); + char const* arg1str = i_arg1 ? objmgr.GetMangosString(i_arg1,loc_idx) : ""; + char const* arg2str = i_arg2 ? objmgr.GetMangosString(i_arg2,loc_idx) : ""; + + char str [2048]; + snprintf(str,2048,text, arg1str, arg2str ); + //copyied from BuildMonsterChat + data << (uint8)CHAT_MSG_MONSTER_YELL; + data << (uint32)i_language; + data << (uint64)i_source->GetGUID(); + data << (uint32)0; //2.1.0 + data << (uint32)(strlen(i_source->GetName())+1); + data << i_source->GetName(); + data << (uint64)0; //Unit Target - isn't important for bgs + data << (uint32)strlen(str)+1; + data << str; + data << (uint8)0; // ChatTag - for bgs allways 0? + } + private: + + uint32 i_language; + int32 i_textId; + Creature const* i_source; + int32 i_arg1; + int32 i_arg2; + }; } // namespace MaNGOS template @@ -664,6 +745,12 @@ void BattleGround::EndBattleGround(uint32 winner) plr->ResurrectPlayer(1.0f); plr->SpawnCorpseBones(); } + else + { + //needed cause else in av some creatures will kill the players at the end + plr->CombatStop(); + plr->getHostilRefManager().deleteReferences(); + } //this line is obsolete - team is set ALWAYS //if(!team) team = plr->GetTeam(); @@ -1381,6 +1468,13 @@ void BattleGround::OnObjectDBLoad(Creature* creature) SpawnBGCreature(creature->GetGUID(), RESPAWN_ONE_DAY); } +uint64 BattleGround::GetSingleCreatureGuid(uint8 event1, uint8 event2) +{ + BGCreatures::const_iterator itr = m_EventObjects[MAKE_PAIR32(event1, event2)].creatures.begin(); + if (itr != m_EventObjects[MAKE_PAIR32(event1, event2)].creatures.end()) + return *itr; + return 0; +} void BattleGround::OnObjectDBLoad(GameObject* obj) { @@ -1525,6 +1619,16 @@ void BattleGround::SendMessageToAll(int32 entry, ChatMsg type, Player const* sou BroadcastWorker(bg_do); } +void BattleGround::SendYellToAll(int32 entry, uint32 language, uint64 const& guid) +{ + Creature* source = GetBgMap()->GetCreature(guid); + if(!source) + return; + MaNGOS::BattleGroundYellBuilder bg_builder(language, entry, source); + MaNGOS::LocalizedPacketDo bg_do(bg_builder); + BroadcastWorker(bg_do); +} + void BattleGround::PSendMessageToAll(int32 entry, ChatMsg type, Player const* source, ...) { va_list ap; @@ -1544,6 +1648,16 @@ void BattleGround::SendMessage2ToAll(int32 entry, ChatMsg type, Player const* so BroadcastWorker(bg_do); } +void BattleGround::SendYell2ToAll(int32 entry, uint32 language, uint64 const& guid, int32 arg1, int32 arg2) +{ + Creature* source = GetBgMap()->GetCreature(guid); + if(!source) + return; + MaNGOS::BattleGround2YellBuilder bg_builder(language, entry, source, arg1, arg2); + MaNGOS::LocalizedPacketDo bg_do(bg_builder); + BroadcastWorker(bg_do); +} + void BattleGround::EndNow() { RemoveFromBGFreeSlotQueue(); @@ -1604,8 +1718,6 @@ void BattleGround::HandleTriggerBuff(uint64 const& go_guid) void BattleGround::HandleKillPlayer( Player *player, Player *killer ) { - //keep in mind that for arena this will have to be changed a bit - // add +1 deaths UpdatePlayerScore(player, SCORE_DEATHS, 1); diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index 6c24828ec..31eab6392 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -198,10 +198,7 @@ enum ScoreType SCORE_GRAVEYARDS_DEFENDED = 12, SCORE_TOWERS_ASSAULTED = 13, SCORE_TOWERS_DEFENDED = 14, - SCORE_MINES_CAPTURED = 15, - SCORE_LEADERS_KILLED = 16, - SCORE_SECONDARY_OBJECTIVES = 17 - // TODO : implement them + SCORE_SECONDARY_OBJECTIVES = 15 }; enum ArenaType @@ -439,10 +436,12 @@ class BattleGround void BlockMovement(Player *plr); void SendMessageToAll(int32 entry, ChatMsg type, Player const* source = NULL); + void SendYellToAll(int32 entry, uint32 language, uint64 const& guid); void PSendMessageToAll(int32 entry, ChatMsg type, Player const* source, ... ); // specialized version with 2 string id args void SendMessage2ToAll(int32 entry, ChatMsg type, Player const* source, int32 strId1 = 0, int32 strId2 = 0); + void SendYell2ToAll(int32 entry, uint32 language, uint64 const& guid, int32 arg1, int32 arg2); /* Raid Group */ Group *GetBgRaid(uint32 TeamID) const { return TeamID == ALLIANCE ? m_BgRaids[BG_TEAM_ALLIANCE] : m_BgRaids[BG_TEAM_HORDE]; } @@ -473,6 +472,7 @@ class BattleGround virtual void HandleAreaTrigger(Player* /*Source*/, uint32 /*Trigger*/) {} // must be implemented in BG subclass if need AND call base class generic code virtual void HandleKillPlayer(Player *player, Player *killer); + virtual void HandleKillUnit(Creature* /*unit*/, Player* /*killer*/) { return; }; /* Battleground events */ virtual void EventPlayerDroppedFlag(Player* /*player*/) {} @@ -505,10 +505,14 @@ class BattleGround return false; return m_ActiveEvents[event1] == event2; } + uint64 GetSingleCreatureGuid(uint8 event1, uint8 event2); + void OpenDoorEvent(uint8 event1, uint8 event2 = 0); bool IsDoor(uint8 event1, uint8 event2); /* other things */ + virtual void OnCreatureRespawn(Creature* /*creature*/) {} + void HandleTriggerBuff(uint64 const& go_guid); // TODO: make this protected: diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp index 19d592ae1..ad485cdb8 100644 --- a/src/game/BattleGroundAB.cpp +++ b/src/game/BattleGroundAB.cpp @@ -191,20 +191,17 @@ void BattleGroundAB::RemovePlayer(Player * /*plr*/, uint64 /*guid*/) void BattleGroundAB::HandleAreaTrigger(Player *Source, uint32 Trigger) { - if (GetStatus() != STATUS_IN_PROGRESS) - return; - switch(Trigger) { case 3948: // Arathi Basin Alliance Exit. if (Source->GetTeam() != ALLIANCE) - Source->GetSession()->SendAreaTriggerMessage("Only The Alliance can use that portal"); + Source->GetSession()->SendNotification(LANG_BATTLEGROUND_ONLY_ALLIANCE_USE); else Source->LeaveBattleground(); break; case 3949: // Arathi Basin Horde Exit. if (Source->GetTeam() != HORDE) - Source->GetSession()->SendAreaTriggerMessage("Only The Horde can use that portal"); + Source->GetSession()->SendNotification(LANG_BATTLEGROUND_ONLY_HORDE_USE); else Source->LeaveBattleground(); break; diff --git a/src/game/BattleGroundAV.cpp b/src/game/BattleGroundAV.cpp index 9a52e726f..be20d2831 100644 --- a/src/game/BattleGroundAV.cpp +++ b/src/game/BattleGroundAV.cpp @@ -16,81 +16,390 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "Object.h" #include "Player.h" #include "BattleGround.h" #include "BattleGroundAV.h" +#include "BattleGroundMgr.h" +#include "Creature.h" +#include "GameObject.h" #include "Language.h" +#include "WorldPacket.h" BattleGroundAV::BattleGroundAV() { - - //TODO FIX ME! - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_EY_START_TWO_MINUTES; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_EY_START_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_EY_START_HALF_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_EY_HAS_BEGUN; + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_AV_START_TWO_MINUTES; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_AV_START_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_AV_START_HALF_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_AV_HAS_BEGUN; } BattleGroundAV::~BattleGroundAV() { +} +void BattleGroundAV::HandleKillPlayer(Player *player, Player *killer) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + BattleGround::HandleKillPlayer(player, killer); + UpdateScore(GetTeamIndexByTeamId(player->GetTeam()), -1); +} + +void BattleGroundAV::HandleKillUnit(Creature *creature, Player *killer) +{ + sLog.outDebug("BattleGroundAV: HandleKillUnit %i", creature->GetEntry()); + if (GetStatus() != STATUS_IN_PROGRESS) + return; + uint8 event1 = (sBattleGroundMgr.GetCreatureEventIndex(creature->GetDBTableGUIDLow())).event1; + if (event1 == BG_EVENT_NONE) + return; + switch(event1) + { + case BG_AV_BOSS_A: + CastSpellOnTeam(BG_AV_BOSS_KILL_QUEST_SPELL, HORDE); // this is a spell which finishes a quest where a player has to kill the boss + RewardReputationToTeam(BG_AV_FACTION_H, m_RepBoss, HORDE); + RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_BOSS), HORDE); + SendYellToAll(LANG_BG_AV_H_GENERAL_DEAD, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0)); + EndBattleGround(HORDE); + break; + case BG_AV_BOSS_H: + CastSpellOnTeam(BG_AV_BOSS_KILL_QUEST_SPELL, ALLIANCE); // this is a spell which finishes a quest where a player has to kill the boss + RewardReputationToTeam(BG_AV_FACTION_A, m_RepBoss, ALLIANCE); + RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_BOSS), ALLIANCE); + SendYellToAll(LANG_BG_AV_A_GENERAL_DEAD, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0)); + EndBattleGround(ALLIANCE); + break; + case BG_AV_CAPTAIN_A: + if (IsActiveEvent(BG_AV_NodeEventCaptainDead_A, 0)) + return; + RewardReputationToTeam(BG_AV_FACTION_H, m_RepCaptain, HORDE); + RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_CAPTAIN), HORDE); + UpdateScore(BG_TEAM_ALLIANCE, (-1) * BG_AV_RES_CAPTAIN); + // spawn destroyed aura + SpawnEvent(BG_AV_NodeEventCaptainDead_A, 0, true); + break; + case BG_AV_CAPTAIN_H: + if (IsActiveEvent(BG_AV_NodeEventCaptainDead_H, 0)) + return; + RewardReputationToTeam(BG_AV_FACTION_A, m_RepCaptain, ALLIANCE); + RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_CAPTAIN), ALLIANCE); + UpdateScore(BG_TEAM_HORDE, (-1) * BG_AV_RES_CAPTAIN); + // spawn destroyed aura + SpawnEvent(BG_AV_NodeEventCaptainDead_H, 0, true); + break; + case BG_AV_MINE_BOSSES_NORTH: + ChangeMineOwner(BG_AV_NORTH_MINE, GetTeamIndexByTeamId(killer->GetTeam())); + break; + case BG_AV_MINE_BOSSES_SOUTH: + ChangeMineOwner(BG_AV_SOUTH_MINE, GetTeamIndexByTeamId(killer->GetTeam())); + break; + } +} + +void BattleGroundAV::HandleQuestComplete(uint32 questid, Player *player) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + uint8 team = GetTeamIndexByTeamId(player->GetTeam()); + uint32 reputation = 0; // reputation for the whole team (other reputation must be done in db) + // TODO add events (including quest not available anymore, next quest availabe, go/npc de/spawning) + sLog.outError("BattleGroundAV: Quest %i completed", questid); + switch(questid) + { + case BG_AV_QUEST_A_SCRAPS1: + case BG_AV_QUEST_A_SCRAPS2: + case BG_AV_QUEST_H_SCRAPS1: + case BG_AV_QUEST_H_SCRAPS2: + m_Team_QuestStatus[team][0] += 20; + reputation = 1; + if( m_Team_QuestStatus[team][0] == 500 || m_Team_QuestStatus[team][0] == 1000 || m_Team_QuestStatus[team][0] == 1500 ) //25,50,75 turn ins + { + sLog.outDebug("BattleGroundAV: Quest %i completed starting with unit upgrading..", questid); + for (BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_FROSTWOLF_HUT; ++i) + if (m_Nodes[i].Owner == team && m_Nodes[i].State == POINT_CONTROLLED) + PopulateNode(i); + } + break; + case BG_AV_QUEST_A_COMMANDER1: + case BG_AV_QUEST_H_COMMANDER1: + m_Team_QuestStatus[team][1]++; + reputation = 1; + if (m_Team_QuestStatus[team][1] == 120) + sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid); + break; + case BG_AV_QUEST_A_COMMANDER2: + case BG_AV_QUEST_H_COMMANDER2: + m_Team_QuestStatus[team][2]++; + reputation = 2; + if (m_Team_QuestStatus[team][2] == 60) + sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid); + break; + case BG_AV_QUEST_A_COMMANDER3: + case BG_AV_QUEST_H_COMMANDER3: + m_Team_QuestStatus[team][3]++; + reputation = 5; + RewardReputationToTeam(team, 1, player->GetTeam()); + if (m_Team_QuestStatus[team][1] == 30) + sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid); + break; + case BG_AV_QUEST_A_BOSS1: + case BG_AV_QUEST_H_BOSS1: + m_Team_QuestStatus[team][4] += 4; // there are 2 quests where you can turn in 5 or 1 item.. ( + 4 cause +1 will be done some lines below) + reputation = 4; + case BG_AV_QUEST_A_BOSS2: + case BG_AV_QUEST_H_BOSS2: + m_Team_QuestStatus[team][4]++; + reputation += 1; + if (m_Team_QuestStatus[team][4] >= 200) + sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid); + break; + case BG_AV_QUEST_A_NEAR_MINE: + case BG_AV_QUEST_H_NEAR_MINE: + m_Team_QuestStatus[team][5]++; + reputation = 2; + if (m_Team_QuestStatus[team][5] == 28) + { + sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid); + if (m_Team_QuestStatus[team][6] == 7) + sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here - ground assault ready", questid); + } + break; + case BG_AV_QUEST_A_OTHER_MINE: + case BG_AV_QUEST_H_OTHER_MINE: + m_Team_QuestStatus[team][6]++; + reputation = 3; + if (m_Team_QuestStatus[team][6] == 7) + { + sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid); + if (m_Team_QuestStatus[team][5] == 20) + sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here - ground assault ready", questid); + } + break; + case BG_AV_QUEST_A_RIDER_HIDE: + case BG_AV_QUEST_H_RIDER_HIDE: + m_Team_QuestStatus[team][7]++; + reputation = 1; + if (m_Team_QuestStatus[team][7] == 25) + { + sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid); + if (m_Team_QuestStatus[team][8] == 25) + sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here - rider assault ready", questid); + } + break; + case BG_AV_QUEST_A_RIDER_TAME: + case BG_AV_QUEST_H_RIDER_TAME: + m_Team_QuestStatus[team][8]++; + reputation = 1; + if (m_Team_QuestStatus[team][8] == 25) + { + sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid); + if (m_Team_QuestStatus[team][7] == 25) + sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here - rider assault ready", questid); + } + break; + default: + sLog.outDebug("BattleGroundAV: Quest %i completed but is not interesting for us", questid); + return; + break; + } + if (reputation) + RewardReputationToTeam((player->GetTeam() == ALLIANCE) ? BG_AV_FACTION_A : BG_AV_FACTION_H, reputation, player->GetTeam()); +} + +void BattleGroundAV::UpdateScore(BattleGroundTeamId team, int32 points ) +{ + // note: to remove reinforcements points must be negative, for adding reinforcements points must be positive + assert( team == BG_TEAM_ALLIANCE || team == BG_TEAM_HORDE); + m_TeamScores[team] += points; // m_TeamScores is int32 - so no problems here + + if (points < 0) + { + if (m_TeamScores[team] < 1) + { + m_TeamScores[team] = 0; + // other team will win: + EndBattleGround((team == BG_TEAM_ALLIANCE)? HORDE : ALLIANCE); + } + else if (!m_IsInformedNearLose[team] && m_TeamScores[team] < BG_AV_SCORE_NEAR_LOSE) + { + SendMessageToAll((team == BG_TEAM_HORDE) ? LANG_BG_AV_H_NEAR_LOSE : LANG_BG_AV_A_NEAR_LOSE, CHAT_MSG_BG_SYSTEM_NEUTRAL); + PlaySoundToAll(BG_AV_SOUND_NEAR_LOSE); + m_IsInformedNearLose[team] = true; + } + } + // must be called here, else it could display a negative value + UpdateWorldState(((team == BG_TEAM_HORDE) ? BG_AV_Horde_Score : BG_AV_Alliance_Score), m_TeamScores[team]); +} + +void BattleGroundAV::OnObjectDBLoad(Creature* creature) +{ + uint32 level = creature->getLevel(); + if (level != 0) + level += GetMaxLevel() - 60; // maybe we can do this more generic for custom level - range.. actually it's ok + creature->SetLevel(level); + BattleGround::OnObjectDBLoad(creature); +} + +void BattleGroundAV::OnCreatureRespawn(Creature* creature) +{ + uint32 level = creature->getLevel(); + if (level != 0) + level += GetMaxLevel() - 60; // maybe we can do this more generic for custom level - range.. actually it's ok + creature->SetLevel(level); } void BattleGroundAV::Update(uint32 diff) { BattleGround::Update(diff); + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + // add points from mine owning, and look if the neutral team can reclaim the mine + for(uint8 mine = 0; mine < BG_AV_MAX_MINES; mine++) + { + if (m_Mine_Owner[mine] == BG_TEAM_ALLIANCE || m_Mine_Owner[mine] == BG_TEAM_HORDE) + { + m_Mine_Timer[mine] -=diff; + if (m_Mine_Timer[mine] <= 0) + { + UpdateScore(BattleGroundTeamId(m_Mine_Owner[mine]), 1); + m_Mine_Timer[mine] = BG_AV_MINE_TICK_TIMER; + } + + if (m_Mine_Reclaim_Timer[mine] > diff) + m_Mine_Reclaim_Timer[mine] -= diff; + else + ChangeMineOwner(mine, BG_AV_NEUTRAL_TEAM); + } + } + + // looks for all timers of the nodes and destroy the building (for graveyards the building wont get destroyed, it goes just to the other team + for(BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i < BG_AV_NODES_MAX; ++i) + { + if (m_Nodes[i].State == POINT_ASSAULTED) + { + if (m_Nodes[i].Timer > diff) + m_Nodes[i].Timer -= diff; + else + EventPlayerDestroyedPoint(i); + } + } } void BattleGroundAV::StartingEventCloseDoors() { + sLog.outDebug("BattleGroundAV: entering state STATUS_WAIT_JOIN ..."); } void BattleGroundAV::StartingEventOpenDoors() { + UpdateWorldState(BG_AV_SHOW_H_SCORE, 1); + UpdateWorldState(BG_AV_SHOW_A_SCORE, 1); + + OpenDoorEvent(BG_EVENT_DOOR); } void BattleGroundAV::AddPlayer(Player *plr) { BattleGround::AddPlayer(plr); - //create score and add it to map, default values are set in constructor + // create score and add it to map, default values are set in constructor BattleGroundAVScore* sc = new BattleGroundAVScore; - m_PlayerScores[plr->GetGUID()] = sc; } -void BattleGroundAV::RemovePlayer(Player* /*plr*/,uint64 /*guid*/) +void BattleGroundAV::EndBattleGround(uint32 winner) { + // calculate bonuskills for both teams: + uint32 tower_survived[BG_TEAMS_COUNT] = {0, 0}; + uint32 graves_owned[BG_TEAMS_COUNT] = {0, 0}; + uint32 mines_owned[BG_TEAMS_COUNT] = {0, 0}; + // towers all not destroyed: + for(BG_AV_Nodes i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_STONEHEART_BUNKER; ++i) + if (m_Nodes[i].State == POINT_CONTROLLED) + if (m_Nodes[i].TotalOwner == BG_TEAM_ALLIANCE) + ++tower_survived[BG_TEAM_ALLIANCE]; + for(BG_AV_Nodes i = BG_AV_NODES_ICEBLOOD_TOWER; i <= BG_AV_NODES_FROSTWOLF_WTOWER; ++i) + if (m_Nodes[i].State == POINT_CONTROLLED) + if (m_Nodes[i].TotalOwner == BG_TEAM_HORDE) + ++tower_survived[BG_TEAM_HORDE]; + // graves all controlled + for(BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i < BG_AV_NODES_MAX; ++i) + if (m_Nodes[i].State == POINT_CONTROLLED) + ++graves_owned[m_Nodes[i].Owner]; + + for (uint32 i = 0; i < BG_AV_MAX_MINES; ++i) + if (m_Mine_Owner[i] != BG_AV_NEUTRAL_TEAM) + ++mines_owned[m_Mine_Owner[i]]; + + // now we have the values give the honor/reputation to the teams: + uint32 team[BG_TEAMS_COUNT] = { ALLIANCE, HORDE }; + uint32 faction[BG_TEAMS_COUNT] = { BG_AV_FACTION_A, BG_AV_FACTION_H }; + for(uint32 i = 0; i < BG_TEAMS_COUNT; i++) + { + if (tower_survived[i]) + { + RewardReputationToTeam(faction[i], tower_survived[i] * m_RepSurviveTower, team[i]); + RewardHonorToTeam(GetBonusHonorFromKill(tower_survived[i] * BG_AV_KILL_SURVIVING_TOWER), team[i]); + } + sLog.outDebug("BattleGroundAV: EndbattleGround: bgteam: %u towers:%u honor:%u rep:%u", i, tower_survived[i], GetBonusHonorFromKill(tower_survived[i] * BG_AV_KILL_SURVIVING_TOWER), tower_survived[i] * BG_AV_REP_SURVIVING_TOWER); + if (graves_owned[i]) + RewardReputationToTeam(faction[i], graves_owned[i] * m_RepOwnedGrave, team[i]); + if (mines_owned[i]) + RewardReputationToTeam(faction[i], mines_owned[i] * m_RepOwnedMine, team[i]); + // captain survived?: + if (!IsActiveEvent(BG_AV_NodeEventCaptainDead_A + GetTeamIndexByTeamId(team[i]), 0)) + { + RewardReputationToTeam(faction[i], m_RepSurviveCaptain, team[i]); + RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_SURVIVING_CAPTAIN), team[i]); + } + } + + // both teams: + if (m_HonorMapComplete) + { + RewardHonorToTeam(m_HonorMapComplete, ALLIANCE); + RewardHonorToTeam(m_HonorMapComplete, HORDE); + } + BattleGround::EndBattleGround(winner); +} + +void BattleGroundAV::RemovePlayer(Player* plr,uint64 /*guid*/) +{ } void BattleGroundAV::HandleAreaTrigger(Player *Source, uint32 Trigger) { // this is wrong way to implement these things. On official it done by gameobject spell cast. - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - uint32 SpellId = 0; switch(Trigger) { case 95: - case 2606: case 2608: + if (Source->GetTeam() != ALLIANCE) + Source->GetSession()->SendNotification(LANG_BATTLEGROUND_ONLY_ALLIANCE_USE); + else + Source->LeaveBattleground(); + break; + case 2606: + if (Source->GetTeam() != HORDE) + Source->GetSession()->SendNotification(LANG_BATTLEGROUND_ONLY_HORDE_USE); + else + Source->LeaveBattleground(); + break; case 3326: case 3327: case 3328: case 3329: case 3330: case 3331: + //Source->Unmount(); break; default: - sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); - Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); + sLog.outDebug("BattleGroundAV: WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); +// Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); break; } - - if (SpellId) - Source->CastSpell(Source, SpellId, true); } void BattleGroundAV::UpdatePlayerScore(Player* Source, uint32 type, uint32 value) @@ -114,17 +423,419 @@ void BattleGroundAV::UpdatePlayerScore(Player* Source, uint32 type, uint32 value case SCORE_TOWERS_DEFENDED: ((BattleGroundAVScore*)itr->second)->TowersDefended += value; break; - case SCORE_MINES_CAPTURED: - ((BattleGroundAVScore*)itr->second)->MinesCaptured += value; - break; - case SCORE_LEADERS_KILLED: - ((BattleGroundAVScore*)itr->second)->LeadersKilled += value; - break; case SCORE_SECONDARY_OBJECTIVES: ((BattleGroundAVScore*)itr->second)->SecondaryObjectives += value; break; default: - BattleGround::UpdatePlayerScore(Source,type,value); + BattleGround::UpdatePlayerScore(Source, type, value); break; } } + +void BattleGroundAV::EventPlayerDestroyedPoint(BG_AV_Nodes node) +{ + + sLog.outDebug("BattleGroundAV: player destroyed point node %i", node); + + // despawn banner + DestroyNode(node); + PopulateNode(node); + UpdateNodeWorldState(node); + + uint32 owner = m_Nodes[node].Owner; + if (IsTower(node)) + { + uint8 tmp = node - BG_AV_NODES_DUNBALDAR_SOUTH; + // despawn marshal (one of those guys protecting the boss) + SpawnEvent(BG_AV_MARSHAL_A_SOUTH + tmp, 0, false); + + UpdateScore(BattleGroundTeamId(owner^0x1), (-1) * BG_AV_RES_TOWER); + RewardReputationToTeam((owner == BG_TEAM_ALLIANCE) ? BG_AV_FACTION_A : BG_AV_FACTION_H, m_RepTowerDestruction, owner); + RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_TOWER), owner); + SendYell2ToAll(LANG_BG_AV_TOWER_TAKEN, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0), GetNodeName(node), ( owner == BG_TEAM_ALLIANCE ) ? LANG_BG_AV_ALLY : LANG_BG_AV_HORDE); + } + else + { + SendYell2ToAll(LANG_BG_AV_GRAVE_TAKEN, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0), GetNodeName(node), ( owner == BG_TEAM_ALLIANCE ) ? LANG_BG_AV_ALLY : LANG_BG_AV_HORDE); + } +} + +void BattleGroundAV::ChangeMineOwner(uint8 mine, uint32 team) +{ + m_Mine_Timer[mine] = BG_AV_MINE_TICK_TIMER; + // TODO implement quest 7122 + // mine=0 northmine, mine=1 southmine + // TODO changing the owner should result in setting respawntime to infinite for current creatures (they should fight the new ones), spawning new mine owners creatures and changing the chest - objects so that the current owning team can use them + assert(mine == BG_AV_NORTH_MINE || mine == BG_AV_SOUTH_MINE); + if (m_Mine_Owner[mine] == int8(team)) + return; + + if (team != BG_TEAM_ALLIANCE && team != BG_TEAM_HORDE) + team = BG_AV_NEUTRAL_TEAM; + + m_Mine_PrevOwner[mine] = m_Mine_Owner[mine]; + m_Mine_Owner[mine] = team; + + SendMineWorldStates(mine); + + SpawnEvent(BG_AV_MINE_EVENT + mine, team, true); + SpawnEvent(BG_AV_MINE_BOSSES + mine, team, true); + + if (team == BG_TEAM_ALLIANCE || team == BG_TEAM_HORDE) + { + PlaySoundToAll((team == BG_TEAM_ALLIANCE) ? BG_AV_SOUND_ALLIANCE_GOOD : BG_AV_SOUND_HORDE_GOOD); + m_Mine_Reclaim_Timer[mine] = BG_AV_MINE_RECLAIM_TIMER; + SendYell2ToAll(LANG_BG_AV_MINE_TAKEN , LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0), + (team == BG_TEAM_ALLIANCE ) ? LANG_BG_AV_ALLY : LANG_BG_AV_HORDE, + (mine == BG_AV_NORTH_MINE) ? LANG_BG_AV_MINE_NORTH : LANG_BG_AV_MINE_SOUTH); + } +} + +bool BattleGroundAV::PlayerCanDoMineQuest(int32 GOId, uint32 team) +{ + if (GOId == BG_AV_OBJECTID_MINE_N) + return (m_Mine_Owner[BG_AV_NORTH_MINE] == GetTeamIndexByTeamId(team)); + if (GOId == BG_AV_OBJECTID_MINE_S) + return (m_Mine_Owner[BG_AV_SOUTH_MINE] == GetTeamIndexByTeamId(team)); + return true; // cause it's no mine'object it is ok if this is true +} + +/// will spawn and despawn creatures around a node +/// more a wrapper around spawnevent cause graveyards are special +void BattleGroundAV::PopulateNode(BG_AV_Nodes node) +{ + uint32 team = m_Nodes[node].Owner; + if (IsGrave(node) && team != BG_AV_NEUTRAL_TEAM) + { + uint32 graveDefenderType; + if (m_Team_QuestStatus[team][0] < 500 ) + graveDefenderType = 0; + else if (m_Team_QuestStatus[team][0] < 1000 ) + graveDefenderType = 1; + else if (m_Team_QuestStatus[team][0] < 1500 ) + graveDefenderType = 2; + else + graveDefenderType = 3; + + if (m_Nodes[node].State == POINT_CONTROLLED) // we can spawn the current owner event + SpawnEvent(BG_AV_NODES_MAX + node, team * BG_AV_MAX_GRAVETYPES + graveDefenderType, true); + else // we despawn the event from the prevowner + SpawnEvent(BG_AV_NODES_MAX + node, m_Nodes[node].PrevOwner * BG_AV_MAX_GRAVETYPES + graveDefenderType, false); + } + SpawnEvent(node, (team * BG_AV_MAX_STATES) + m_Nodes[node].State, true); +} + +/// called when using a banner +void BattleGroundAV::EventPlayerClickedOnFlag(Player *source, GameObject* target_obj) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + sLog.outDebug("BattleGroundAV: using gameobject %i", target_obj->GetEntry()); + uint8 event = (sBattleGroundMgr.GetGameObjectEventIndex(target_obj->GetDBTableGUIDLow())).event1; + if (event >= BG_AV_NODES_MAX) // not a node + return; + BG_AV_Nodes node = BG_AV_Nodes(event); + switch ((sBattleGroundMgr.GetGameObjectEventIndex(target_obj->GetDBTableGUIDLow())).event2 % BG_AV_MAX_STATES) + { + case POINT_CONTROLLED: + EventPlayerAssaultsPoint(source, node); + break; + case POINT_ASSAULTED: + EventPlayerDefendsPoint(source, node); + break; + default: + break; + } +} + +void BattleGroundAV::EventPlayerDefendsPoint(Player* player, BG_AV_Nodes node) +{ + assert(GetStatus() == STATUS_IN_PROGRESS); + + uint32 team = GetTeamIndexByTeamId(player->GetTeam()); + + if (m_Nodes[node].Owner == team || m_Nodes[node].State != POINT_ASSAULTED) + return; + if( m_Nodes[node].TotalOwner == BG_AV_NEUTRAL_TEAM ) // initial snowfall capture + { + // until snowfall doesn't belong to anyone it is better handled in assault - code (best would be to have a special function + // for neutral nodes.. but doing this just for snowfall will be a bit to much i think + assert(node == BG_AV_NODES_SNOWFALL_GRAVE); // currently the only neutral grave + EventPlayerAssaultsPoint(player, node); + return; + } + sLog.outDebug("BattleGroundAV: player defends node: %i", node); + if (m_Nodes[node].PrevOwner != team) + { + sLog.outError("BattleGroundAV: player defends point which doesn't belong to his team %i", node); + return; + } + + DefendNode(node, team); // set the right variables for nodeinfo + PopulateNode(node); // spawn node-creatures (defender for example) + UpdateNodeWorldState(node); // send new mapicon to the player + + if (IsTower(node)) + { + SendYell2ToAll( LANG_BG_AV_TOWER_DEFENDED, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0), + GetNodeName(node), + ( team == BG_TEAM_ALLIANCE ) ? LANG_BG_AV_ALLY:LANG_BG_AV_HORDE); + UpdatePlayerScore(player, SCORE_TOWERS_DEFENDED, 1); + PlaySoundToAll(BG_AV_SOUND_BOTH_TOWER_DEFEND); + } + else + { + SendYell2ToAll(LANG_BG_AV_GRAVE_DEFENDED, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0), + GetNodeName(node), + ( team == BG_TEAM_ALLIANCE ) ? LANG_BG_AV_ALLY:LANG_BG_AV_HORDE); + UpdatePlayerScore(player, SCORE_GRAVEYARDS_DEFENDED, 1); + // update the statistic for the defending player + PlaySoundToAll((team == BG_TEAM_ALLIANCE)?BG_AV_SOUND_ALLIANCE_GOOD:BG_AV_SOUND_HORDE_GOOD); + } +} + +void BattleGroundAV::EventPlayerAssaultsPoint(Player* player, BG_AV_Nodes node) +{ + // TODO implement quest 7101, 7081 + uint32 team = GetTeamIndexByTeamId(player->GetTeam()); + sLog.outDebug("BattleGroundAV: player assaults node %i", node); + if (m_Nodes[node].Owner == team || team == m_Nodes[node].TotalOwner) + return; + + AssaultNode(node, team); // update nodeinfo variables + UpdateNodeWorldState(node); // send mapicon + PopulateNode(node); + + if (IsTower(node)) + { + SendYell2ToAll(LANG_BG_AV_TOWER_ASSAULTED, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0), + GetNodeName(node), + ( team == BG_TEAM_ALLIANCE ) ? LANG_BG_AV_ALLY:LANG_BG_AV_HORDE); + UpdatePlayerScore(player, SCORE_GRAVEYARDS_ASSAULTED, 1); + } + else + { + SendYell2ToAll(LANG_BG_AV_GRAVE_ASSAULTED, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0), + GetNodeName(node), + ( team == BG_TEAM_ALLIANCE ) ? LANG_BG_AV_ALLY:LANG_BG_AV_HORDE); + // update the statistic for the assaulting player + UpdatePlayerScore(player, SCORE_GRAVEYARDS_ASSAULTED, 1); + } + + PlaySoundToAll((team == BG_TEAM_ALLIANCE) ? BG_AV_SOUND_ALLIANCE_ASSAULTS : BG_AV_SOUND_HORDE_ASSAULTS); +} + +void BattleGroundAV::FillInitialWorldStates(WorldPacket& data) +{ + bool stateok; + for (uint32 i = BG_AV_NODES_FIRSTAID_STATION; i < BG_AV_NODES_MAX; ++i) + { + for (uint8 j = 0; j < BG_AV_MAX_STATES; j++) + { + stateok = (m_Nodes[i].State == j); + data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j, BG_TEAM_ALLIANCE)]) << uint32((m_Nodes[i].Owner == BG_TEAM_ALLIANCE && stateok) ? 1 : 0); + data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j, BG_TEAM_HORDE)]) << uint32((m_Nodes[i].Owner == BG_TEAM_HORDE && stateok) ? 1 : 0); + } + } + + if( m_Nodes[BG_AV_NODES_SNOWFALL_GRAVE].Owner == BG_AV_NEUTRAL_TEAM ) // cause neutral teams aren't handled generic + data << uint32(AV_SNOWFALL_N) << uint32(1); + + data << uint32(BG_AV_Alliance_Score) << uint32(m_TeamScores[BG_TEAM_ALLIANCE]); + data << uint32(BG_AV_Horde_Score) << uint32(m_TeamScores[BG_TEAM_HORDE]); + if( GetStatus() == STATUS_IN_PROGRESS ) // only if game is running the teamscores are displayed + { + data << uint32(BG_AV_SHOW_A_SCORE) << uint32(1); + data << uint32(BG_AV_SHOW_H_SCORE) << uint32(1); + } + else + { + data << uint32(BG_AV_SHOW_A_SCORE) << uint32(0); + data << uint32(BG_AV_SHOW_H_SCORE) << uint32(0); + } + SendMineWorldStates(BG_AV_NORTH_MINE); + SendMineWorldStates(BG_AV_SOUTH_MINE); +} + +void BattleGroundAV::UpdateNodeWorldState(BG_AV_Nodes node) +{ + UpdateWorldState(BG_AV_NodeWorldStates[node][GetWorldStateType(m_Nodes[node].State,m_Nodes[node].Owner)], 1); + if( m_Nodes[node].PrevOwner == BG_AV_NEUTRAL_TEAM ) // currently only snowfall is supported as neutral node + UpdateWorldState(AV_SNOWFALL_N, 0); + else + UpdateWorldState(BG_AV_NodeWorldStates[node][GetWorldStateType(m_Nodes[node].PrevState,m_Nodes[node].PrevOwner)], 0); +} + +void BattleGroundAV::SendMineWorldStates(uint32 mine) +{ + assert(mine == BG_AV_NORTH_MINE || mine == BG_AV_SOUTH_MINE); + assert(m_Mine_PrevOwner[mine] == BG_TEAM_ALLIANCE || m_Mine_PrevOwner[mine] == BG_TEAM_HORDE || m_Mine_PrevOwner[mine] == BG_AV_NEUTRAL_TEAM); + assert(m_Mine_Owner[mine] == BG_TEAM_ALLIANCE || m_Mine_Owner[mine] == BG_TEAM_HORDE || m_Mine_Owner[mine] == BG_AV_NEUTRAL_TEAM); + + UpdateWorldState(BG_AV_MineWorldStates[mine][m_Mine_Owner[mine]], 1); + if (m_Mine_Owner[mine] != m_Mine_PrevOwner[mine]) + UpdateWorldState(BG_AV_MineWorldStates[mine][m_Mine_PrevOwner[mine]], 0); +} + +WorldSafeLocsEntry const* BattleGroundAV::GetClosestGraveYard(Player *plr) +{ + float x = plr->GetPositionX(); + float y = plr->GetPositionY(); + uint32 team = GetTeamIndexByTeamId(plr->GetTeam()); + WorldSafeLocsEntry const* good_entry = NULL; + if (GetStatus() == STATUS_IN_PROGRESS) + { + // Is there any occupied node for this team? + float mindist = 9999999.0f; + for(uint8 i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_FROSTWOLF_HUT; ++i) + { + if (m_Nodes[i].Owner != team || m_Nodes[i].State != POINT_CONTROLLED) + continue; + WorldSafeLocsEntry const * entry = sWorldSafeLocsStore.LookupEntry( BG_AV_GraveyardIds[i] ); + if (!entry) + continue; + float dist = (entry->x - x) * (entry->x - x) + (entry->y - y) * (entry->y - y); + if (mindist > dist) + { + mindist = dist; + good_entry = entry; + } + } + } + // If not, place ghost in the starting-cave + if (!good_entry) + good_entry = sWorldSafeLocsStore.LookupEntry( BG_AV_GraveyardIds[team + 7] ); + + return good_entry; +} + +uint32 BattleGroundAV::GetNodeName(BG_AV_Nodes node) +{ + switch (node) + { + case BG_AV_NODES_FIRSTAID_STATION: return LANG_BG_AV_NODE_GRAVE_STORM_AID; + case BG_AV_NODES_DUNBALDAR_SOUTH: return LANG_BG_AV_NODE_TOWER_DUN_S; + case BG_AV_NODES_DUNBALDAR_NORTH: return LANG_BG_AV_NODE_TOWER_DUN_N; + case BG_AV_NODES_STORMPIKE_GRAVE: return LANG_BG_AV_NODE_GRAVE_STORMPIKE; + case BG_AV_NODES_ICEWING_BUNKER: return LANG_BG_AV_NODE_TOWER_ICEWING; + case BG_AV_NODES_STONEHEART_GRAVE: return LANG_BG_AV_NODE_GRAVE_STONE; + case BG_AV_NODES_STONEHEART_BUNKER: return LANG_BG_AV_NODE_TOWER_STONE; + case BG_AV_NODES_SNOWFALL_GRAVE: return LANG_BG_AV_NODE_GRAVE_SNOW; + case BG_AV_NODES_ICEBLOOD_TOWER: return LANG_BG_AV_NODE_TOWER_ICE; + case BG_AV_NODES_ICEBLOOD_GRAVE: return LANG_BG_AV_NODE_GRAVE_ICE; + case BG_AV_NODES_TOWER_POINT: return LANG_BG_AV_NODE_TOWER_POINT; + case BG_AV_NODES_FROSTWOLF_GRAVE: return LANG_BG_AV_NODE_GRAVE_FROST; + case BG_AV_NODES_FROSTWOLF_ETOWER: return LANG_BG_AV_NODE_TOWER_FROST_E; + case BG_AV_NODES_FROSTWOLF_WTOWER: return LANG_BG_AV_NODE_TOWER_FROST_W; + case BG_AV_NODES_FROSTWOLF_HUT: return LANG_BG_AV_NODE_GRAVE_FROST_HUT; + default: return 0; break; + } +} + +void BattleGroundAV::AssaultNode(BG_AV_Nodes node, uint32 team) +{ + assert(team < 3); // alliance:0, horde:1, neutral:2 + assert(m_Nodes[node].TotalOwner != team); + assert(m_Nodes[node].Owner != team); + assert(m_Nodes[node].State != POINT_ASSAULTED || !m_Nodes[node].TotalOwner ); // only assault an assaulted node if no totalowner exists + // the timer gets another time, if the previous owner was 0 == Neutral + m_Nodes[node].Timer = (m_Nodes[node].PrevOwner != BG_AV_NEUTRAL_TEAM) ? BG_AV_CAPTIME : BG_AV_SNOWFALL_FIRSTCAP; + m_Nodes[node].PrevOwner = m_Nodes[node].Owner; + m_Nodes[node].Owner = team; + m_Nodes[node].PrevState = m_Nodes[node].State; + m_Nodes[node].State = POINT_ASSAULTED; +} + +void BattleGroundAV::DestroyNode(BG_AV_Nodes node) +{ + assert(m_Nodes[node].State == POINT_ASSAULTED); + + m_Nodes[node].TotalOwner = m_Nodes[node].Owner; + m_Nodes[node].PrevOwner = m_Nodes[node].Owner; + m_Nodes[node].PrevState = m_Nodes[node].State; + m_Nodes[node].State = POINT_CONTROLLED; + m_Nodes[node].Timer = 0; +} + +void BattleGroundAV::InitNode(BG_AV_Nodes node, uint32 team, bool tower) +{ + assert(team < 3); // alliance:0, horde:1, neutral:2 + m_Nodes[node].TotalOwner = team; + m_Nodes[node].Owner = team; + m_Nodes[node].PrevOwner = team; + m_Nodes[node].State = POINT_CONTROLLED; + m_Nodes[node].PrevState = m_Nodes[node].State; + m_Nodes[node].State = POINT_CONTROLLED; + m_Nodes[node].Timer = 0; + m_Nodes[node].Tower = tower; + m_ActiveEvents[node] = team * BG_AV_MAX_STATES + m_Nodes[node].State; + if (IsGrave(node)) // grave-creatures are special cause of a quest + m_ActiveEvents[node + BG_AV_NODES_MAX] = team * BG_AV_MAX_GRAVETYPES; +} + +void BattleGroundAV::DefendNode(BG_AV_Nodes node, uint32 team) +{ + assert(team < 3); // alliance:0, horde:1, neutral:2 + assert(m_Nodes[node].TotalOwner == team); + assert(m_Nodes[node].Owner != team); + assert(m_Nodes[node].State != POINT_CONTROLLED); + m_Nodes[node].PrevOwner = m_Nodes[node].Owner; + m_Nodes[node].Owner = team; + m_Nodes[node].PrevState = m_Nodes[node].State; + m_Nodes[node].State = POINT_CONTROLLED; + m_Nodes[node].Timer = 0; +} + +void BattleGroundAV::Reset() +{ + BattleGround::Reset(); + // set the reputation and honor variables: + bool isBGWeekend = sBattleGroundMgr.IsBGWeekend(GetTypeID()); + + m_HonorMapComplete = (isBGWeekend) ? BG_AV_KILL_MAP_COMPLETE_HOLIDAY : BG_AV_KILL_MAP_COMPLETE; + m_RepTowerDestruction = (isBGWeekend) ? BG_AV_REP_TOWER_HOLIDAY : BG_AV_REP_TOWER; + m_RepCaptain = (isBGWeekend) ? BG_AV_REP_CAPTAIN_HOLIDAY : BG_AV_REP_CAPTAIN; + m_RepBoss = (isBGWeekend) ? BG_AV_REP_BOSS_HOLIDAY : BG_AV_REP_BOSS; + m_RepOwnedGrave = (isBGWeekend) ? BG_AV_REP_OWNED_GRAVE_HOLIDAY : BG_AV_REP_OWNED_GRAVE; + m_RepSurviveCaptain = (isBGWeekend) ? BG_AV_REP_SURVIVING_CAPTAIN_HOLIDAY : BG_AV_REP_SURVIVING_CAPTAIN; + m_RepSurviveTower = (isBGWeekend) ? BG_AV_REP_SURVIVING_TOWER_HOLIDAY : BG_AV_REP_SURVIVING_TOWER; + + for(uint8 i = 0; i < BG_TEAMS_COUNT; i++) + { + for(uint8 j = 0; j < 9; j++) // 9 quests getting tracked + m_Team_QuestStatus[i][j] = 0; + m_TeamScores[i] = BG_AV_SCORE_INITIAL_POINTS; + m_IsInformedNearLose[i] = false; + m_ActiveEvents[BG_AV_NodeEventCaptainDead_A + i] = BG_EVENT_NONE; + } + + for(uint8 i = 0; i < BG_AV_MAX_MINES; i++) + { + m_Mine_Owner[i] = BG_AV_NEUTRAL_TEAM; + m_Mine_PrevOwner[i] = m_Mine_Owner[i]; + m_ActiveEvents[BG_AV_MINE_BOSSES+ i] = BG_AV_NEUTRAL_TEAM; + m_ActiveEvents[BG_AV_MINE_EVENT + i] = BG_AV_NEUTRAL_TEAM; + m_Mine_Timer[i] = BG_AV_MINE_TICK_TIMER; + } + + m_ActiveEvents[BG_AV_CAPTAIN_A] = 0; + m_ActiveEvents[BG_AV_CAPTAIN_H] = 0; + m_ActiveEvents[BG_AV_HERALD] = 0; + m_ActiveEvents[BG_AV_BOSS_A] = 0; + m_ActiveEvents[BG_AV_BOSS_H] = 0; + for(BG_AV_Nodes i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_FROSTWOLF_WTOWER; ++i) // towers + m_ActiveEvents[BG_AV_MARSHAL_A_SOUTH + i - BG_AV_NODES_DUNBALDAR_SOUTH] = 0; + + for(BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_STONEHEART_GRAVE; ++i) // alliance graves + InitNode(i, BG_TEAM_ALLIANCE, false); + for(BG_AV_Nodes i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_STONEHEART_BUNKER; ++i) // alliance towers + InitNode(i, BG_TEAM_ALLIANCE, true); + + for(BG_AV_Nodes i = BG_AV_NODES_ICEBLOOD_GRAVE; i <= BG_AV_NODES_FROSTWOLF_HUT; ++i) // horde graves + InitNode(i, BG_TEAM_HORDE, false); + for(BG_AV_Nodes i = BG_AV_NODES_ICEBLOOD_TOWER; i <= BG_AV_NODES_FROSTWOLF_WTOWER; ++i) // horde towers + InitNode(i, BG_TEAM_HORDE, true); + + InitNode(BG_AV_NODES_SNOWFALL_GRAVE, BG_AV_NEUTRAL_TEAM, false); // give snowfall neutral owner + +} diff --git a/src/game/BattleGroundAV.h b/src/game/BattleGroundAV.h index edacf1cfe..353318344 100644 --- a/src/game/BattleGroundAV.h +++ b/src/game/BattleGroundAV.h @@ -21,17 +21,279 @@ class BattleGround; +#define BG_AV_MAX_NODE_DISTANCE 25 // distance in which players are still counted in range of a banner (for alliance towers this is calculated from the center of the tower) + +#define BG_AV_BOSS_KILL_QUEST_SPELL 23658 + +#define BG_AV_CAPTIME 240000 // 4 minutes +#define BG_AV_SNOWFALL_FIRSTCAP 300000 // 5 minutes but i also have seen 4:05 + +#define BG_AV_SCORE_INITIAL_POINTS 600 +#define BG_AV_SCORE_NEAR_LOSE 120 + +// description: KILL = bonushonor kill one kill is 21honor worth at 0 +// REP reputation, RES = ressources a team will lose +#define BG_AV_KILL_BOSS 4 +#define BG_AV_REP_BOSS 350 +#define BG_AV_REP_BOSS_HOLIDAY 525 + +#define BG_AV_KILL_CAPTAIN 3 +#define BG_AV_REP_CAPTAIN 125 +#define BG_AV_REP_CAPTAIN_HOLIDAY 185 +#define BG_AV_RES_CAPTAIN 100 + +#define BG_AV_KILL_TOWER 3 +#define BG_AV_REP_TOWER 12 +#define BG_AV_REP_TOWER_HOLIDAY 18 +#define BG_AV_RES_TOWER 75 + +#define BG_AV_KILL_GET_COMMANDER 1 // for a safely returned wingcommander TODO implement it + +// bonushonor at the end +#define BG_AV_KILL_SURVIVING_TOWER 2 +#define BG_AV_REP_SURVIVING_TOWER 12 +#define BG_AV_REP_SURVIVING_TOWER_HOLIDAY 18 + +#define BG_AV_KILL_SURVIVING_CAPTAIN 2 +#define BG_AV_REP_SURVIVING_CAPTAIN 125 +#define BG_AV_REP_SURVIVING_CAPTAIN_HOLIDAY 175 + +#define BG_AV_KILL_MAP_COMPLETE 0 +#define BG_AV_KILL_MAP_COMPLETE_HOLIDAY 4 + +#define BG_AV_REP_OWNED_GRAVE 12 +#define BG_AV_REP_OWNED_GRAVE_HOLIDAY 18 + +#define BG_AV_REP_OWNED_MINE 24 +#define BG_AV_REP_OWNED_MINE_HOLIDAY 36 + +enum BG_AV_Sounds +{ + BG_AV_SOUND_NEAR_LOSE = 8456, // not confirmed yet + + BG_AV_SOUND_ALLIANCE_ASSAULTS = 8212, // tower,grave + enemy boss if someone tries to attack him + BG_AV_SOUND_HORDE_ASSAULTS = 8174, + BG_AV_SOUND_ALLIANCE_GOOD = 8173, // if something good happens for the team: wins(maybe only through killing the boss), captures mine or grave, destroys tower and defends grave + BG_AV_SOUND_HORDE_GOOD = 8213, + BG_AV_SOUND_BOTH_TOWER_DEFEND = 8192, + + BG_AV_SOUND_ALLIANCE_CAPTAIN = 8232, // gets called when someone attacks them and at the beginning after 3min + rand(x) * 10sec (maybe buff) + BG_AV_SOUND_HORDE_CAPTAIN = 8333, +}; + +enum BG_AV_OTHER_VALUES +{ + BG_AV_NORTH_MINE = 0, + BG_AV_SOUTH_MINE = 1, + BG_AV_MINE_TICK_TIMER = 45000, + BG_AV_MINE_RECLAIM_TIMER = 1200000, // TODO: get the right value.. this is currently 20 minutes + BG_AV_NEUTRAL_TEAM = 2, // this is the neutral owner of snowfall + BG_AV_FACTION_A = 730, + BG_AV_FACTION_H = 729, +}; +#define BG_AV_MAX_MINES 2 + +enum BG_AV_ObjectIds +{ + // mine supplies + BG_AV_OBJECTID_MINE_N = 178785, + BG_AV_OBJECTID_MINE_S = 178784, +}; + +enum BG_AV_Nodes +{ + BG_AV_NODES_FIRSTAID_STATION = 0, + BG_AV_NODES_STORMPIKE_GRAVE = 1, + BG_AV_NODES_STONEHEART_GRAVE = 2, + BG_AV_NODES_SNOWFALL_GRAVE = 3, + BG_AV_NODES_ICEBLOOD_GRAVE = 4, + BG_AV_NODES_FROSTWOLF_GRAVE = 5, + BG_AV_NODES_FROSTWOLF_HUT = 6, + BG_AV_NODES_DUNBALDAR_SOUTH = 7, + BG_AV_NODES_DUNBALDAR_NORTH = 8, + BG_AV_NODES_ICEWING_BUNKER = 9, + BG_AV_NODES_STONEHEART_BUNKER = 10, + BG_AV_NODES_ICEBLOOD_TOWER = 11, + BG_AV_NODES_TOWER_POINT = 12, + BG_AV_NODES_FROSTWOLF_ETOWER = 13, + BG_AV_NODES_FROSTWOLF_WTOWER = 14, + BG_AV_NODES_ERROR = 255, +}; +#define BG_AV_NODES_MAX 15 + + +// for nodeevents we will use event1=node +// event2 is related to BG_AV_States +// 0 = alliance assaulted +// 1 = alliance control +// 2 = horde assaulted +// 3 = horde control +// 4 = neutral assaulted +// 5 = neutral control + +// graves have special creatures - their defenders can be in 4 different states +// through some quests with armor scraps +// so i use event1=BG_AV_NODES_MAX+node (15-21) +// and event2=type + +#define BG_AV_MINE_BOSSES 46 // + mineid will be exact event +#define BG_AV_MINE_BOSSES_NORTH 46 +#define BG_AV_MINE_BOSSES_SOUTH 47 +#define BG_AV_CAPTAIN_A 48 +#define BG_AV_CAPTAIN_H 49 +#define BG_AV_MINE_EVENT 50 // + mineid will be exact event +#define BG_AV_MINE_EVENT_NORTH 50 +#define BG_AV_MINE_EVENT_SOUTH 51 + +#define BG_AV_MARSHAL_A_SOUTH 52 +#define BG_AV_MARSHAL_A_NORTH 53 +#define BG_AV_MARSHAL_A_ICE 54 +#define BG_AV_MARSHAL_A_STONE 55 +#define BG_AV_MARSHAL_H_ICE 56 +#define BG_AV_MARSHAL_H_TOWER 57 +#define BG_AV_MARSHAL_H_ETOWER 58 +#define BG_AV_MARSHAL_H_WTOWER 59 + +#define BG_AV_HERALD 60 +#define BG_AV_BOSS_A 61 +#define BG_AV_BOSS_H 62 +#define BG_AV_NodeEventCaptainDead_A 63 +#define BG_AV_NodeEventCaptainDead_H 64 + +enum BG_AV_Graveyards +{ + BG_AV_GRAVE_STORM_AID = 751, + BG_AV_GRAVE_STORM_GRAVE = 689, + BG_AV_GRAVE_STONE_GRAVE = 729, + BG_AV_GRAVE_SNOWFALL = 169, + BG_AV_GRAVE_ICE_GRAVE = 749, + BG_AV_GRAVE_FROSTWOLF = 690, + BG_AV_GRAVE_FROST_HUT = 750, + BG_AV_GRAVE_MAIN_ALLIANCE = 611, + BG_AV_GRAVE_MAIN_HORDE = 610 +}; + +const uint32 BG_AV_GraveyardIds[9]= { + BG_AV_GRAVE_STORM_AID, + BG_AV_GRAVE_STORM_GRAVE, + BG_AV_GRAVE_STONE_GRAVE, + BG_AV_GRAVE_SNOWFALL, + BG_AV_GRAVE_ICE_GRAVE, + BG_AV_GRAVE_FROSTWOLF, + BG_AV_GRAVE_FROST_HUT, + BG_AV_GRAVE_MAIN_ALLIANCE, + BG_AV_GRAVE_MAIN_HORDE +}; + +enum BG_AV_States +{ + POINT_ASSAULTED = 0, + POINT_CONTROLLED = 1 +}; +#define BG_AV_MAX_STATES 2 + +enum BG_AV_WorldStates +{ + BG_AV_Alliance_Score = 3127, + BG_AV_Horde_Score = 3128, + BG_AV_SHOW_H_SCORE = 3133, + BG_AV_SHOW_A_SCORE = 3134, + AV_SNOWFALL_N = 1966, +}; + +// alliance_control horde_control neutral_control +const uint32 BG_AV_MineWorldStates[2][3] = { + {1358, 1359, 1360}, + {1355, 1356, 1357} +}; + +// alliance_control alliance_assault h_control h_assault +const uint32 BG_AV_NodeWorldStates[BG_AV_NODES_MAX][4] = { + // Stormpike first aid station + {1326,1325,1328,1327}, + // Stormpike Graveyard + {1335,1333,1336,1334}, + // Stoneheart Grave + {1304,1302,1303,1301}, + // Snowfall Grave + {1343,1341,1344,1342}, + // Iceblood grave + {1348,1346,1349,1347}, + // Frostwolf Grave + {1339,1337,1340,1338}, + // Frostwolf Hut + {1331,1329,1332,1330}, + // Dunbaldar South Bunker + {1375,1361,1378,1370}, + // Dunbaldar North Bunker + {1374,1362,1379,1371}, + // Icewing Bunker + {1376,1363,1380,1372}, + // Stoneheart Bunker + {1377,1364,1381,1373}, + // Iceblood Tower + {1390,1368,1395,1385}, + // Tower Point + {1389,1367,1394,1384}, + // Frostwolf East + {1388,1366,1393,1383}, + // Frostwolf West + {1387,1365,1392,1382}, +}; + +// through the armorscap-quest 4 different gravedefender exist +#define BG_AV_MAX_GRAVETYPES 4 +enum BG_AV_QuestIds +{ + BG_AV_QUEST_A_SCRAPS1 = 7223, // first quest + BG_AV_QUEST_A_SCRAPS2 = 6781, // repeatable + BG_AV_QUEST_H_SCRAPS1 = 7224, + BG_AV_QUEST_H_SCRAPS2 = 6741, + BG_AV_QUEST_A_COMMANDER1 = 6942, // soldier + BG_AV_QUEST_H_COMMANDER1 = 6825, + BG_AV_QUEST_A_COMMANDER2 = 6941, // leutnant + BG_AV_QUEST_H_COMMANDER2 = 6826, + BG_AV_QUEST_A_COMMANDER3 = 6943, // commander + BG_AV_QUEST_H_COMMANDER3 = 6827, + BG_AV_QUEST_A_BOSS1 = 7386, // 5 cristal/blood + BG_AV_QUEST_H_BOSS1 = 7385, + BG_AV_QUEST_A_BOSS2 = 6881, // 1 + BG_AV_QUEST_H_BOSS2 = 6801, + BG_AV_QUEST_A_NEAR_MINE = 5892, // the mine near start location of team + BG_AV_QUEST_H_NEAR_MINE = 5893, + BG_AV_QUEST_A_OTHER_MINE = 6982, // the other mine ;) + BG_AV_QUEST_H_OTHER_MINE = 6985, + BG_AV_QUEST_A_RIDER_HIDE = 7026, + BG_AV_QUEST_H_RIDER_HIDE = 7002, + BG_AV_QUEST_A_RIDER_TAME = 7027, + BG_AV_QUEST_H_RIDER_TAME = 7001 +}; + +struct BG_AV_NodeInfo +{ + uint32 TotalOwner; + uint32 Owner; + uint32 PrevOwner; + BG_AV_States State; + BG_AV_States PrevState; + uint32 Timer; + bool Tower; +}; + +inline BG_AV_Nodes &operator++(BG_AV_Nodes &i) +{ + return i = BG_AV_Nodes(i + 1); +} + class BattleGroundAVScore : public BattleGroundScore { public: - BattleGroundAVScore() : GraveyardsAssaulted(0), GraveyardsDefended(0), TowersAssaulted(0), TowersDefended(0), MinesCaptured(0), LeadersKilled(0), SecondaryObjectives(0) {}; + BattleGroundAVScore() : GraveyardsAssaulted(0), GraveyardsDefended(0), TowersAssaulted(0), TowersDefended(0), SecondaryObjectives(0) {}; virtual ~BattleGroundAVScore() {}; uint32 GraveyardsAssaulted; uint32 GraveyardsDefended; uint32 TowersAssaulted; uint32 TowersDefended; - uint32 MinesCaptured; - uint32 LeadersKilled; uint32 SecondaryObjectives; }; @@ -46,16 +308,79 @@ class BattleGroundAV : public BattleGround /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); + virtual void OnObjectDBLoad(Creature* creature); + virtual void OnCreatureRespawn(Creature* creature); + virtual void StartingEventCloseDoors(); virtual void StartingEventOpenDoors(); + // world states + virtual void FillInitialWorldStates(WorldPacket& data); void RemovePlayer(Player *plr,uint64 guid); void HandleAreaTrigger(Player *Source, uint32 Trigger); - //bool SetupBattleGround(); + virtual void Reset(); - /* Scorekeeping */ + /*general stuff*/ + void UpdateScore(BattleGroundTeamId team, int32 points); void UpdatePlayerScore(Player *Source, uint32 type, uint32 value); + /*handle stuff*/ // these are functions which get called from extern scripts + virtual void EventPlayerClickedOnFlag(Player *source, GameObject* target_obj); + void HandleKillPlayer(Player* player, Player *killer); + void HandleKillUnit(Creature *creature, Player *killer); + void HandleQuestComplete(uint32 questid, Player *player); + bool PlayerCanDoMineQuest(int32 GOId,uint32 team); + + void EndBattleGround(uint32 winner); + + virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player *plr); + private: + /* Nodes occupying */ + void EventPlayerAssaultsPoint(Player* player, BG_AV_Nodes node); + void EventPlayerDefendsPoint(Player* player, BG_AV_Nodes node); + void EventPlayerDestroyedPoint(BG_AV_Nodes node); + + void AssaultNode(BG_AV_Nodes node, uint32 team); + void DestroyNode(BG_AV_Nodes node); + void InitNode(BG_AV_Nodes node, uint32 team, bool tower); + void DefendNode(BG_AV_Nodes node, uint32 team); + + void PopulateNode(BG_AV_Nodes node); + + uint32 GetNodeName(BG_AV_Nodes node); + const bool IsTower(BG_AV_Nodes node) { return (node == BG_AV_NODES_ERROR)? false : m_Nodes[node].Tower; } + const bool IsGrave(BG_AV_Nodes node) { return (node == BG_AV_NODES_ERROR)? false : !m_Nodes[node].Tower; } + + /*mine*/ + void ChangeMineOwner(uint8 mine, uint32 team); + + /*worldstates*/ + uint8 GetWorldStateType(uint8 state, uint32 team) const { return team * BG_AV_MAX_STATES + state; } + void SendMineWorldStates(uint32 mine); + void UpdateNodeWorldState(BG_AV_Nodes node); + + /*variables */ + uint32 m_Team_QuestStatus[BG_TEAMS_COUNT][9]; // [x][y] x=team y=questcounter + + BG_AV_NodeInfo m_Nodes[BG_AV_NODES_MAX]; + + int8 m_Mine_Owner[BG_AV_MAX_MINES]; + int8 m_Mine_PrevOwner[BG_AV_MAX_MINES]; // only for worldstates needed + int32 m_Mine_Timer[BG_AV_MAX_MINES]; + uint32 m_Mine_Reclaim_Timer[BG_AV_MAX_MINES]; + + bool m_IsInformedNearLose[BG_TEAMS_COUNT]; + bool m_captainAlive[BG_TEAMS_COUNT]; + + uint32 m_HonorMapComplete; + uint32 m_RepTowerDestruction; + uint32 m_RepCaptain; + uint32 m_RepBoss; + uint32 m_RepOwnedGrave; + uint32 m_RepOwnedMine; + uint32 m_RepSurviveCaptain; + uint32 m_RepSurviveTower; }; + #endif diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index b40dcd2b6..0e9784e5f 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -1383,7 +1383,7 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg) *data << (uint32)((BattleGroundAVScore*)itr->second)->GraveyardsDefended; // GraveyardsDefended *data << (uint32)((BattleGroundAVScore*)itr->second)->TowersAssaulted; // TowersAssaulted *data << (uint32)((BattleGroundAVScore*)itr->second)->TowersDefended; // TowersDefended - *data << (uint32)((BattleGroundAVScore*)itr->second)->MinesCaptured; // MinesCaptured + *data << (uint32)((BattleGroundAVScore*)itr->second)->SecondaryObjectives; // SecondaryObjectives - free some of the Lieutnants break; case BATTLEGROUND_WS: *data << (uint32)0x00000002; // count of next fields diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 4872e282d..89abfc303 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -366,6 +366,9 @@ void Creature::Update(uint32 diff) else setDeathState( JUST_ALIVED ); + if (GetMap()->IsBattleGround() && ((BattleGroundMap*)GetMap())->GetBG()) + ((BattleGroundMap*)GetMap())->GetBG()->OnCreatureRespawn(this); // for alterac valley needed to adjust the correct level again + //Call AI respawn virtual function i_AI->JustRespawned(); diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index c0e0299c4..c7d1829a7 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -34,6 +34,7 @@ #include "CellImpl.h" #include "InstanceData.h" #include "BattleGround.h" +#include "BattleGroundAV.h" #include "Util.h" GameObject::GameObject() : WorldObject() @@ -744,7 +745,14 @@ bool GameObject::ActivateToQuest( Player *pTarget)const case GAMEOBJECT_TYPE_CHEST: { if(LootTemplates_Gameobject.HaveQuestLootForPlayer(GetGOInfo()->GetLootId(), pTarget)) + { + //look for battlegroundAV for some objects which are only activated after mine gots captured by own team + if (GetEntry() == BG_AV_OBJECTID_MINE_N || GetEntry() == BG_AV_OBJECTID_MINE_S) + if (BattleGround *bg = pTarget->GetBattleGround()) + if (bg->GetTypeID() == BATTLEGROUND_AV && !(((BattleGroundAV*)bg)->PlayerCanDoMineQuest(GetEntry(),pTarget->GetTeam()))) + return false; return true; + } break; } case GAMEOBJECT_TYPE_GOOBER: diff --git a/src/game/Language.h b/src/game/Language.h index fbf33d2a5..627c0763c 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -686,16 +686,51 @@ enum MangosStrings LANG_DIST_ARENA_POINTS_TEAM_START = 744, LANG_DIST_ARENA_POINTS_TEAM_END = 745, LANG_DIST_ARENA_POINTS_END = 746, -// = 747, not used -// = 748, not used -// = 749, not used + LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 750, // "Not enough players. This game will close in %u mins." LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS = 751, // "Not enough players. This game will close in %u seconds." -// = 752, not used -// LANG_BG_WS_START_TWO_MINUTES = 753, - defined above -// LANG_BG_AB_START_TWO_MINUTES = 754, - defined above -// LANG_BG_EY_START_TWO_MINUTES = 755, - defined above - // Room for batleground/arena strings 756-799 not used + LANG_BATTLEGROUND_ONLY_ALLIANCE_USE = 752, // "Only The Alliance can use that portal" + LANG_BATTLEGROUND_ONLY_HORDE_USE = 753, // "Only The Horde can use that portal" + + LANG_BG_AV_ALLY = 757, + LANG_BG_AV_HORDE = 758, + LANG_BG_AV_TOWER_TAKEN = 759, + LANG_BG_AV_TOWER_ASSAULTED = 760, + LANG_BG_AV_TOWER_DEFENDED = 761, + LANG_BG_AV_GRAVE_TAKEN = 762, + LANG_BG_AV_GRAVE_DEFENDED = 763, + LANG_BG_AV_GRAVE_ASSAULTED = 764, + LANG_BG_AV_MINE_TAKEN = 765, + LANG_BG_AV_MINE_NORTH = 766, + LANG_BG_AV_MINE_SOUTH = 767, + + LANG_BG_AV_NODE_GRAVE_STORM_AID = 768, + LANG_BG_AV_NODE_TOWER_DUN_S = 769, + LANG_BG_AV_NODE_TOWER_DUN_N = 770, + LANG_BG_AV_NODE_GRAVE_STORMPIKE = 771, + LANG_BG_AV_NODE_TOWER_ICEWING = 772, + LANG_BG_AV_NODE_GRAVE_STONE = 773, + LANG_BG_AV_NODE_TOWER_STONE = 774, + LANG_BG_AV_NODE_GRAVE_SNOW = 775, + LANG_BG_AV_NODE_TOWER_ICE = 776, + LANG_BG_AV_NODE_GRAVE_ICE = 777, + LANG_BG_AV_NODE_TOWER_POINT = 778, + LANG_BG_AV_NODE_GRAVE_FROST = 779, + LANG_BG_AV_NODE_TOWER_FROST_E = 780, + LANG_BG_AV_NODE_TOWER_FROST_W = 781, + LANG_BG_AV_NODE_GRAVE_FROST_HUT = 782, + + LANG_BG_AV_START_TWO_MINUTES = 783, + LANG_BG_AV_START_ONE_MINUTE = 784, + LANG_BG_AV_START_HALF_MINUTE = 785, + LANG_BG_AV_HAS_BEGUN = 786, + LANG_BG_AV_A_NEAR_LOSE = 787, + LANG_BG_AV_H_NEAR_LOSE = 788, + LANG_BG_AV_H_GENERAL_DEAD = 789, + LANG_BG_AV_A_GENERAL_DEAD = 790, + + + // Room for batleground/arena strings 790-799 not used // in game strings // = 800, not used diff --git a/src/game/LootHandler.cpp b/src/game/LootHandler.cpp index 67cb4dc59..14dead0a4 100644 --- a/src/game/LootHandler.cpp +++ b/src/game/LootHandler.cpp @@ -65,6 +65,16 @@ void WorldSession::HandleAutostoreLootItemOpcode( WorldPacket & recv_data ) loot = &pItem->loot; } + else if (IS_CORPSE_GUID(lguid)) + { + Corpse *bones = ObjectAccessor::GetCorpse(*player, lguid); + if (!bones) + { + player->SendLootRelease(lguid); + return; + } + loot = &bones->loot; + } else { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 624169fe8..857bddcfe 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -782,9 +782,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data) { BattleGround* bg = GetPlayer()->GetBattleGround(); if(bg) - if(bg->GetStatus() == STATUS_IN_PROGRESS) - bg->HandleAreaTrigger(GetPlayer(), Trigger_ID); - + bg->HandleAreaTrigger(GetPlayer(), Trigger_ID); return; } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 43bf9d85a..88541ba6c 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -51,6 +51,7 @@ #include "Transports.h" #include "Weather.h" #include "BattleGround.h" +#include "BattleGroundAV.h" #include "BattleGroundMgr.h" #include "ArenaTeam.h" #include "Chat.h" @@ -7410,6 +7411,14 @@ void Player::SendLoot(uint64 guid, LootType loot_type) if (go->getLootState() == GO_READY) { uint32 lootid = go->GetGOInfo()->GetLootId(); + if ((go->GetEntry() == BG_AV_OBJECTID_MINE_N || go->GetEntry() == BG_AV_OBJECTID_MINE_S)) + if (BattleGround *bg = GetBattleGround()) + if (bg->GetTypeID() == BATTLEGROUND_AV) + if (!(((BattleGroundAV*)bg)->PlayerCanDoMineQuest(go->GetEntry(), GetTeam()))) + { + SendLootRelease(guid); + return; + } if (lootid) { @@ -7476,6 +7485,8 @@ void Player::SendLoot(uint64 guid, LootType loot_type) bones->lootForBody = true; uint32 pLevel = bones->loot.gold; bones->loot.clear(); + if (GetBattleGround()->GetTypeID() == BATTLEGROUND_AV) + loot->FillLoot(0, LootTemplates_Creature, this, false); // It may need a better formula // Now it works like this: lvl10: ~6copper, lvl70: ~9silver bones->loot.gold = (uint32)( urand(50, 150) * 0.016f * pow( ((float)pLevel)/5.76f, 2.5f) * sWorld.getRate(RATE_DROP_MONEY) ); @@ -7759,81 +7770,86 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid) case 2257: break; case 2597: // AV - data << uint32(0x7ae) << uint32(0x1); // 7 - data << uint32(0x532) << uint32(0x1); // 8 - data << uint32(0x531) << uint32(0x0); // 9 - data << uint32(0x52e) << uint32(0x0); // 10 - data << uint32(0x571) << uint32(0x0); // 11 - data << uint32(0x570) << uint32(0x0); // 12 - data << uint32(0x567) << uint32(0x1); // 13 - data << uint32(0x566) << uint32(0x1); // 14 - data << uint32(0x550) << uint32(0x1); // 15 - data << uint32(0x544) << uint32(0x0); // 16 - data << uint32(0x536) << uint32(0x0); // 17 - data << uint32(0x535) << uint32(0x1); // 18 - data << uint32(0x518) << uint32(0x0); // 19 - data << uint32(0x517) << uint32(0x0); // 20 - data << uint32(0x574) << uint32(0x0); // 21 - data << uint32(0x573) << uint32(0x0); // 22 - data << uint32(0x572) << uint32(0x0); // 23 - data << uint32(0x56f) << uint32(0x0); // 24 - data << uint32(0x56e) << uint32(0x0); // 25 - data << uint32(0x56d) << uint32(0x0); // 26 - data << uint32(0x56c) << uint32(0x0); // 27 - data << uint32(0x56b) << uint32(0x0); // 28 - data << uint32(0x56a) << uint32(0x1); // 29 - data << uint32(0x569) << uint32(0x1); // 30 - data << uint32(0x568) << uint32(0x1); // 13 - data << uint32(0x565) << uint32(0x0); // 32 - data << uint32(0x564) << uint32(0x0); // 33 - data << uint32(0x563) << uint32(0x0); // 34 - data << uint32(0x562) << uint32(0x0); // 35 - data << uint32(0x561) << uint32(0x0); // 36 - data << uint32(0x560) << uint32(0x0); // 37 - data << uint32(0x55f) << uint32(0x0); // 38 - data << uint32(0x55e) << uint32(0x0); // 39 - data << uint32(0x55d) << uint32(0x0); // 40 - data << uint32(0x3c6) << uint32(0x4); // 41 - data << uint32(0x3c4) << uint32(0x6); // 42 - data << uint32(0x3c2) << uint32(0x4); // 43 - data << uint32(0x516) << uint32(0x1); // 44 - data << uint32(0x515) << uint32(0x0); // 45 - data << uint32(0x3b6) << uint32(0x6); // 46 - data << uint32(0x55c) << uint32(0x0); // 47 - data << uint32(0x55b) << uint32(0x0); // 48 - data << uint32(0x55a) << uint32(0x0); // 49 - data << uint32(0x559) << uint32(0x0); // 50 - data << uint32(0x558) << uint32(0x0); // 51 - data << uint32(0x557) << uint32(0x0); // 52 - data << uint32(0x556) << uint32(0x0); // 53 - data << uint32(0x555) << uint32(0x0); // 54 - data << uint32(0x554) << uint32(0x1); // 55 - data << uint32(0x553) << uint32(0x1); // 56 - data << uint32(0x552) << uint32(0x1); // 57 - data << uint32(0x551) << uint32(0x1); // 58 - data << uint32(0x54f) << uint32(0x0); // 59 - data << uint32(0x54e) << uint32(0x0); // 60 - data << uint32(0x54d) << uint32(0x1); // 61 - data << uint32(0x54c) << uint32(0x0); // 62 - data << uint32(0x54b) << uint32(0x0); // 63 - data << uint32(0x545) << uint32(0x0); // 64 - data << uint32(0x543) << uint32(0x1); // 65 - data << uint32(0x542) << uint32(0x0); // 66 - data << uint32(0x540) << uint32(0x0); // 67 - data << uint32(0x53f) << uint32(0x0); // 68 - data << uint32(0x53e) << uint32(0x0); // 69 - data << uint32(0x53d) << uint32(0x0); // 70 - data << uint32(0x53c) << uint32(0x0); // 71 - data << uint32(0x53b) << uint32(0x0); // 72 - data << uint32(0x53a) << uint32(0x1); // 73 - data << uint32(0x539) << uint32(0x0); // 74 - data << uint32(0x538) << uint32(0x0); // 75 - data << uint32(0x537) << uint32(0x0); // 76 - data << uint32(0x534) << uint32(0x0); // 77 - data << uint32(0x533) << uint32(0x0); // 78 - data << uint32(0x530) << uint32(0x0); // 79 - data << uint32(0x52f) << uint32(0x0); // 80 - data << uint32(0x52d) << uint32(0x1); // 81 + if (bg && bg->GetTypeID() == BATTLEGROUND_AV) + bg->FillInitialWorldStates(data); + else + { + data << uint32(0x7ae) << uint32(0x1); // 7 snowfall n + data << uint32(0x532) << uint32(0x1); // 8 frostwolfhut hc + data << uint32(0x531) << uint32(0x0); // 9 frostwolfhut ac + data << uint32(0x52e) << uint32(0x0); // 10 stormpike firstaid a_a + data << uint32(0x571) << uint32(0x0); // 11 east frostwolf tower horde assaulted -unused + data << uint32(0x570) << uint32(0x0); // 12 west frostwolf tower horde assaulted - unused + data << uint32(0x567) << uint32(0x1); // 13 frostwolfe c + data << uint32(0x566) << uint32(0x1); // 14 frostwolfw c + data << uint32(0x550) << uint32(0x1); // 15 irondeep (N) ally + data << uint32(0x544) << uint32(0x0); // 16 ice grave a_a + data << uint32(0x536) << uint32(0x0); // 17 stormpike grave h_c + data << uint32(0x535) << uint32(0x1); // 18 stormpike grave a_c + data << uint32(0x518) << uint32(0x0); // 19 stoneheart grave a_a + data << uint32(0x517) << uint32(0x0); // 20 stoneheart grave h_a + data << uint32(0x574) << uint32(0x0); // 21 1396 unk + data << uint32(0x573) << uint32(0x0); // 22 iceblood tower horde assaulted -unused + data << uint32(0x572) << uint32(0x0); // 23 towerpoint horde assaulted - unused + data << uint32(0x56f) << uint32(0x0); // 24 1391 unk + data << uint32(0x56e) << uint32(0x0); // 25 iceblood a + data << uint32(0x56d) << uint32(0x0); // 26 towerp a + data << uint32(0x56c) << uint32(0x0); // 27 frostwolfe a + data << uint32(0x56b) << uint32(0x0); // 28 froswolfw a + data << uint32(0x56a) << uint32(0x1); // 29 1386 unk + data << uint32(0x569) << uint32(0x1); // 30 iceblood c + data << uint32(0x568) << uint32(0x1); // 31 towerp c + data << uint32(0x565) << uint32(0x0); // 32 stoneh tower a + data << uint32(0x564) << uint32(0x0); // 33 icewing tower a + data << uint32(0x563) << uint32(0x0); // 34 dunn a + data << uint32(0x562) << uint32(0x0); // 35 duns a + data << uint32(0x561) << uint32(0x0); // 36 stoneheart bunker alliance assaulted - unused + data << uint32(0x560) << uint32(0x0); // 37 icewing bunker alliance assaulted - unused + data << uint32(0x55f) << uint32(0x0); // 38 dunbaldar south alliance assaulted - unused + data << uint32(0x55e) << uint32(0x0); // 39 dunbaldar north alliance assaulted - unused + data << uint32(0x55d) << uint32(0x0); // 40 stone tower d + data << uint32(0x3c6) << uint32(0x0); // 41 966 unk + data << uint32(0x3c4) << uint32(0x0); // 42 964 unk + data << uint32(0x3c2) << uint32(0x0); // 43 962 unk + data << uint32(0x516) << uint32(0x1); // 44 stoneheart grave a_c + data << uint32(0x515) << uint32(0x0); // 45 stonheart grave h_c + data << uint32(0x3b6) << uint32(0x0); // 46 950 unk + data << uint32(0x55c) << uint32(0x0); // 47 icewing tower d + data << uint32(0x55b) << uint32(0x0); // 48 dunn d + data << uint32(0x55a) << uint32(0x0); // 49 duns d + data << uint32(0x559) << uint32(0x0); // 50 1369 unk + data << uint32(0x558) << uint32(0x0); // 51 iceblood d + data << uint32(0x557) << uint32(0x0); // 52 towerp d + data << uint32(0x556) << uint32(0x0); // 53 frostwolfe d + data << uint32(0x555) << uint32(0x0); // 54 frostwolfw d + data << uint32(0x554) << uint32(0x1); // 55 stoneh tower c + data << uint32(0x553) << uint32(0x1); // 56 icewing tower c + data << uint32(0x552) << uint32(0x1); // 57 dunn c + data << uint32(0x551) << uint32(0x1); // 58 duns c + data << uint32(0x54f) << uint32(0x0); // 59 irondeep (N) horde + data << uint32(0x54e) << uint32(0x0); // 60 irondeep (N) ally + data << uint32(0x54d) << uint32(0x1); // 61 mine (S) neutral + data << uint32(0x54c) << uint32(0x0); // 62 mine (S) horde + data << uint32(0x54b) << uint32(0x0); // 63 mine (S) ally + data << uint32(0x545) << uint32(0x0); // 64 iceblood h_a + data << uint32(0x543) << uint32(0x1); // 65 iceblod h_c + data << uint32(0x542) << uint32(0x0); // 66 iceblood a_c + data << uint32(0x540) << uint32(0x0); // 67 snowfall h_a + data << uint32(0x53f) << uint32(0x0); // 68 snowfall a_a + data << uint32(0x53e) << uint32(0x0); // 69 snowfall h_c + data << uint32(0x53d) << uint32(0x0); // 70 snowfall a_c + data << uint32(0x53c) << uint32(0x0); // 71 frostwolf g h_a + data << uint32(0x53b) << uint32(0x0); // 72 frostwolf g a_a + data << uint32(0x53a) << uint32(0x1); // 73 frostwolf g h_c + data << uint32(0x539) << uint32(0x0); // 74 frostwolf g a_c + data << uint32(0x538) << uint32(0x0); // 75 stormpike grave h_a + data << uint32(0x537) << uint32(0x0); // 76 stormpike grave a_a + data << uint32(0x534) << uint32(0x0); // 77 frostwolf hut h_a + data << uint32(0x533) << uint32(0x0); // 78 frostwolf hut a_a + data << uint32(0x530) << uint32(0x0); // 79 stormpike first aid h_a + data << uint32(0x52f) << uint32(0x0); // 80 stormpike first aid h_c + data << uint32(0x52d) << uint32(0x1); // 81 stormpike first aid a_c + } break; case 3277: // WS if (bg && bg->GetTypeID() == BATTLEGROUND_WS) @@ -12645,6 +12661,10 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver RemoveTimedQuest(quest_id); + if (BattleGround* bg = GetBattleGround()) + if (bg->GetTypeID() == BATTLEGROUND_AV) + ((BattleGroundAV*)bg)->HandleQuestComplete(pQuest->GetQuestId(), this); + if (pQuest->GetRewChoiceItemsCount() > 0) { if (uint32 itemId = pQuest->RewChoiceItemId[reward]) @@ -13751,7 +13771,8 @@ bool Player::HasQuestForItem( uint32 itemid ) const continue; // hide quest if player is in raid-group and quest is no raid quest - if(GetGroup() && GetGroup()->isRaidGroup() && qinfo->GetType() != QUEST_TYPE_RAID) + if (GetGroup() && GetGroup()->isRaidGroup() && qinfo->GetType() != QUEST_TYPE_RAID + && !InBattleGround()) continue; // There should be no mixed ReqItem/ReqSource drop diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index e7d9587cc..bf9852b15 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -3044,7 +3044,7 @@ void Spell::EffectOpenLock(uint32 effIndex) if (BattleGround *bg = player->GetBattleGround()) { // check if it's correct bg - if (bg && bg->GetTypeID() == BATTLEGROUND_AB) + if (bg->GetTypeID() == BATTLEGROUND_AB || bg->GetTypeID() == BATTLEGROUND_AV) bg->EventPlayerClickedOnFlag(player, gameObjTarget); return; } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 6d706c484..3b19f33d9 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -718,10 +718,12 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa if(BattleGround *bg = killed->GetBattleGround()) if(player) bg->HandleKillPlayer(killed, player); - //later we can add support for creature->player kills here i'm - //not sure, but i guess those kills also get counted in av - //else if(GetTypeId() == TYPEID_UNIT) - // bg->HandleKillPlayer(killed,(Creature*)this); + } + else if(pVictim->GetTypeId() == TYPEID_UNIT) + { + if (player) + if (BattleGround *bg = player->GetBattleGround()) + bg->HandleKillUnit((Creature*)pVictim, player); } } else // if (health <= damage) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 619411466..11ce1dcb0 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8607" + #define REVISION_NR "8608" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index d2277b7bb..0210c0b6f 100644 --- a/src/shared/revision_sql.h +++ b/src/shared/revision_sql.h @@ -1,6 +1,6 @@ #ifndef __REVISION_SQL_H__ #define __REVISION_SQL_H__ #define REVISION_DB_CHARACTERS "required_8596_01_characters_bugreport" - #define REVISION_DB_MANGOS "required_8607_02_mangos_command" + #define REVISION_DB_MANGOS "required_8608_02_mangos_battleground_events" #define REVISION_DB_REALMD "required_8332_01_realmd_realmcharacters" #endif // __REVISION_SQL_H__ From bb10fada9aea251fdb2941c0c85fbee6e26f27b1 Mon Sep 17 00:00:00 2001 From: LordJZ Date: Fri, 9 Oct 2009 20:31:03 +0200 Subject: [PATCH 12/20] [8609] fixed typo in UpdateScore in last commit --- src/game/BattleGroundAV.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/BattleGroundAV.cpp b/src/game/BattleGroundAV.cpp index be20d2831..17bf3d7a9 100644 --- a/src/game/BattleGroundAV.cpp +++ b/src/game/BattleGroundAV.cpp @@ -611,7 +611,7 @@ void BattleGroundAV::EventPlayerAssaultsPoint(Player* player, BG_AV_Nodes node) SendYell2ToAll(LANG_BG_AV_TOWER_ASSAULTED, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0), GetNodeName(node), ( team == BG_TEAM_ALLIANCE ) ? LANG_BG_AV_ALLY:LANG_BG_AV_HORDE); - UpdatePlayerScore(player, SCORE_GRAVEYARDS_ASSAULTED, 1); + UpdatePlayerScore(player, SCORE_TOWERS_ASSAULTED, 1); } else { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 11ce1dcb0..7eaeff270 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8608" + #define REVISION_NR "8609" #endif // __REVISION_NR_H__ From 4dc1df7d54acf7d6760bdf411a941356d2d4416b Mon Sep 17 00:00:00 2001 From: balrok Date: Thu, 17 Sep 2009 00:09:40 +0200 Subject: [PATCH 13/20] [8610] castchecks for recall spell for the av-trinket this spell should be cast only in battlegrounds and only after battleground started --- src/game/SpellMgr.cpp | 15 +++++++++++++++ src/shared/revision_nr.h | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index fa0cff155..c9407f88f 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -2819,6 +2819,21 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell switch(spellInfo->Id) { + // a trinket in alterac valley allows to teleport to the boss + case 22564: // recall + case 22563: // recall + { + if (!player) + return SPELL_FAILED_REQUIRES_AREA; + MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); + if (!mapEntry) + return SPELL_FAILED_REQUIRES_AREA; + if (!mapEntry->IsBattleGround()) + return SPELL_FAILED_REQUIRES_AREA; + BattleGround* bg = player->GetBattleGround(); + return map_id == 30 && bg && bg->GetStatus()!=STATUS_WAIT_JOIN ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA; + break; + } case 23333: // Warsong Flag case 23335: // Silverwing Flag return map_id == 489 && player && player->InBattleGround() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 7eaeff270..af12e3ae5 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8609" + #define REVISION_NR "8610" #endif // __REVISION_NR_H__ From d7e01c3e167995b2bc3716c2211b6a2c1ce97dc5 Mon Sep 17 00:00:00 2001 From: balrok Date: Fri, 9 Oct 2009 22:45:57 +0200 Subject: [PATCH 14/20] [8611] added new 322 value to MailStationery also changed numbers from hexadecimal to decimal --- src/game/Mail.h | 13 +++++++------ src/shared/revision_nr.h | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/game/Mail.h b/src/game/Mail.h index 7f7398da8..c13124c04 100644 --- a/src/game/Mail.h +++ b/src/game/Mail.h @@ -65,12 +65,13 @@ enum MailAuctionAnswers // gathered from Stationery.dbc enum MailStationery { - MAIL_STATIONERY_UNKNOWN = 0x01, - MAIL_STATIONERY_NORMAL = 0x29, - MAIL_STATIONERY_GM = 0x3D, - MAIL_STATIONERY_AUCTION = 0x3E, - MAIL_STATIONERY_VAL = 0x40, - MAIL_STATIONERY_CHR = 0x41 + MAIL_STATIONERY_UNKNOWN = 1, + MAIL_STATIONERY_NORMAL = 41, + MAIL_STATIONERY_GM = 61, + MAIL_STATIONERY_AUCTION = 62, + MAIL_STATIONERY_VAL = 64, + MAIL_STATIONERY_CHR = 65, + MAIL_STATIONERY_ORP = 67, // new in 3.2.2 }; struct MailItemInfo diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index af12e3ae5..1f738eb52 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8610" + #define REVISION_NR "8611" #endif // __REVISION_NR_H__ From caf4732e38fbf718451b52db476ae85d6c956d70 Mon Sep 17 00:00:00 2001 From: balrok Date: Sat, 10 Oct 2009 01:35:58 +0200 Subject: [PATCH 15/20] [8612] better error-check when getting bgTypeId from Battlemasterentry --- src/game/BattleGroundHandler.cpp | 3 +++ src/game/BattleGroundMgr.h | 2 +- src/game/Creature.cpp | 8 ++++++++ src/shared/revision_nr.h | 2 +- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index 004f5e050..868f5b9d9 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -50,6 +50,9 @@ void WorldSession::HandleBattlemasterHelloOpcode( WorldPacket & recv_data ) BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(unit->GetEntry()); + if (bgTypeId == BATTLEGROUND_TYPE_NONE) + return; + if (!_player->GetBGAccessByLevel(bgTypeId)) { // temp, must be gossip message... diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index 5fb3668c0..4d72d9656 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -235,7 +235,7 @@ class BattleGroundMgr BattleMastersMap::const_iterator itr = mBattleMastersMap.find(entry); if (itr != mBattleMastersMap.end()) return itr->second; - return BATTLEGROUND_WS; + return BATTLEGROUND_TYPE_NONE; } void LoadBattleEventIndexes(); diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 89abfc303..38c5bc5a9 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -711,6 +711,9 @@ bool Creature::isCanInteractWithBattleMaster(Player* pPlayer, bool msg) const return false; BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(GetEntry()); + if (bgTypeId == BATTLEGROUND_TYPE_NONE) + return false; + if(!msg) return pPlayer->GetBGAccessByLevel(bgTypeId); @@ -968,6 +971,11 @@ void Creature::OnGossipSelect(Player* player, uint32 option) case GOSSIP_OPTION_BATTLEFIELD: { BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(GetEntry()); + if (bgTypeId == BATTLEGROUND_TYPE_NONE) + { + sLog.outError("a user (guid %u) requested battlegroundlist from a npc who is no battlemaster", player->GetGUIDLow()); + return; + } player->GetSession()->SendBattlegGroundList( GetGUID(), bgTypeId ); break; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 1f738eb52..702f6cf17 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8611" + #define REVISION_NR "8612" #endif // __REVISION_NR_H__ From 21de4570dcf7d9c5004dfc64bd87663ab03e3160 Mon Sep 17 00:00:00 2001 From: balrok Date: Sat, 10 Oct 2009 01:35:53 +0200 Subject: [PATCH 16/20] [8613] mail from battlemasters should be deleted after one day --- src/game/Mail.cpp | 10 ++++++++++ src/shared/revision_nr.h | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/game/Mail.cpp b/src/game/Mail.cpp index 98b85dbbd..f3077c168 100644 --- a/src/game/Mail.cpp +++ b/src/game/Mail.cpp @@ -28,6 +28,7 @@ #include "Unit.h" #include "Language.h" #include "DBCStores.h" +#include "BattleGroundMgr.h" enum MailShowFlags { @@ -823,6 +824,15 @@ void WorldSession::SendMailTo(Player* receiver, uint8 messageType, uint8 station expire_delay = HOUR; else expire_delay = (COD > 0) ? 3 * DAY : 30 * DAY; + if (messageType == MAIL_CREATURE) + { + // mail from battlemaster (rewardmarks) should last only one day + BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(sender_guidlow_or_entry); + if (bgTypeId != BATTLEGROUND_TYPE_NONE) + expire_delay = DAY; + } + + time_t expire_time = deliver_time + expire_delay; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 702f6cf17..fefeeb2af 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8612" + #define REVISION_NR "8613" #endif // __REVISION_NR_H__ From 17b0c43ea982f666b91444d5a4e2395686c2d52d Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sat, 10 Oct 2009 11:40:11 +0400 Subject: [PATCH 17/20] [8614] Simplify check, drop redundent break. --- src/game/SpellMgr.cpp | 9 ++------- src/shared/revision_nr.h | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index c9407f88f..e69a9877c 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -2825,14 +2825,9 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell { if (!player) return SPELL_FAILED_REQUIRES_AREA; - MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); - if (!mapEntry) - return SPELL_FAILED_REQUIRES_AREA; - if (!mapEntry->IsBattleGround()) - return SPELL_FAILED_REQUIRES_AREA; BattleGround* bg = player->GetBattleGround(); - return map_id == 30 && bg && bg->GetStatus()!=STATUS_WAIT_JOIN ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA; - break; + return map_id == 30 && bg + && bg->GetStatus() != STATUS_WAIT_JOIN ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA; } case 23333: // Warsong Flag case 23335: // Silverwing Flag diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index fefeeb2af..8a14f89ee 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8613" + #define REVISION_NR "8614" #endif // __REVISION_NR_H__ From 29e660133583077caea454b2a6a39764dd2db823 Mon Sep 17 00:00:00 2001 From: balrok Date: Sat, 10 Oct 2009 10:07:32 +0200 Subject: [PATCH 18/20] [8615] fixed wrong assert in av-code when alliance captured snowfall and horde assaulted this grave while assault in progress crashes could happen --- src/game/BattleGroundAV.cpp | 3 ++- src/shared/revision_nr.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/game/BattleGroundAV.cpp b/src/game/BattleGroundAV.cpp index 17bf3d7a9..160796925 100644 --- a/src/game/BattleGroundAV.cpp +++ b/src/game/BattleGroundAV.cpp @@ -737,7 +737,8 @@ void BattleGroundAV::AssaultNode(BG_AV_Nodes node, uint32 team) assert(team < 3); // alliance:0, horde:1, neutral:2 assert(m_Nodes[node].TotalOwner != team); assert(m_Nodes[node].Owner != team); - assert(m_Nodes[node].State != POINT_ASSAULTED || !m_Nodes[node].TotalOwner ); // only assault an assaulted node if no totalowner exists + // only assault an assaulted node if no totalowner exists: + assert(m_Nodes[node].State != POINT_ASSAULTED || m_Nodes[node].TotalOwner == BG_AV_NEUTRAL_TEAM); // the timer gets another time, if the previous owner was 0 == Neutral m_Nodes[node].Timer = (m_Nodes[node].PrevOwner != BG_AV_NEUTRAL_TEAM) ? BG_AV_CAPTIME : BG_AV_SNOWFALL_FIRSTCAP; m_Nodes[node].PrevOwner = m_Nodes[node].Owner; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 8a14f89ee..168576ebd 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8614" + #define REVISION_NR "8615" #endif // __REVISION_NR_H__ From f5db4fc163b2d3983fa3ac222fe84fb5c1f6d61c Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sat, 10 Oct 2009 12:11:59 +0400 Subject: [PATCH 19/20] [8616] Some cleanups in WorldSession::SendMailTo --- src/game/Mail.cpp | 33 +++++++++++++++------------------ src/shared/revision_nr.h | 2 +- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/game/Mail.cpp b/src/game/Mail.cpp index f3077c168..3190d12dd 100644 --- a/src/game/Mail.cpp +++ b/src/game/Mail.cpp @@ -818,35 +818,32 @@ void WorldSession::SendMailTo(Player* receiver, uint8 messageType, uint8 station time_t deliver_time = time(NULL) + deliver_delay; - // expire time if COD 3 days, if no COD 30 days, if auction sale pending 1 hour uint32 expire_delay; - if(messageType == MAIL_AUCTION && !mi && !money) // auction mail without any items and money + // auction mail without any items and money (auction sale note) pending 1 hour + if (messageType == MAIL_AUCTION && !mi && !money) expire_delay = HOUR; + // mail from battlemaster (rewardmarks) should last only one day + else if (messageType == MAIL_CREATURE && sBattleGroundMgr.GetBattleMasterBG(sender_guidlow_or_entry) != BATTLEGROUND_TYPE_NONE) + expire_delay = DAY; + // default case: expire time if COD 3 days, if no COD 30 days else expire_delay = (COD > 0) ? 3 * DAY : 30 * DAY; - if (messageType == MAIL_CREATURE) - { - // mail from battlemaster (rewardmarks) should last only one day - BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(sender_guidlow_or_entry); - if (bgTypeId != BATTLEGROUND_TYPE_NONE) - expire_delay = DAY; - } time_t expire_time = deliver_time + expire_delay; - if(mailTemplateId && !sMailTemplateStore.LookupEntry(mailTemplateId)) + if (mailTemplateId && !sMailTemplateStore.LookupEntry(mailTemplateId)) { sLog.outError( "WorldSession::SendMailTo - Mail have not existed MailTemplateId (%u), remove at send", mailTemplateId); mailTemplateId = 0; } - if(receiver) + if (receiver) { receiver->AddNewMailDeliverTime(deliver_time); - if ( receiver->IsMailsLoaded() ) + if (receiver->IsMailsLoaded()) { Mail *m = new Mail; m->messageID = mailId; @@ -858,7 +855,7 @@ void WorldSession::SendMailTo(Player* receiver, uint8 messageType, uint8 station m->subject = subject; m->itemTextId = itemTextId; - if(mi) + if (mi) m->AddAllItems(*mi); m->expire_time = expire_time; @@ -870,20 +867,20 @@ void WorldSession::SendMailTo(Player* receiver, uint8 messageType, uint8 station receiver->AddMail(m); // to insert new mail to beginning of maillist - if(mi) + if (mi) { for(MailItemMap::iterator mailItemIter = mi->begin(); mailItemIter != mi->end(); ++mailItemIter) { MailItem& mailItem = mailItemIter->second; - if(mailItem.item) + if (mailItem.item) receiver->AddMItem(mailItem.item); } } } - else if(mi) + else if (mi) mi->deleteIncludedItems(); } - else if(mi) + else if (mi) mi->deleteIncludedItems(); CharacterDatabase.BeginTransaction(); @@ -892,7 +889,7 @@ void WorldSession::SendMailTo(Player* receiver, uint8 messageType, uint8 station "VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '%s', '%u', '%u', '" UI64FMTD "','" UI64FMTD "', '%u', '%u', '%d')", mailId, messageType, stationery, mailTemplateId, sender_guidlow_or_entry, receiver_guidlow, subject.c_str(), itemTextId, (mi && !mi->empty() ? 1 : 0), (uint64)expire_time, (uint64)deliver_time, money, COD, checked); - if(mi) + if (mi) { for(MailItemMap::const_iterator mailItemIter = mi->begin(); mailItemIter != mi->end(); ++mailItemIter) { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 168576ebd..ea33176bb 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8615" + #define REVISION_NR "8616" #endif // __REVISION_NR_H__ From ddb67f69cad51fc1e03f8ce62b091cd7dfd1989e Mon Sep 17 00:00:00 2001 From: Lutik Date: Sat, 10 Oct 2009 14:49:31 +0400 Subject: [PATCH 20/20] [8617] Update resilience affect for 3.2.x Signed-off-by: VladimirMangos --- src/game/Player.cpp | 30 ++++++++++++++++++++++++------ src/game/Player.h | 4 +++- src/game/SpellAuras.cpp | 10 ---------- src/game/Unit.cpp | 11 +++++++++++ src/shared/revision_nr.h | 2 +- 5 files changed, 39 insertions(+), 18 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 88541ba6c..14ac2c082 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -4823,6 +4823,15 @@ uint32 Player::GetMeleeCritDamageReduction(uint32 damage) const return uint32 (melee * damage /100.0f); } +uint32 Player::GetMeleeDamageReduction(uint32 damage) const +{ + float rate = GetRatingBonusValue(CR_CRIT_TAKEN_MELEE); + // Resilience not limited (limit it by 100%) + if (rate > 100.0f) + rate = 100.0f; + return uint32 (rate * damage / 100.0f); +} + uint32 Player::GetRangedCritDamageReduction(uint32 damage) const { float ranged = GetRatingBonusValue(CR_CRIT_TAKEN_RANGED)*2.2f; @@ -4830,6 +4839,15 @@ uint32 Player::GetRangedCritDamageReduction(uint32 damage) const return uint32 (ranged * damage /100.0f); } +uint32 Player::GetRangedDamageReduction(uint32 damage) const +{ + float rate = GetRatingBonusValue(CR_CRIT_TAKEN_RANGED); + // Resilience not limited (limit it by 100%) + if (rate > 100.0f) + rate = 100.0f; + return uint32 (rate * damage / 100.0f); +} + uint32 Player::GetSpellCritDamageReduction(uint32 damage) const { float spell = GetRatingBonusValue(CR_CRIT_TAKEN_SPELL)*2.2f; @@ -4839,13 +4857,13 @@ uint32 Player::GetSpellCritDamageReduction(uint32 damage) const return uint32 (spell * damage / 100.0f); } -uint32 Player::GetDotDamageReduction(uint32 damage) const +uint32 Player::GetSpellDamageReduction(uint32 damage) const { - float spellDot = GetRatingBonusValue(CR_CRIT_TAKEN_SPELL); - // Dot resilience not limited (limit it by 100%) - if (spellDot > 100.0f) - spellDot = 100.0f; - return uint32 (spellDot * damage / 100.0f); + float rate = GetRatingBonusValue(CR_CRIT_TAKEN_SPELL); + // Resilience not limited (limit it by 100%) + if (rate > 100.0f) + rate = 100.0f; + return uint32 (rate * damage / 100.0f); } float Player::GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const diff --git a/src/game/Player.h b/src/game/Player.h index 5d0a4fbcf..39a25e8f0 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1723,9 +1723,11 @@ class MANGOS_DLL_SPEC Player : public Unit float GetRatingCoefficient(CombatRating cr) const; float GetRatingBonusValue(CombatRating cr) const; uint32 GetMeleeCritDamageReduction(uint32 damage) const; + uint32 GetMeleeDamageReduction(uint32 damage) const; uint32 GetRangedCritDamageReduction(uint32 damage) const; + uint32 GetRangedDamageReduction(uint32 damage) const; uint32 GetSpellCritDamageReduction(uint32 damage) const; - uint32 GetDotDamageReduction(uint32 damage) const; + uint32 GetSpellDamageReduction(uint32 damage) const; uint32 GetBaseSpellPowerBonus() { return m_baseSpellPower; } float GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const; diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 6948cbd00..c1723f711 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -6355,11 +6355,6 @@ void Aura::PeriodicTick() // This method can modify pdamage bool isCrit = IsCritFromAbilityAura(pCaster, pdamage); - // As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit - // Reduce dot damage from resilience for players - if (m_target->GetTypeId() == TYPEID_PLAYER) - pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage); - pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist); sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", @@ -6415,11 +6410,6 @@ void Aura::PeriodicTick() pdamage = pCaster->SpellDamageBonus(m_target, GetSpellProto(), pdamage, DOT, GetStackAmount()); - // As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit - // Reduce dot damage from resilience for players - if (m_target->GetTypeId()==TYPEID_PLAYER) - pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage); - pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist); if(m_target->GetHealth() < pdamage) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 3b19f33d9..e0d330cb8 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -1120,6 +1120,9 @@ void Unit::CalculateSpellDamage(SpellNonMeleeDamage *damageInfo, int32 damage, S break; } + if (GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER) + damage -= ((Player*)pVictim)->GetSpellDamageReduction(damage); + // Calculate absorb resist if(damage > 0) { @@ -1408,6 +1411,14 @@ void Unit::CalculateMeleeDamage(Unit *pVictim, uint32 damage, CalcDamageInfo *da break; } + if (GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER) + { + if (attackType != RANGED_ATTACK) + damage-=((Player*)pVictim)->GetMeleeDamageReduction(damage); + else + damage-=((Player*)pVictim)->GetRangedDamageReduction(damage); + } + // Calculate absorb resist if(int32(damageInfo->damage) > 0) { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index ea33176bb..eb7705dbc 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8616" + #define REVISION_NR "8617" #endif // __REVISION_NR_H__