diff options
Diffstat (limited to 'src')
58 files changed, 2806 insertions, 1902 deletions
diff --git a/src/framework/Platform/Define.h b/src/framework/Platform/Define.h index 7a7bdcab419..59c2418c745 100644 --- a/src/framework/Platform/Define.h +++ b/src/framework/Platform/Define.h @@ -57,6 +57,8 @@ # define TRINITY_GET_PROC_ADDR dlsym # if defined(__APPLE_CC__) && defined(BIG_ENDIAN) # define TRINITY_IMPORT __attribute__ ((longcall)) +# elif defined(__x86_64__) +# define TRINITY_IMPORT # else # define TRINITY_IMPORT __attribute__ ((cdecl)) # endif //__APPLE_CC__ && BIG_ENDIAN diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 6048c8ea78d..3acf2caa5a5 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -308,7 +308,10 @@ void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *cri void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement) { - sLog.outDebug("AchievementMgr::SendAchievementEarned(%u)", achievement->ID); + #ifdef MANGOS_DEBUG + if((sLog.getLogFilter() & LOG_FILTER_ACHIEVEMENT_UPDATES)==0) + sLog.outDebug("AchievementMgr::SendAchievementEarned(%u)", achievement->ID); + #endif if(Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId())) { @@ -392,7 +395,8 @@ static const uint32 achievIdForDangeon[][4] = */ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1, uint32 miscvalue2, Unit *unit, uint32 time) { - sLog.outDetail("AchievementMgr::UpdateAchievementCriteria(%u, %u, %u, %u)", type, miscvalue1, miscvalue2, time); + if((sLog.getLogFilter() & LOG_FILTER_ACHIEVEMENT_UPDATES)==0) + sLog.outDetail("AchievementMgr::UpdateAchievementCriteria(%u, %u, %u, %u)", type, miscvalue1, miscvalue2, time); if (!sWorld.getConfig(CONFIG_GM_ALLOW_ACHIEVEMENT_GAINS) && m_player->GetSession()->GetSecurity() > SEC_PLAYER) return; @@ -455,6 +459,54 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; if(achievementCriteria->kill_creature.creatureID != miscvalue1) continue; + + // LOT achievement->ID required special custom checks + switch(achievement->ID) + { + // Just heroic + case 489: case 490: case 491: case 492: case 493: case 494: case 495: + case 496: case 497: case 498: case 499: case 500: case 563: case 565: + case 567: case 569: case 573: case 575: case 577: case 623: case 625: + case 667: case 668: case 669: case 670: case 671: case 672: case 673: + case 674: case 675: case 676: case 677: case 678: case 679: case 680: + case 681: case 682: case 1367: case 1368: case 1378: case 1379: + case 1380: case 1381: case 1382: case 1383: case 1384: case 1385: + case 1386: case 1387: case 1388: case 1389: case 1390: case 1393: + case 1394: case 1400: case 1402: case 1504: case 1505: case 1506: + case 1507: case 1508: case 1509: case 1510: case 1511: case 1512: + case 1513: case 1514: case 1515: case 1721: case 1754: case 1756: + case 1768: case 1817: case 1865: + if(GetPlayer()->GetDifficulty()!=DIFFICULTY_HEROIC) + continue; + break; + // Heroic + other + case 579: case 1296: case 1297: case 1816: case 1834: case 1857: case 1859: + case 1860: case 1861: case 1862: case 1864: case 1866: case 1867: case 1868: + case 1870: case 1871: case 1872: case 1873: case 1875: case 1877: case 1919: + case 2036: case 2037: case 2038: case 2039: case 2040: case 2041: case 2042: + case 2043: case 2044: case 2045: case 2046: case 2048: case 2052: case 2053: + case 2054: case 2056: case 2057: case 2058: case 2139: case 2140: case 2147: + case 2149: case 2150: case 2151: case 2152: case 2154: case 2155: case 2156: + case 2157: case 2179: case 2181: case 2183: case 2185: case 2186: + if(GetPlayer()->GetDifficulty()!=DIFFICULTY_HEROIC) + continue; + // FIX ME: mark as fail always until implement + continue; + // Normal + other + case 578: case 624: case 1790: case 1856: case 1858: case 1869: case 1874: + case 1996: case 1997: case 2047: case 2049: case 2050: case 2051: case 2146: + case 2148: case 2153: case 2178: case 2180: case 2182: case 2184: case 2187: + if(GetPlayer()->GetDifficulty()!=DIFFICULTY_NORMAL) + continue; + // FIX ME: mark as fail always until implement + continue; + // Just Normal + default: + if(GetPlayer()->GetDifficulty()!=DIFFICULTY_NORMAL) + continue; + break; + }; + SetCriteriaProgress(achievementCriteria, miscvalue2, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: @@ -1023,7 +1075,9 @@ AchievementCompletionState AchievementMgr::GetAchievementCompletionState(Achieve void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 changeValue, ProgressType ptype) { - sLog.outDetail("AchievementMgr::SetCriteriaProgress(%u, %u) for (GUID:%u)", entry->ID, changeValue); + if((sLog.getLogFilter() & LOG_FILTER_ACHIEVEMENT_UPDATES)==0) + sLog.outDetail("AchievementMgr::SetCriteriaProgress(%u, %u) for (GUID:%u)", entry->ID, changeValue); + CriteriaProgress *progress = NULL; CriteriaProgressMap::iterator iter = m_criteriaProgress.find(entry->ID); diff --git a/src/game/ArenaTeam.cpp b/src/game/ArenaTeam.cpp index a556210d4c5..96e279f7d83 100644 --- a/src/game/ArenaTeam.cpp +++ b/src/game/ArenaTeam.cpp @@ -575,6 +575,28 @@ void ArenaTeam::MemberLost(Player * plr, uint32 againstRating) } } +void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstRating) +{ + // called for offline player after ending rated arena match! + for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + { + if(itr->guid == guid) + { + // update personal rating + float chance = GetChanceAgainst(itr->personal_rating, againstRating); + int32 mod = (int32)ceil(32.0f * (0.0f - chance)); + if (int32(itr->personal_rating) + mod < 0) + itr->personal_rating = 0; + else + itr->personal_rating += mod; + // update personal played stats + itr->games_week +=1; + itr->games_season +=1; + return; + } + } +} + void ArenaTeam::MemberWon(Player * plr, uint32 againstRating) { // called for each participant after winning a match diff --git a/src/game/ArenaTeam.h b/src/game/ArenaTeam.h index eb19c984f05..60c80f972d2 100644 --- a/src/game/ArenaTeam.h +++ b/src/game/ArenaTeam.h @@ -200,6 +200,7 @@ class ArenaTeam void MemberWon(Player * plr, uint32 againstRating); int32 LostAgainst(uint32 againstRating); void MemberLost(Player * plr, uint32 againstRating); + void OfflineMemberLost(uint64 guid, uint32 againstRating); void UpdateArenaPointsHelper(std::map<uint32, uint32> & PlayerPoints); diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 316d82db626..abef4f823d5 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -25,7 +25,6 @@ #include "Creature.h" #include "MapManager.h" #include "Language.h" -#include "Chat.h" #include "SpellAuras.h" #include "ArenaTeam.h" #include "World.h" @@ -33,6 +32,98 @@ #include "ObjectMgr.h" #include "WorldPacket.h" #include "Util.h" +#include "Formulas.h" +#include "GridNotifiersImpl.h" + +namespace MaNGOS +{ + class BattleGroundChatBuilder + { + public: + BattleGroundChatBuilder(ChatMsg msgtype, int32 textId, Player const* source, va_list* args = NULL) + : i_msgtype(msgtype), 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) + { + uint64 target_guid = i_source ? i_source ->GetGUID() : 0; + + data << uint8(i_msgtype); + data << uint32(LANG_UNIVERSAL); + data << uint64(target_guid); // there 0 for BG messages + data << uint32(0); // can be chat msg group or something + data << uint64(target_guid); + data << uint32(strlen(text)+1); + data << text; + data << uint8(i_source ? i_source->chatTag() : uint8(0)); + } + + ChatMsg i_msgtype; + int32 i_textId; + Player const* i_source; + va_list* i_args; + }; + + class BattleGround2ChatBuilder + { + public: + BattleGround2ChatBuilder(ChatMsg msgtype, int32 textId, Player const* source, int32 arg1, int32 arg2) + : i_msgtype(msgtype), 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 ); + + uint64 target_guid = i_source ? i_source ->GetGUID() : 0; + + data << uint8(i_msgtype); + data << uint32(LANG_UNIVERSAL); + data << uint64(target_guid); // there 0 for BG messages + data << uint32(0); // can be chat msg group or something + data << uint64(target_guid); + data << uint32(strlen(str)+1); + data << str; + data << uint8(i_source ? i_source->chatTag() : uint8(0)); + } + private: + + ChatMsg i_msgtype; + int32 i_textId; + Player const* i_source; + int32 i_arg1; + int32 i_arg2; + }; +} // namespace MaNGOS + +template<class Do> +void BattleGround::BroadcastWorker(Do& _do) +{ + for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + if(Player *plr = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER))) + _do(plr); +} BattleGround::BattleGround() { @@ -140,55 +231,30 @@ BattleGround::~BattleGround() void BattleGround::Update(uint32 diff) { - if(!GetPlayersSize() && !GetRemovedPlayersSize() && !GetReviveQueueSize()) + if(!GetPlayersSize() && !GetReviveQueueSize()) //BG is empty return; - if(GetRemovedPlayersSize()) + // remove offline players from bg after 5 minutes + if( !m_OfflineQueue.empty() ) { - for(std::map<uint64, uint8>::iterator itr = m_RemovedPlayers.begin(); itr != m_RemovedPlayers.end(); ++itr) + BattleGroundPlayerMap::iterator itr = m_Players.find(*(m_OfflineQueue.begin())); + if( itr != m_Players.end() ) { - Player *plr = objmgr.GetPlayer(itr->first); - switch(itr->second) + if( itr->second.OfflineRemoveTime <= sWorld.GetGameTime() ) { - case 1: // currently in bg and was removed from bg - if(plr) - RemovePlayerAtLeave(itr->first, true, true); - else - RemovePlayerAtLeave(itr->first, false, false); - break; - case 2: // revive queue - RemovePlayerFromResurrectQueue(itr->first); - break; - default: - sLog.outError("BattleGround: Unknown remove player case!"); + RemovePlayerAtLeave(itr->first, true, true);// remove player from BG + m_OfflineQueue.pop_front(); // remove from offline queue + //do not use itr for anything, because it is erased in RemovePlayerAtLeave() } } - m_RemovedPlayers.clear(); - } - - // remove offline players from bg after ~5 minutes - if(GetPlayersSize()) - { - for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) - { - Player *plr = objmgr.GetPlayer(itr->first); - itr->second.LastOnlineTime += diff; - - if(plr) - itr->second.LastOnlineTime = 0; // update last online time - else - if(itr->second.LastOnlineTime >= MAX_OFFLINE_TIME) // 5 minutes - m_RemovedPlayers[itr->first] = 1; // add to remove list (BG) - } } - //TODO: move this system to spell system and ressurect players correclt there! /*********************************************************/ /*** BATTLEGROUND RESSURECTION SYSTEM ***/ /*********************************************************/ - //this should be handled by spell system: + //this should be handled by spell system m_LastResurrectTime += diff; if (m_LastResurrectTime >= RESURRECTION_INTERVAL) { @@ -253,7 +319,13 @@ void BattleGround::Update(uint32 diff) else if(m_PrematureCountDownTimer < diff) { // time's up! - EndBattleGround(0); // noone wins + uint32 winner = 0; + if( GetPlayersCountByTeam(ALLIANCE) >= GetMinPlayersPerTeam() ) + winner = ALLIANCE; + else if( GetPlayersCountByTeam(HORDE) >= GetMinPlayersPerTeam() ) + winner = HORDE; + + EndBattleGround(winner); m_PrematureCountDown = false; } else @@ -263,13 +335,13 @@ void BattleGround::Update(uint32 diff) if( newtime > (MINUTE * IN_MILISECONDS) ) { if( newtime / (MINUTE * IN_MILISECONDS) != m_PrematureCountDownTimer / (MINUTE * IN_MILISECONDS) ) - PSendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING, CHAT_MSG_SYSTEM, (uint32)(m_PrematureCountDownTimer / (MINUTE * IN_MILISECONDS))); + PSendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING, CHAT_MSG_SYSTEM, NULL, (uint32)(m_PrematureCountDownTimer / (MINUTE * IN_MILISECONDS))); } else { //announce every 15 seconds if( newtime / (15 * IN_MILISECONDS) != m_PrematureCountDownTimer / (15 * IN_MILISECONDS) ) - PSendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS, CHAT_MSG_SYSTEM, (uint32)(m_PrematureCountDownTimer / IN_MILISECONDS)); + PSendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS, CHAT_MSG_SYSTEM, NULL, (uint32)(m_PrematureCountDownTimer / IN_MILISECONDS)); } m_PrematureCountDownTimer = newtime; } @@ -327,16 +399,13 @@ void BattleGround::Update(uint32 diff) //remove preparation if( isArena() ) { - //TODO : add arena sound (PlaySoundToAll(SOUND_ARENA_START); + //TODO : add arena sound PlaySoundToAll(SOUND_ARENA_START); for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) if(Player *plr = objmgr.GetPlayer(itr->first)) plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); - if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) - EndBattleGround(HORDE); - else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE)) - EndBattleGround(ALLIANCE); + CheckArenaWinConditions(); } else { @@ -346,7 +415,7 @@ void BattleGround::Update(uint32 diff) for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) if(Player* plr = objmgr.GetPlayer(itr->first)) plr->RemoveAurasDueToSpell(SPELL_PREPARATION); - //Announce BG starting: + //Announce BG starting if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) ) { sWorld.SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, GetName(), GetMinLevel(), GetMaxLevel()); @@ -365,11 +434,15 @@ void BattleGround::Update(uint32 diff) m_EndTime += diff; if(m_EndTime >= TIME_TO_AUTOREMOVE) // 2 minutes { - for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + BattleGroundPlayerMap::iterator itr, next; + for(itr = m_Players.begin(); itr != m_Players.end(); itr = next) { - m_RemovedPlayers[itr->first] = 1; // add to remove list (BG) + next = itr; + ++next; + //itr is erased here! + RemovePlayerAtLeave(itr->first, true, true);// remove player from BG + // do not change any battleground's private variables } - // do not change any battleground's private variables } } @@ -386,7 +459,7 @@ void BattleGround::SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, flo void BattleGround::SendPacketToAll(WorldPacket *packet) { - for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); if(plr) @@ -398,7 +471,7 @@ void BattleGround::SendPacketToAll(WorldPacket *packet) void BattleGround::SendPacketToTeam(uint32 TeamID, WorldPacket *packet, Player *sender, bool self) { - for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); @@ -430,7 +503,7 @@ void BattleGround::PlaySoundToTeam(uint32 SoundID, uint32 TeamID) { WorldPacket data; - for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); @@ -453,7 +526,7 @@ void BattleGround::PlaySoundToTeam(uint32 SoundID, uint32 TeamID) void BattleGround::CastSpellOnTeam(uint32 SpellID, uint32 TeamID) { - for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); @@ -490,7 +563,7 @@ void BattleGround::YellToAll(Creature* creature, const char* text, uint32 langua void BattleGround::RewardHonorToTeam(uint32 Honor, uint32 TeamID) { - for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); @@ -515,7 +588,7 @@ void BattleGround::RewardReputationToTeam(uint32 faction_id, uint32 Reputation, if(!factionEntry) return; - for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); @@ -556,15 +629,11 @@ void BattleGround::EndBattleGround(uint32 winner) uint32 loser_rating = 0; uint32 winner_rating = 0; WorldPacket data; - Player *Source = NULL; - const char *winmsg = ""; + int32 winmsg_id = 0; if(winner == ALLIANCE) { - if(isBattleGround()) - winmsg = GetTrinityString(LANG_BG_A_WINS); - else - winmsg = GetTrinityString(LANG_ARENA_GOLD_WINS); + winmsg_id = isBattleGround() ? LANG_BG_A_WINS : LANG_ARENA_GOLD_WINS; PlaySoundToAll(SOUND_ALLIANCE_WINS); // alliance wins sound @@ -572,10 +641,7 @@ void BattleGround::EndBattleGround(uint32 winner) } else if(winner == HORDE) { - if(isBattleGround()) - winmsg = GetTrinityString(LANG_BG_H_WINS); - else - winmsg = GetTrinityString(LANG_ARENA_GREEN_WINS); + winmsg_id = isBattleGround() ? LANG_BG_H_WINS : LANG_ARENA_GREEN_WINS; PlaySoundToAll(SOUND_HORDE_WINS); // horde wins sound @@ -592,33 +658,17 @@ void BattleGround::EndBattleGround(uint32 winner) // arena rating calculation if(isArena() && isRated()) { - if(winner == ALLIANCE) - { - winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); - loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); - } - else if(winner == HORDE) - { - winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); - loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); - } - if(winner_arena_team && loser_arena_team) + winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(winner)); + loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(winner))); + if( winner_arena_team && loser_arena_team ) { loser_rating = loser_arena_team->GetStats().rating; winner_rating = winner_arena_team->GetStats().rating; int32 winner_change = winner_arena_team->WonAgainst(loser_rating); int32 loser_change = loser_arena_team->LostAgainst(winner_rating); sLog.outDebug("--- Winner rating: %u, Loser rating: %u, Winner change: %u, Losser change: %u ---", winner_rating, loser_rating, winner_change, loser_change); - if(winner == ALLIANCE) - { - SetArenaTeamRatingChangeForTeam(ALLIANCE, winner_change); - SetArenaTeamRatingChangeForTeam(HORDE, loser_change); - } - else - { - SetArenaTeamRatingChangeForTeam(HORDE, winner_change); - SetArenaTeamRatingChangeForTeam(ALLIANCE, loser_change); - } + SetArenaTeamRatingChangeForTeam(winner, winner_change); + SetArenaTeamRatingChangeForTeam(GetOtherTeam(winner), loser_change); } else { @@ -627,11 +677,21 @@ void BattleGround::EndBattleGround(uint32 winner) } } - for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); + uint32 team = itr->second.Team; + if(!plr) { + //if rated arena match - make member lost! + if(isArena() && isRated() && winner_arena_team && loser_arena_team) + { + if(team == winner) + winner_arena_team->OfflineMemberLost(itr->first, loser_rating); + else + loser_arena_team->OfflineMemberLost(itr->first, winner_rating); + } sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first); continue; } @@ -646,8 +706,8 @@ void BattleGround::EndBattleGround(uint32 winner) plr->SpawnCorpseBones(); } - uint32 team = itr->second.Team; - if(!team) team = plr->GetTeam(); + //this line is obsolete - team is set ALWAYS + //if(!team) team = plr->GetTeam(); // per player calculation if(isArena() && isRated() && winner_arena_team && loser_arena_team) @@ -660,10 +720,7 @@ void BattleGround::EndBattleGround(uint32 winner) if(team == winner) { - if(!Source) - Source = plr; RewardMark(plr,ITEM_WINNER_COUNT); - UpdatePlayerScore(plr, SCORE_BONUS_HONOR, 20); RewardQuest(plr); } else @@ -679,7 +736,7 @@ void BattleGround::EndBattleGround(uint32 winner) plr->GetSession()->SendPacket(&data); BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType()); - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); plr->GetSession()->SendPacket(&data); plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1); } @@ -701,11 +758,14 @@ void BattleGround::EndBattleGround(uint32 winner) // inform invited players about the removal sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); - if(Source) - { - ChatHandler(Source).FillMessageData(&data, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, Source->GetGUID(), winmsg); - SendPacketToAll(&data); - } + if(winmsg_id) + SendMessageToAll(winmsg_id, CHAT_MSG_BG_SYSTEM_NEUTRAL); +} + +uint32 BattleGround::GetBonusHonorFromKill(uint32 kills) const +{ + //variable kills means how many honorable kills you scored (so we need kills * honor_for_one_kill) + return MaNGOS::Honor::hk_honor_at_level(GetMaxLevel(), kills); } uint32 BattleGround::GetBattlemasterEntry() const @@ -841,10 +901,10 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac uint32 team = GetPlayerTeam(guid); bool participant = false; // Remove from lists/maps - std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.find(guid); + BattleGroundPlayerMap::iterator itr = m_Players.find(guid); if(itr != m_Players.end()) { - UpdatePlayersCountByTeam(team, true); // -1 player + UpdatePlayersCountByTeam(team, true); // -1 player m_Players.erase(itr); // check if the player was a participant of the match, or only entered through gm command (goname) participant = true; @@ -873,21 +933,21 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac RemovePlayer(plr, guid); // BG subclass specific code - if(plr) + if(participant) // if the player was a match participant, remove auras, calc rating, update queue { - plr->ClearAfkReports(); - - if(participant) // if the player was a match participant, remove auras, calc rating, update queue + BattleGroundTypeId bgTypeId = GetTypeID(); + BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType()); + if(plr) { + plr->ClearAfkReports(); + if(!team) team = plr->GetTeam(); - BattleGroundTypeId bgTypeId = GetTypeID(); - BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType()); // if arena, remove the specific arena auras if(isArena()) { - plr->RemoveArenaAuras(true); // removes debuffs / dots etc., we don't want the player to die after porting out - bgTypeId=BATTLEGROUND_AA; // set the bg type to all arenas (it will be used for queue refreshing) + plr->RemoveArenaAuras(true); // removes debuffs / dots etc., we don't want the player to die after porting out + bgTypeId=BATTLEGROUND_AA; // set the bg type to all arenas (it will be used for queue refreshing) // summon old pet if there was one and there isn't a current pet if(!plr->GetPet() && plr->GetTemporaryUnsummonedPetNumber()) @@ -902,65 +962,64 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac if(isRated() && GetStatus() == STATUS_IN_PROGRESS) { //left a rated match while the encounter was in progress, consider as loser - ArenaTeam * winner_arena_team = 0; - ArenaTeam * loser_arena_team = 0; - if(team == HORDE) - { - winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); - loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); - } - else - { - winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); - loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); - } + ArenaTeam * winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(team))); + ArenaTeam * loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(team)); if(winner_arena_team && loser_arena_team) - { loser_arena_team->MemberLost(plr,winner_arena_team->GetRating()); - } } } - - WorldPacket data; if(SendPacket) { - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, team, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0); + WorldPacket data; + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0); plr->GetSession()->SendPacket(&data); } // this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg plr->RemoveBattleGroundQueueId(bgQueueTypeId); - - DecreaseInvitedCount(team); - //we should update battleground queue, but only if bg isn't ending - if (GetStatus() < STATUS_WAIT_LEAVE) - sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, GetQueueId()); - - Group * group = plr->GetGroup(); - // remove from raid group if exist - if(group && group == GetBgRaid(team)) + } + else + // removing offline participant + { + if(isRated() && GetStatus() == STATUS_IN_PROGRESS) { - if(!group->RemoveMember(guid, 0)) // group was disbanded - { - SetBgRaid(team, NULL); - delete group; - } + //left a rated match while the encounter was in progress, consider as loser + ArenaTeam * others_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(team))); + ArenaTeam * players_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(team)); + if( others_arena_team && players_arena_team ) + players_arena_team->OfflineMemberLost(guid, others_arena_team->GetRating()); } + } - // Let others know - sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, plr); - SendPacketToTeam(team, &data, plr, false); + // remove from raid group if player is member + if(Group *group = GetBgRaid(team)) + { + if( !group->RemoveMember(guid, 0) ) // group was disbanded + { + SetBgRaid(team, NULL); + delete group; + } } + DecreaseInvitedCount(team); + //we should update battleground queue, but only if bg isn't ending + if( isBattleGround() && GetStatus() < STATUS_WAIT_LEAVE ) + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, GetQueueId()); + // Let others know + WorldPacket data; + sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, guid); + SendPacketToTeam(team, &data, plr, false); + } + if( plr ) + { // Do next only if found in battleground - plr->SetBattleGroundId(0, BATTLEGROUND_TYPE_NONE); // We're not in BG. + plr->SetBattleGroundId(0, BATTLEGROUND_TYPE_NONE); // We're not in BG. // reset destination bg team plr->SetBGTeam(0); if(Transport) plr->TeleportTo(plr->GetBattleGroundEntryPoint()); - // Log sLog.outDetail("BATTLEGROUND: Removed player %s from BattleGround.", plr->GetName()); } @@ -1018,7 +1077,7 @@ void BattleGround::AddPlayer(Player *plr) uint32 team = plr->GetBGTeam(); BattleGroundPlayer bp; - bp.LastOnlineTime = 0; + bp.OfflineRemoveTime = 0; bp.Team = team; // Add to list/maps @@ -1083,7 +1142,7 @@ void BattleGround::AddPlayer(Player *plr) } // setup BG group membership - PlayerRelogin(plr); + PlayerAddedToBGCheckIfBGIsRunning(plr); AddOrSetPlayerToCorrectBgGroup(plr, guid, team); // Log @@ -1112,6 +1171,38 @@ void BattleGround::AddOrSetPlayerToCorrectBgGroup(Player *plr, uint64 plr_guid, } } +// This method should be called when player logs into running battleground +void BattleGround::EventPlayerLoggedIn(Player* player, uint64 plr_guid) +{ + // player is correct pointer + for(std::deque<uint64>::iterator itr = m_OfflineQueue.begin(); itr != m_OfflineQueue.end(); ++itr) + { + if( *itr == plr_guid ) + { + m_OfflineQueue.erase(itr); + break; + } + } + m_Players[plr_guid].OfflineRemoveTime = 0; + PlayerAddedToBGCheckIfBGIsRunning(player); + // if battleground is starting, then add preparation aura + // we don't have to do that, because preparation aura isn't removed when player logs out +} + +// This method should be called when player logs out from running battleground +void BattleGround::EventPlayerLoggedOut(Player* player) +{ + // player is correct pointer, it is checked in WorldSession::LogoutPlayer() + m_OfflineQueue.push_back(player->GetGUID()); + m_Players[player->GetGUID()].OfflineRemoveTime = sWorld.GetGameTime() + MAX_OFFLINE_TIME; + if( GetStatus() == STATUS_IN_PROGRESS ) + { + if( isBattleGround() ) + EventPlayerDroppedFlag(player); + else + CheckArenaWinConditions(); + } +} /* This method should be called only once ... it adds pointer to queue */ void BattleGround::AddToBGFreeSlotQueue() @@ -1496,31 +1587,30 @@ bool BattleGround::AddSpiritGuide(uint32 type, float x, float y, float z, float return true; } -void BattleGround::SendMessageToAll(char const* text, uint8 type) +void BattleGround::SendMessageToAll(int32 entry, ChatMsg type, Player const* source) { - WorldPacket data; - ChatHandler::FillMessageData(&data, NULL, type, LANG_UNIVERSAL, NULL, 0, text, NULL); - SendPacketToAll(&data); + MaNGOS::BattleGroundChatBuilder bg_builder(type, entry, source); + MaNGOS::LocalizedPacketDo<MaNGOS::BattleGroundChatBuilder> bg_do(bg_builder); + BroadcastWorker(bg_do); } -void BattleGround::SendMessageToAll(int32 entry, uint8 type) +void BattleGround::PSendMessageToAll(int32 entry, ChatMsg type, Player const* source, ...) { - char const* text = GetTrinityString(entry); - WorldPacket data; - ChatHandler::FillMessageData(&data, NULL, type, LANG_UNIVERSAL, NULL, 0, text, NULL); - SendPacketToAll(&data); + va_list ap; + va_start(ap, source); + + MaNGOS::BattleGroundChatBuilder bg_builder(type, entry, source, &ap); + MaNGOS::LocalizedPacketDo<MaNGOS::BattleGroundChatBuilder> bg_do(bg_builder); + BroadcastWorker(bg_do); + + va_end(ap); } -//copied from void ChatHandler::PSendSysMessage(int32 entry, ...) -void BattleGround::PSendMessageToAll(int32 entry, uint8 type, ...) +void BattleGround::SendMessage2ToAll(int32 entry, ChatMsg type, Player const* source, int32 arg1, int32 arg2) { - const char *format = GetMangosString(entry); - va_list ap; - char str [2048]; - va_start(ap, type); - vsnprintf(str,2048,format, ap ); - va_end(ap); - SendMessageToAll(str, type); + MaNGOS::BattleGround2ChatBuilder bg_builder(type, entry, source, arg1, arg2); + MaNGOS::LocalizedPacketDo<MaNGOS::BattleGround2ChatBuilder> bg_do(bg_builder); + BroadcastWorker(bg_do); } void BattleGround::EndNow() @@ -1532,7 +1622,7 @@ void BattleGround::EndNow() sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); } -// Battleground messages are localized using the dbc lang, they are not client language dependent +//to be removed const char *BattleGround::GetTrinityString(int32 entry) { // FIXME: now we have different DBC locales and need localized message for each target client @@ -1592,7 +1682,7 @@ void BattleGround::HandleKillPlayer( Player *player, Player *killer ) UpdatePlayerScore(killer, SCORE_HONORABLE_KILLS, 1); UpdatePlayerScore(killer, SCORE_KILLING_BLOWS, 1); - for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); @@ -1612,21 +1702,26 @@ void BattleGround::HandleKillPlayer( Player *player, Player *killer ) // used in same faction arena matches mainly uint32 BattleGround::GetPlayerTeam(uint64 guid) { - std::map<uint64, BattleGroundPlayer>::const_iterator itr = m_Players.find(guid); + BattleGroundPlayerMap::const_iterator itr = m_Players.find(guid); if(itr!=m_Players.end()) return itr->second.Team; return 0; } +uint32 BattleGround::GetOtherTeam(uint32 teamId) +{ + return (teamId) ? ((teamId == ALLIANCE) ? HORDE : ALLIANCE) : 0; +} + bool BattleGround::IsPlayerInBattleGround(uint64 guid) { - std::map<uint64, BattleGroundPlayer>::const_iterator itr = m_Players.find(guid); - if(itr!=m_Players.end()) + BattleGroundPlayerMap::const_iterator itr = m_Players.find(guid); + if(itr != m_Players.end()) return true; return false; } -void BattleGround::PlayerRelogin(Player* plr) +void BattleGround::PlayerAddedToBGCheckIfBGIsRunning(Player* plr) { if(GetStatus() != STATUS_WAIT_LEAVE) return; @@ -1639,14 +1734,14 @@ void BattleGround::PlayerRelogin(Player* plr) sBattleGroundMgr.BuildPvpLogDataPacket(&data, this); plr->GetSession()->SendPacket(&data); - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); plr->GetSession()->SendPacket(&data); } uint32 BattleGround::GetAlivePlayersCountByTeam(uint32 Team) const { int count = 0; - for(std::map<uint64, BattleGroundPlayer>::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for(BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { if(itr->second.Team == Team) { @@ -1679,6 +1774,14 @@ void BattleGround::HandleKillUnit(Creature *creature, Player *killer) { } +void BattleGround::CheckArenaWinConditions() +{ + if( !GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE) ) + EndBattleGround(HORDE); + else if( GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE) ) + EndBattleGround(ALLIANCE); +} + void BattleGround::SetBgRaid( uint32 TeamID, Group *bg_raid ) { Group* &old_raid = TeamID == ALLIANCE ? m_BgRaids[BG_TEAM_ALLIANCE] : m_BgRaids[BG_TEAM_HORDE]; diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index ea691dc9750..857f1c9803e 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -89,11 +89,10 @@ enum BattleGroundTimeIntervals INVITATION_REMIND_TIME = 60000, // ms INVITE_ACCEPT_WAIT_TIME = 80000, // ms TIME_TO_AUTOREMOVE = 120000, // ms - MAX_OFFLINE_TIME = 300000, // ms + MAX_OFFLINE_TIME = 300, // secs RESPAWN_ONE_DAY = 86400, // secs RESPAWN_IMMEDIATELY = 0, // secs BUFF_RESPAWN_TIME = 180, // secs - BG_HONOR_SCORE_TICKS = 330 // points }; enum BattleGroundStartTimeIntervals @@ -125,7 +124,7 @@ enum BattleGroundStatus struct BattleGroundPlayer { - uint32 LastOnlineTime; // for tracking and removing offline players from queue after 5 minutes + time_t OfflineRemoveTime; // for tracking and removing offline players from queue after 5 minutes uint32 Team; // Player's team }; @@ -322,6 +321,7 @@ class BattleGround uint8 GetArenaType() const { return m_ArenaType; } uint8 GetWinner() const { return m_Winner; } uint32 GetBattlemasterEntry() const; + uint32 GetBonusHonorFromKill(uint32 kills) const; // Set methods: void SetName(char const* Name) { m_Name = Name; } @@ -374,7 +374,6 @@ class BattleGround typedef std::map<uint64, BattleGroundPlayer> BattleGroundPlayerMap; BattleGroundPlayerMap const& GetPlayers() const { return m_Players; } uint32 GetPlayersSize() const { return m_Players.size(); } - uint32 GetRemovedPlayersSize() const { return m_RemovedPlayers.size(); } std::map<uint64, BattleGroundScore*>::const_iterator GetPlayerScoresBegin() const { return m_PlayerScores.begin(); } std::map<uint64, BattleGroundScore*>::const_iterator GetPlayerScoresEnd() const { return m_PlayerScores.end(); } @@ -409,6 +408,10 @@ class BattleGround void SendPacketToTeam(uint32 TeamID, WorldPacket *packet, Player *sender = NULL, bool self = true); void SendPacketToAll(WorldPacket *packet); void YellToAll(Creature* creature, const char* text, uint32 language); + + template<class Do> + void BroadcastWorker(Do& _do); + void PlaySoundToTeam(uint32 SoundID, uint32 TeamID); void PlaySoundToAll(uint32 SoundID); void CastSpellOnTeam(uint32 SpellID, uint32 TeamID); @@ -422,9 +425,11 @@ class BattleGround void EndBattleGround(uint32 winner); void BlockMovement(Player *plr); - void SendMessageToAll(char const* text, uint8 type); - void SendMessageToAll(int32 entry, uint8 type); - void PSendMessageToAll(int32 entry, uint8 type, ... ); + void SendMessageToAll(int32 entry, ChatMsg type, Player const* source = NULL); + 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); /* Raid Group */ Group *GetBgRaid(uint32 TeamID) const { return TeamID == ALLIANCE ? m_BgRaids[BG_TEAM_ALLIANCE] : m_BgRaids[BG_TEAM_HORDE]; } @@ -445,9 +450,10 @@ class BattleGround // used for rated arena battles void SetArenaTeamIdForTeam(uint32 Team, uint32 ArenaTeamId) { m_ArenaTeamIds[GetTeamIndexByTeamId(Team)] = ArenaTeamId; } - uint32 GetArenaTeamIdForTeam(uint32 Team) const { return m_ArenaTeamIds[GetTeamIndexByTeamId(Team)]; } + uint32 GetArenaTeamIdForTeam(uint32 Team) const { return m_ArenaTeamIds[GetTeamIndexByTeamId(Team)]; } void SetArenaTeamRatingChangeForTeam(uint32 Team, int32 RatingChange) { m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)] = RatingChange; } - int32 GetArenaTeamRatingChangeForTeam(uint32 Team) const { return m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)]; } + int32 GetArenaTeamRatingChangeForTeam(uint32 Team) const { return m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)]; } + void CheckArenaWinConditions(); /* Triggers handle */ // must be implemented in BG subclass @@ -460,6 +466,8 @@ class BattleGround virtual void EventPlayerDroppedFlag(Player* /*player*/) {} virtual void EventPlayerClickedOnFlag(Player* /*player*/, GameObject* /*target_obj*/) {} virtual void EventPlayerCapturedFlag(Player* /*player*/) {} + void EventPlayerLoggedIn(Player* player, uint64 plr_guid); + void EventPlayerLoggedOut(Player* player); /* Death related */ virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); @@ -490,20 +498,22 @@ class BattleGround void DoorOpen(uint32 type); void DoorClose(uint32 type); + //to be removed const char *GetTrinityString(int32 entry); virtual bool HandlePlayerUnderMap(Player * /*plr*/) { return false; } // since arenas can be AvA or Hvh, we have to get the "temporary" team of a player uint32 GetPlayerTeam(uint64 guid); + uint32 GetOtherTeam(uint32 teamId); bool IsPlayerInBattleGround(uint64 guid); - void PlayerRelogin(Player* plr); void SetDeleteThis() {m_SetDeleteThis = true;} protected: //this method is called, when BG cannot spawn its own spirit guide, or something is wrong, It correctly ends BattleGround void EndNow(); + void PlayerAddedToBGCheckIfBGIsRunning(Player* plr); /* Scorekeeping */ // Player scores @@ -549,7 +559,7 @@ class BattleGround /* Player lists */ std::vector<uint64> m_ResurrectQueue; // Player GUID - std::map<uint64, uint8> m_RemovedPlayers; // uint8 is remove type (0 - bgqueue, 1 - bg, 2 - resurrect queue) + std::deque<uint64> m_OfflineQueue; // Player GUID /* Invited counters are useful for player invitation to BG - do not allow, if BG is started to one faction to have 2 more players than another faction */ /* Invited counters will be changed only when removing already invited player from queue, removing player from battleground and inviting player to BG */ diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp index a5dc765103e..4c882a46f78 100644 --- a/src/game/BattleGroundAB.cpp +++ b/src/game/BattleGroundAB.cpp @@ -23,7 +23,6 @@ #include "BattleGround.h" #include "BattleGroundAB.h" #include "Creature.h" -#include "Chat.h" #include "ObjectMgr.h" #include "Language.h" #include "World.h" @@ -98,13 +97,19 @@ void BattleGroundAB::Update(uint32 diff) _SendNodeUpdate(node); _NodeOccupied(node,(teamIndex == 0) ? ALLIANCE:HORDE); // Message to chatlog - char buf[256]; - uint8 type = (teamIndex == 0) ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE; - sprintf(buf, GetTrinityString(LANG_BG_AB_NODE_TAKEN), (teamIndex == 0) ? GetTrinityString(LANG_BG_AB_ALLY) : GetTrinityString(LANG_BG_AB_HORDE), _GetNodeName(node)); - WorldPacket data; - ChatHandler::FillMessageData(&data, NULL, type, LANG_UNIVERSAL, NULL, 0, buf, NULL); - SendPacketToAll(&data); - PlaySoundToAll((teamIndex == 0) ? SOUND_NODE_CAPTURED_ALLIANCE : SOUND_NODE_CAPTURED_HORDE); + + if(teamIndex == 0) + { + // FIXME: team and node names not localized + SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE,NULL,LANG_BG_AB_ALLY,_GetNodeNameId(node)); + PlaySoundToAll(SOUND_NODE_CAPTURED_ALLIANCE); + } + else + { + // FIXME: team and node names not localized + SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_HORDE,NULL,LANG_BG_AB_HORDE,_GetNodeNameId(node)); + PlaySoundToAll(SOUND_NODE_CAPTURED_HORDE); + } } } @@ -126,22 +131,22 @@ void BattleGroundAB::Update(uint32 diff) m_TeamScores[team] += BG_AB_TickPoints[points]; m_HonorScoreTics[team] += BG_AB_TickPoints[points]; m_ReputationScoreTics[team] += BG_AB_TickPoints[points]; - if( m_ReputationScoreTics[team] >= BG_AB_ReputationScoreTicks[m_HonorMode] ) + if( m_ReputationScoreTics[team] >= m_ReputationTics ) { (team == BG_TEAM_ALLIANCE) ? RewardReputationToTeam(509, 10, ALLIANCE) : RewardReputationToTeam(510, 10, HORDE); - m_ReputationScoreTics[team] -= BG_AB_ReputationScoreTicks[m_HonorMode]; + m_ReputationScoreTics[team] -= m_ReputationTics; } - if( m_HonorScoreTics[team] >= BG_AB_HonorScoreTicks[m_HonorMode] ) + if( m_HonorScoreTics[team] >= m_HonorTics ) { - (team == BG_TEAM_ALLIANCE) ? RewardHonorToTeam(20, ALLIANCE) : RewardHonorToTeam(20, HORDE); - m_HonorScoreTics[team] -= BG_AB_HonorScoreTicks[m_HonorMode]; + RewardHonorToTeam(GetBonusHonorFromKill(1), (team == BG_TEAM_ALLIANCE) ? ALLIANCE : HORDE); + m_HonorScoreTics[team] -= m_HonorTics; } if( !m_IsInformedNearVictory && m_TeamScores[team] > 1800 ) { if( team == BG_TEAM_ALLIANCE ) - SendMessageToAll(GetMangosString(LANG_BG_AB_A_NEAR_VICTORY), CHAT_MSG_BG_SYSTEM_NEUTRAL); + SendMessageToAll(LANG_BG_AB_A_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL); else - SendMessageToAll(GetMangosString(LANG_BG_AB_H_NEAR_VICTORY), CHAT_MSG_BG_SYSTEM_NEUTRAL); + SendMessageToAll(LANG_BG_AB_H_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL); PlaySoundToAll(SOUND_NEAR_VICTORY); m_IsInformedNearVictory = true; } @@ -281,24 +286,19 @@ void BattleGroundAB::_DelBanner(uint8 node, uint8 type, uint8 teamIndex) SpawnBGObject(obj, RESPAWN_ONE_DAY); } -const char* BattleGroundAB::_GetNodeName(uint8 node) +int32 BattleGroundAB::_GetNodeNameId(uint8 node) { switch (node) { - case BG_AB_NODE_STABLES: - return GetTrinityString(LANG_BG_AB_NODE_STABLES); - case BG_AB_NODE_BLACKSMITH: - return GetTrinityString(LANG_BG_AB_NODE_BLACKSMITH); - case BG_AB_NODE_FARM: - return GetTrinityString(LANG_BG_AB_NODE_FARM); - case BG_AB_NODE_LUMBER_MILL: - return GetTrinityString(LANG_BG_AB_NODE_LUMBER_MILL); - case BG_AB_NODE_GOLD_MINE: - return GetTrinityString(LANG_BG_AB_NODE_GOLD_MINE); + case BG_AB_NODE_STABLES: return LANG_BG_AB_NODE_STABLES; + case BG_AB_NODE_BLACKSMITH: return LANG_BG_AB_NODE_BLACKSMITH; + case BG_AB_NODE_FARM: return LANG_BG_AB_NODE_FARM; + case BG_AB_NODE_LUMBER_MILL:return LANG_BG_AB_NODE_LUMBER_MILL; + case BG_AB_NODE_GOLD_MINE: return LANG_BG_AB_NODE_GOLD_MINE; default: ASSERT(0); } - return ""; + return 0; } void BattleGroundAB::FillInitialWorldStates(WorldPacket& data) @@ -429,10 +429,6 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ uint8 teamIndex = GetTeamIndexByTeamId(source->GetTeam()); - // Message to chatlog - char buf[256]; - uint8 type = (teamIndex == 0) ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE; - // Check if player really could use this banner, not cheated if( !(m_Nodes[node] == 0 || teamIndex == m_Nodes[node]%2) ) return; @@ -451,7 +447,13 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true); _SendNodeUpdate(node); m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; - sprintf(buf, GetTrinityString(LANG_BG_AB_NODE_CLAIMED), _GetNodeName(node), (teamIndex == 0) ? GetTrinityString(LANG_BG_AB_ALLY) : GetTrinityString(LANG_BG_AB_HORDE)); + + // FIXME: team and node names not localized + if(teamIndex == 0) + SendMessage2ToAll(LANG_BG_AB_NODE_CLAIMED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node), LANG_BG_AB_ALLY); + else + SendMessage2ToAll(LANG_BG_AB_NODE_CLAIMED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node), LANG_BG_AB_HORDE); + sound = SOUND_NODE_CLAIMED; } // If node is contested @@ -469,7 +471,12 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true); _SendNodeUpdate(node); m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; - sprintf(buf, GetTrinityString(LANG_BG_AB_NODE_ASSAULTED), _GetNodeName(node)); + + // FIXME: node names not localized + if(teamIndex == 0) + SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node)); + else + SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node)); } // If contested, change back to occupied else @@ -484,7 +491,12 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ _SendNodeUpdate(node); m_NodeTimers[node] = 0; _NodeOccupied(node,(teamIndex == 0) ? ALLIANCE:HORDE); - sprintf(buf, GetTrinityString(LANG_BG_AB_NODE_DEFENDED), _GetNodeName(node)); + + // FIXME: node names not localized + if(teamIndex == 0) + SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node)); + else + SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node)); } sound = (teamIndex == 0) ? SOUND_NODE_ASSAULTED_ALLIANCE : SOUND_NODE_ASSAULTED_HORDE; } @@ -501,18 +513,24 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ _SendNodeUpdate(node); _NodeDeOccupied(node); m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; - sprintf(buf, GetTrinityString(LANG_BG_AB_NODE_ASSAULTED), _GetNodeName(node)); + + // FIXME: node names not localized + if(teamIndex == 0) + SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node)); + else + SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node)); + sound = (teamIndex == 0) ? SOUND_NODE_ASSAULTED_ALLIANCE : SOUND_NODE_ASSAULTED_HORDE; } - WorldPacket data; - ChatHandler::FillMessageData(&data, source->GetSession(), type, LANG_UNIVERSAL, NULL, source->GetGUID(), buf, NULL); - SendPacketToAll(&data); + // If node is occupied again, send "X has taken the Y" msg. if( m_Nodes[node] >= BG_AB_NODE_TYPE_OCCUPIED ) { - sprintf(buf, GetTrinityString(LANG_BG_AB_NODE_TAKEN), (teamIndex == 0) ? GetTrinityString(LANG_BG_AB_ALLY) : GetTrinityString(LANG_BG_AB_HORDE), _GetNodeName(node)); - ChatHandler::FillMessageData(&data, NULL, type, LANG_UNIVERSAL, NULL, 0, buf, NULL); - SendPacketToAll(&data); + // FIXME: team and node names not localized + if(teamIndex == 0) + SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE, NULL, LANG_BG_AB_ALLY, _GetNodeNameId(node)); + else + SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_HORDE, NULL, LANG_BG_AB_HORDE, _GetNodeNameId(node)); } PlaySoundToAll(sound); } @@ -569,6 +587,10 @@ void BattleGroundAB::Reset() m_ReputationScoreTics[BG_TEAM_ALLIANCE] = 0; m_ReputationScoreTics[BG_TEAM_HORDE] = 0; m_IsInformedNearVictory = false; + bool isBGWeekend = false; //TODO FIXME - call sBattleGroundMgr.IsBGWeekend(m_TypeID); - you must also implement that call! + m_HonorTics = (isBGWeekend) ? BG_AB_ABBGWeekendHonorTicks : BG_AB_NotABBGWeekendHonorTicks; + m_ReputationTics = (isBGWeekend) ? BG_AB_ABBGWeekendReputationTicks : BG_AB_NotABBGWeekendReputationTicks; + for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) { m_Nodes[i] = 0; @@ -582,6 +604,20 @@ void BattleGroundAB::Reset() DelCreature(i); } +void BattleGroundAB::EndBattleGround(uint32 winner) +{ + //win reward + if( winner == ALLIANCE ) + RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE); + if( winner == HORDE ) + RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE); + //complete map_end rewards (even if no team wins) + RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE); + RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE); + + BattleGround::EndBattleGround(winner); +} + WorldSafeLocsEntry const* BattleGroundAB::GetClosestGraveYard(Player* player) { uint8 teamIndex = GetTeamIndexByTeamId(player->GetTeam()); diff --git a/src/game/BattleGroundAB.h b/src/game/BattleGroundAB.h index 65ee073c9ae..00328949bc5 100644 --- a/src/game/BattleGroundAB.h +++ b/src/game/BattleGroundAB.h @@ -172,6 +172,11 @@ enum BG_AB_Sounds SOUND_NEAR_VICTORY = 8456 }; +#define BG_AB_NotABBGWeekendHonorTicks 330 +#define BG_AB_ABBGWeekendHonorTicks 200 +#define BG_AB_NotABBGWeekendReputationTicks 200 +#define BG_AB_ABBGWeekendReputationTicks 150 + // x, y, z, o const float BG_AB_NodePositions[BG_AB_DYNAMIC_NODES_COUNT][4] = { {1166.785f, 1200.132f, -56.70859f, 0.9075713f}, // stables @@ -246,6 +251,7 @@ class BattleGroundAB : public BattleGround void HandleAreaTrigger(Player *Source, uint32 Trigger); virtual bool SetupBattleGround(); virtual void Reset(); + void EndBattleGround(uint32 winner); virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); /* Scorekeeping */ @@ -267,7 +273,7 @@ class BattleGroundAB : public BattleGround void _NodeOccupied(uint8 node,Team team); void _NodeDeOccupied(uint8 node); - const char* _GetNodeName(uint8 node); + int32 _GetNodeNameId(uint8 node); /* Nodes info: 0: neutral @@ -275,15 +281,19 @@ class BattleGroundAB : public BattleGround 2: horde contested 3: ally occupied 4: horde occupied */ - uint8 m_Nodes[BG_AB_DYNAMIC_NODES_COUNT]; - uint8 m_prevNodes[BG_AB_DYNAMIC_NODES_COUNT]; - BG_AB_BannerTimer m_BannerTimers[BG_AB_DYNAMIC_NODES_COUNT]; - int32 m_NodeTimers[BG_AB_DYNAMIC_NODES_COUNT]; - uint32 m_TeamScores[2]; - uint32 m_lastTick[2]; - uint32 m_HonorScoreTics[2]; - uint32 m_ReputationScoreTics[2]; - bool m_IsInformedNearVictory; + uint8 m_Nodes[BG_AB_DYNAMIC_NODES_COUNT]; + uint8 m_prevNodes[BG_AB_DYNAMIC_NODES_COUNT]; + BG_AB_BannerTimer m_BannerTimers[BG_AB_DYNAMIC_NODES_COUNT]; + int32 m_NodeTimers[BG_AB_DYNAMIC_NODES_COUNT]; + uint32 m_TeamScores[2]; + uint32 m_lastTick[2]; + uint32 m_HonorScoreTics[2]; + uint32 m_ReputationScoreTics[2]; + bool m_IsInformedNearVictory; + uint32 m_HonorTics; + uint32 m_ReputationTics; + + }; #endif diff --git a/src/game/BattleGroundAV.cpp b/src/game/BattleGroundAV.cpp index f02dc3b2e90..6320623f453 100644 --- a/src/game/BattleGroundAV.cpp +++ b/src/game/BattleGroundAV.cpp @@ -241,7 +241,7 @@ void BattleGroundAV::UpdateScore(uint16 team, int16 points ) } else if(!m_IsInformedNearVictory[teamindex] && m_Team_Scores[teamindex] < SEND_MSG_NEAR_LOSE) { - SendMessageToAll(GetTrinityString((teamindex==BG_TEAM_HORDE)?LANG_BG_AV_H_NEAR_LOSE:LANG_BG_AV_A_NEAR_LOSE), teamindex==BG_TEAM_HORDE ? CHAT_MSG_BG_SYSTEM_HORDE : CHAT_MSG_BG_SYSTEM_ALLIANCE); + SendMessageToAll(teamindex==BG_TEAM_HORDE?LANG_BG_AV_H_NEAR_LOSE:LANG_BG_AV_A_NEAR_LOSE, teamindex==BG_TEAM_HORDE ? CHAT_MSG_BG_SYSTEM_HORDE : CHAT_MSG_BG_SYSTEM_ALLIANCE); PlaySoundToAll(AV_SOUND_NEAR_VICTORY); m_IsInformedNearVictory[teamindex] = true; } @@ -374,13 +374,13 @@ void BattleGroundAV::Update(uint32 diff) else if (GetStartDelayTime() <= BG_START_DELAY_1M && !(m_Events & 0x04)) { m_Events |= 0x04; - SendMessageToAll(GetTrinityString(LANG_BG_AV_ONEMINTOSTART), CHAT_MSG_BG_SYSTEM_NEUTRAL); + SendMessageToAll(LANG_BG_AV_ONEMINTOSTART, CHAT_MSG_BG_SYSTEM_NEUTRAL); } // After 1,5 minute, warning is signalled else if (GetStartDelayTime() <= BG_START_DELAY_1M + BG_START_DELAY_30S && !(m_Events & 0x08)) { m_Events |= 0x08; - SendMessageToAll(GetTrinityString(LANG_BG_AV_HALFMINTOSTART), CHAT_MSG_BG_SYSTEM_NEUTRAL); + SendMessageToAll(LANG_BG_AV_HALFMINTOSTART, CHAT_MSG_BG_SYSTEM_NEUTRAL); } // After 2 minutes, gates OPEN ! x) else if (GetStartDelayTime() <= 0 && !(m_Events & 0x10)) @@ -389,7 +389,7 @@ void BattleGroundAV::Update(uint32 diff) UpdateWorldState(AV_SHOW_A_SCORE, 1); m_Events |= 0x10; - SendMessageToAll(GetTrinityString(LANG_BG_AV_STARTED), CHAT_MSG_BG_SYSTEM_NEUTRAL); + SendMessageToAll(LANG_BG_AV_STARTED, CHAT_MSG_BG_SYSTEM_NEUTRAL); PlaySoundToAll(SOUND_BG_START); SetStatus(STATUS_IN_PROGRESS); diff --git a/src/game/BattleGroundBE.cpp b/src/game/BattleGroundBE.cpp index 9e976ac7330..f417c353c1c 100644 --- a/src/game/BattleGroundBE.cpp +++ b/src/game/BattleGroundBE.cpp @@ -94,10 +94,7 @@ void BattleGroundBE::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE)); UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE)); - if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) - EndBattleGround(HORDE); - else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE)) - EndBattleGround(ALLIANCE); + CheckArenaWinConditions(); } void BattleGroundBE::HandleKillPlayer(Player *player, Player *killer) @@ -116,16 +113,7 @@ void BattleGroundBE::HandleKillPlayer(Player *player, Player *killer) UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE)); UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE)); - if(!GetAlivePlayersCountByTeam(ALLIANCE)) - { - // all opponents killed - EndBattleGround(HORDE); - } - else if(!GetAlivePlayersCountByTeam(HORDE)) - { - // all opponents killed - EndBattleGround(ALLIANCE); - } + CheckArenaWinConditions(); } bool BattleGroundBE::HandlePlayerUnderMap(Player *player) diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp index 6d92b086720..55e5d002a91 100644 --- a/src/game/BattleGroundEY.cpp +++ b/src/game/BattleGroundEY.cpp @@ -23,7 +23,6 @@ #include "BattleGround.h" #include "BattleGroundEY.h" #include "Creature.h" -#include "Chat.h" #include "ObjectMgr.h" #include "Language.h" #include "World.h" //music @@ -131,10 +130,10 @@ void BattleGroundEY::AddPoints(uint32 Team, uint32 Points) uint8 team_index = GetTeamIndexByTeamId(Team); m_TeamScores[team_index] += Points; m_HonorScoreTics[team_index] += Points; - if (m_HonorScoreTics[team_index] >= BG_EY_HonorScoreTicks[m_HonorMode]) + if (m_HonorScoreTics[team_index] >= m_HonorTics ) { - RewardHonorToTeam(20, Team); - m_HonorScoreTics[team_index] -= BG_EY_HonorScoreTicks[m_HonorMode]; + RewardHonorToTeam(GetBonusHonorFromKill(1), Team); + m_HonorScoreTics[team_index] -= m_HonorTics; } UpdateTeamScore(Team); } @@ -157,7 +156,7 @@ void BattleGroundEY::CheckSomeoneJoinedPoint() ++j; continue; } - if (plr->isAllowUseBattleGroundObject() && plr->IsWithinDistInMap(obj, BG_EY_POINT_RADIUS)) + if (plr->CanCaptureTowerPoint() && plr->IsWithinDistInMap(obj, BG_EY_POINT_RADIUS)) { //player joined point! //show progress bar @@ -200,7 +199,7 @@ void BattleGroundEY::CheckSomeoneLeftPoint() ++j; continue; } - if (!plr->isAllowUseBattleGroundObject() || !plr->IsWithinDistInMap(obj, BG_EY_POINT_RADIUS)) + if (!plr->CanCaptureTowerPoint() || !plr->IsWithinDistInMap(obj, BG_EY_POINT_RADIUS)) //move player out of point (add him to players that are out of points { m_PlayersNearPoint[EY_POINTS_MAX].push_back(m_PlayersNearPoint[i][j]); @@ -280,6 +279,20 @@ void BattleGroundEY::UpdateTeamScore(uint32 Team) UpdateWorldState(EY_HORDE_RESOURCES, score); } +void BattleGroundEY::EndBattleGround(uint32 winner) +{ + //win reward + if( winner == ALLIANCE ) + RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE); + if( winner == HORDE ) + RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE); + //complete map reward + RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE); + RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE); + + BattleGround::EndBattleGround(winner); +} + void BattleGroundEY::UpdatePointsCount(uint32 Team) { if(Team == ALLIANCE) @@ -504,6 +517,8 @@ void BattleGroundEY::Reset() m_DroppedFlagGUID = 0; m_PointAddingTimer = 0; m_TowerCapCheckTimer = 0; + bool isBGWeekend = false; //TODO FIXME - call sBattleGroundMgr.IsBGWeekend(m_TypeID); - you must also implement that call! + uint32 m_HonorTics = (isBGWeekend) ? BG_EY_EYWeekendHonorTicks : BG_EY_NotEYWeekendHonorTicks; for(uint8 i = 0; i < EY_POINTS_MAX; ++i) { @@ -528,7 +543,7 @@ void BattleGroundEY::RespawnFlag(bool send_message) if(send_message) { - SendMessageToAll(GetMangosString(LANG_BG_EY_RESETED_FLAG), CHAT_MSG_BG_SYSTEM_NEUTRAL); + SendMessageToAll(LANG_BG_EY_RESETED_FLAG, CHAT_MSG_BG_SYSTEM_NEUTRAL); PlaySoundToAll(BG_EY_SOUND_FLAG_RESET); // flags respawned sound... } @@ -577,32 +592,20 @@ void BattleGroundEY::EventPlayerDroppedFlag(Player *Source) if(GetFlagPickerGUID() != Source->GetGUID()) return; - const char *message = ""; - uint8 type = 0; - SetFlagPicker(0); Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL); m_FlagState = BG_EY_FLAG_STATE_ON_GROUND; m_FlagsTimer = BG_EY_FLAG_RESPAWN_TIME; Source->CastSpell(Source, SPELL_RECENTLY_DROPPED_FLAG, true); Source->CastSpell(Source, BG_EY_PLAYER_DROPPED_FLAG_SPELL, true); - if(Source->GetTeam() == ALLIANCE) - { - message = GetTrinityString(LANG_BG_EY_DROPPED_FLAG); - type = CHAT_MSG_BG_SYSTEM_ALLIANCE; - } - else - { - message = GetTrinityString(LANG_BG_EY_DROPPED_FLAG); - type = CHAT_MSG_BG_SYSTEM_HORDE; - } //this does not work correctly :( (it should remove flag carrier name) UpdateWorldState(NETHERSTORM_FLAG_STATE_HORDE, BG_EY_FLAG_STATE_WAIT_RESPAWN); UpdateWorldState(NETHERSTORM_FLAG_STATE_ALLIANCE, BG_EY_FLAG_STATE_WAIT_RESPAWN); - WorldPacket data; - ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); - SendPacketToAll(&data); + if(Source->GetTeam() == ALLIANCE) + SendMessageToAll(LANG_BG_EY_DROPPED_FLAG,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); + else + SendMessageToAll(LANG_BG_EY_DROPPED_FLAG,CHAT_MSG_BG_SYSTEM_HORDE, Source); } void BattleGroundEY::EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj) @@ -610,20 +613,14 @@ void BattleGroundEY::EventPlayerClickedOnFlag(Player *Source, GameObject* target if(GetStatus() != STATUS_IN_PROGRESS || this->IsFlagPickedup() || !Source->IsWithinDistInMap(target_obj, 10)) return; - const char *message; - uint8 type = 0; - message = GetTrinityString(LANG_BG_EY_HAS_TAKEN_FLAG); - if(Source->GetTeam() == ALLIANCE) { UpdateWorldState(NETHERSTORM_FLAG_STATE_ALLIANCE, BG_EY_FLAG_STATE_ON_PLAYER); - type = CHAT_MSG_BG_SYSTEM_ALLIANCE; PlaySoundToAll(BG_EY_SOUND_FLAG_PICKED_UP_ALLIANCE); } else { UpdateWorldState(NETHERSTORM_FLAG_STATE_HORDE, BG_EY_FLAG_STATE_ON_PLAYER); - type = CHAT_MSG_BG_SYSTEM_HORDE; PlaySoundToAll(BG_EY_SOUND_FLAG_PICKED_UP_HORDE); } @@ -637,9 +634,10 @@ void BattleGroundEY::EventPlayerClickedOnFlag(Player *Source, GameObject* target Source->CastSpell(Source, BG_EY_NETHERSTORM_FLAG_SPELL, true); Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); - WorldPacket data; - ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); - SendPacketToAll(&data); + if(Source->GetTeam() == ALLIANCE) + SendMessageToAll(LANG_BG_EY_HAS_TAKEN_FLAG,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); + else + SendMessageToAll(LANG_BG_EY_HAS_TAKEN_FLAG,CHAT_MSG_BG_SYSTEM_HORDE, Source); } void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point) @@ -648,8 +646,6 @@ void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point) return; //Natural point - uint8 message_type = 0; - const char *message = ""; uint32 Team = m_PointOwnedByTeam[Point]; if(!Team) @@ -658,8 +654,6 @@ void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point) if (Team == ALLIANCE) { m_TeamPointsCount[BG_TEAM_ALLIANCE]--; - message_type = CHAT_MSG_BG_SYSTEM_ALLIANCE; - message = GetTrinityString(m_LoosingPointTypes[Point].MessageIdAlliance); SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance, RESPAWN_ONE_DAY); SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance + 1, RESPAWN_ONE_DAY); SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance + 2, RESPAWN_ONE_DAY); @@ -667,8 +661,6 @@ void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point) else { m_TeamPointsCount[BG_TEAM_HORDE]--; - message_type = CHAT_MSG_BG_SYSTEM_HORDE; - message = GetTrinityString(m_LoosingPointTypes[Point].MessageIdHorde); SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde, RESPAWN_ONE_DAY); SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde + 1, RESPAWN_ONE_DAY); SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde + 2, RESPAWN_ONE_DAY); @@ -683,9 +675,10 @@ void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point) m_PointOwnedByTeam[Point] = EY_POINT_NO_OWNER; m_PointState[Point] = EY_POINT_NO_OWNER; - WorldPacket data; - ChatHandler::FillMessageData(&data, Source->GetSession(), message_type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); - SendPacketToAll(&data); + if (Team == ALLIANCE) + SendMessageToAll(m_LoosingPointTypes[Point].MessageIdAlliance,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); + else + SendMessageToAll(m_LoosingPointTypes[Point].MessageIdHorde,CHAT_MSG_BG_SYSTEM_HORDE, Source); UpdatePointsIcons(Team, Point); UpdatePointsCount(Team); @@ -696,8 +689,6 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point) if(GetStatus() != STATUS_IN_PROGRESS) return; - uint8 type = 0; - const char *message = ""; uint32 Team = Source->GetTeam(); SpawnBGObject(m_CapturingPointTypes[Point].DespawnNeutralObjectType, RESPAWN_ONE_DAY); @@ -707,8 +698,6 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point) if (Team == ALLIANCE) { m_TeamPointsCount[BG_TEAM_ALLIANCE]++; - type = CHAT_MSG_BG_SYSTEM_ALLIANCE; - message = GetTrinityString(m_CapturingPointTypes[Point].MessageIdAlliance); SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance, RESPAWN_IMMEDIATELY); SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance + 1, RESPAWN_IMMEDIATELY); SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance + 2, RESPAWN_IMMEDIATELY); @@ -716,8 +705,6 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point) else { m_TeamPointsCount[BG_TEAM_HORDE]++; - type = CHAT_MSG_BG_SYSTEM_HORDE; - message = GetTrinityString(m_CapturingPointTypes[Point].MessageIdHorde); SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde, RESPAWN_IMMEDIATELY); SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde + 1, RESPAWN_IMMEDIATELY); SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde + 2, RESPAWN_IMMEDIATELY); @@ -728,9 +715,10 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point) m_PointOwnedByTeam[Point] = Team; m_PointState[Point] = EY_POINT_UNDER_CONTROL; - WorldPacket data; - ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); - SendPacketToAll(&data); + if (Team == ALLIANCE) + SendMessageToAll(m_CapturingPointTypes[Point].MessageIdAlliance,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); + else + SendMessageToAll(m_CapturingPointTypes[Point].MessageIdHorde,CHAT_MSG_BG_SYSTEM_HORDE, Source); if(m_BgCreatures[Point]) DelCreature(Point); @@ -752,38 +740,33 @@ void BattleGroundEY::EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType if(GetStatus() != STATUS_IN_PROGRESS || this->GetFlagPickerGUID() != Source->GetGUID()) return; - uint8 type = 0; - uint8 team_id = 0; - const char *message = ""; - SetFlagPicker(0); m_FlagState = BG_EY_FLAG_STATE_WAIT_RESPAWN; Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL); Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + if(Source->GetTeam() == ALLIANCE) - { PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_ALLIANCE); - team_id = BG_TEAM_ALLIANCE; - message = GetTrinityString(LANG_BG_EY_CAPTURED_FLAG_A); - type = CHAT_MSG_BG_SYSTEM_ALLIANCE; - } else - { PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_HORDE); - team_id = BG_TEAM_HORDE; - message = GetTrinityString(LANG_BG_EY_CAPTURED_FLAG_H); - type = CHAT_MSG_BG_SYSTEM_HORDE; - } SpawnBGObject(BgObjectType, RESPAWN_IMMEDIATELY); m_FlagsTimer = BG_EY_FLAG_RESPAWN_TIME; m_FlagCapturedBgObjectType = BgObjectType; - WorldPacket data; - ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); - SendPacketToAll(&data); + uint8 team_id = 0; + if(Source->GetTeam() == ALLIANCE) + { + team_id = BG_TEAM_ALLIANCE; + SendMessageToAll(LANG_BG_EY_CAPTURED_FLAG_A, CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); + } + else + { + team_id = BG_TEAM_HORDE; + SendMessageToAll(LANG_BG_EY_CAPTURED_FLAG_H, CHAT_MSG_BG_SYSTEM_HORDE, Source); + } if(m_TeamPointsCount[team_id] > 0) AddPoints(Source->GetTeam(), BG_EY_FlagPoints[m_TeamPointsCount[team_id] - 1]); diff --git a/src/game/BattleGroundEY.h b/src/game/BattleGroundEY.h index 1eb79d7b9fd..ffefe543060 100644 --- a/src/game/BattleGroundEY.h +++ b/src/game/BattleGroundEY.h @@ -212,6 +212,9 @@ enum EYBattleGroundObjectTypes BG_EY_OBJECT_MAX = 59 }; +#define BG_EY_NotEYWeekendHonorTicks 330 +#define BG_EY_EYWeekendHonorTicks 200 + enum BG_EY_FlagState { BG_EY_FLAG_STATE_ON_BASE = 0, @@ -323,6 +326,7 @@ class BattleGroundEY : public BattleGround virtual bool SetupBattleGround(); virtual void Reset(); void UpdateTeamScore(uint32 Team); + void EndBattleGround(uint32 winner); void UpdatePlayerScore(Player *Source, uint32 type, uint32 value); virtual void FillInitialWorldStates(WorldPacket& data); void SetDroppedFlagGUID(uint64 guid) { m_DroppedFlagGUID = guid;} @@ -372,6 +376,7 @@ class BattleGroundEY : public BattleGround uint8 m_CurrentPointPlayersCount[2*EY_POINTS_MAX]; int32 m_PointAddingTimer; + uint32 m_HonorTics; }; #endif diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index ba687f52662..c28d712f436 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -174,7 +174,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) WorldPacket data; // send status packet (in queue) - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, 0, 0); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); @@ -195,7 +195,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) WorldPacket data; // send status packet (in queue) - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, 0, 0); SendPacket(&data); GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, false, 0); @@ -360,7 +360,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) // re - invite player with proper data WorldPacket data; - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, itrPlayerStatus->second.GroupInfo->Team?itrPlayerStatus->second.GroupInfo->Team:_player->GetTeam(), i, status, INVITE_ACCEPT_WAIT_TIME, 0, arenatype, israted); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, status, INVITE_ACCEPT_WAIT_TIME, 0, arenatype); SendPacket(&data); } } @@ -427,6 +427,12 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) sLog.outError("Battleground: Invalid player queue info!"); return; } + //if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue + if( arenatype == 0 && !_player->CanJoinToBattleground() ) + { + sLog.outDebug("Battleground: player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName(), _player->GetGUIDLow()); + action = 0; + } WorldPacket data; switch(action) { @@ -447,7 +453,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) } _player->RemoveFromGroup(); queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); _player->GetSession()->SendPacket(&data); // remove battleground queue status from BGmgr sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), false); @@ -482,7 +488,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) } } _player->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_NONE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), true); // player left queue, we should update it, maybe now his group fits in sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId,_player->GetBattleGroundQueueIdFromLevel(bgTypeId),arenatype,israted,rating); @@ -537,7 +543,7 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId_tmp); if((bg->GetStatus() <= STATUS_IN_PROGRESS)) { - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); SendPacket(&data); } for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) @@ -562,7 +568,7 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) { //in this call is small bug, this call should be filled by player's waiting time in queue //this call nulls all timers for client : - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0,arenatype,isRated); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, i, STATUS_WAIT_QUEUE, 0, 0,arenatype); SendPacket(&data); } } @@ -591,19 +597,11 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) } if(bg) { - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, 0, 0, arenatype); SendPacket(&data); } } } -/* else // not sure if it needed... - { - for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) - { - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, NULL, _player->GetTeam(),i , STATUS_NONE, 0, 0); - SendPacket(&data); - } - }*/ } void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket & recv_data ) @@ -784,7 +782,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) WorldPacket data; // send status packet (in queue) - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); @@ -805,7 +803,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) WorldPacket data; // send status packet (in queue) - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype); SendPacket(&data); GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 9ee9c841de3..8bcc2a28fcf 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -236,7 +236,7 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou } sLog.outDebug("BattleGroundQueue: Removing player GUID %u, from queue_id %u", GUID_LOPART(guid), (uint32)queue_id); - // ALL variables are corrcetly set + // ALL variables are correctly set // We can ignore leveling up in queue - it should not cause crash // remove player from group // if only one player there, remove group @@ -261,6 +261,22 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou if( (decreaseInvitedCount && !group->ArenaType) || (group->ArenaType && group->IsRated && group->Players.empty()) ) AnnounceWorld(group, guid, false); + //if player leaves queue and he is invited to rated arena match, then he have to loose + if( group->IsInvitedToBGInstanceGUID && group->IsRated && decreaseInvitedCount ) + { + ArenaTeam * at = objmgr.GetArenaTeamById(group->ArenaTeamId); + if( at ) + { + sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u", GUID_LOPART(guid), group->OpponentsTeamRating); + Player *plr = objmgr.GetPlayer(guid); + if( plr ) + at->MemberLost(plr, group->OpponentsTeamRating); + else + at->OfflineMemberLost(guid, group->OpponentsTeamRating); + at->SaveToDB(); + } + } + // remove group queue info if needed if( group->Players.empty() ) { @@ -282,7 +298,7 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou plr2->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to // queue->removeplayer, it causes bugs WorldPacket data; - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr2->GetTeam(), queueSlot, STATUS_NONE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0); plr2->GetSession()->SendPacket(&data); } // then actually delete, this may delete the group as well! @@ -382,7 +398,7 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b sLog.outDebug("Battleground: invited plr %s (%u) to BG instance %u queueindex %u bgtype %u, I can't help it if they don't press the enter battle button.",plr->GetName(),plr->GetGUIDLow(),bg->GetInstanceID(),queueSlot,bg->GetTypeID()); // send status packet - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, side?side:plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0); plr->GetSession()->SendPacket(&data); } return true; @@ -414,7 +430,6 @@ void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg) { // after removing this much playerinfos, the ginfo will be deleted, so we'll use a for loop uint32 to_remove = ginfo->Players.size(); - uint32 team = ginfo->Team; for(uint32 j = 0; j < to_remove; j++) { // always remove the first one in the group @@ -440,7 +455,7 @@ void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg) // remove player from queue, this might delete the ginfo as well! don't use that pointer after this! RemovePlayer(itr2->first, true); WorldPacket data; - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, team, queueSlot, STATUS_NONE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0); plr->GetSession()->SendPacket(&data); } } @@ -999,7 +1014,7 @@ bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) if (qItr != qpMap.end() && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID) { WorldPacket data; - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, qItr->second.GroupInfo->Team, queueSlot, STATUS_WAIT_JOIN, INVITATION_REMIND_TIME, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITATION_REMIND_TIME, 0); plr->GetSession()->SendPacket(&data); } } @@ -1034,21 +1049,11 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) BattleGroundQueue::QueuedPlayersMap::iterator qMapItr = qpMap.find(m_PlayerGuid); if (qMapItr != qpMap.end() && qMapItr->second.GroupInfo && qMapItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID) { - if (qMapItr->second.GroupInfo->IsRated) - { - ArenaTeam * at = objmgr.GetArenaTeamById(qMapItr->second.GroupInfo->ArenaTeamId); - if (at) - { - sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u", GUID_LOPART(plr->GetGUID()), qMapItr->second.GroupInfo->OpponentsTeamRating); - at->MemberLost(plr, qMapItr->second.GroupInfo->OpponentsTeamRating); - at->SaveToDB(); - } - } plr->RemoveBattleGroundQueueId(bgQueueTypeId); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(m_PlayerGuid, true); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bg->GetTypeID(), bg->GetQueueId()); WorldPacket data; - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, m_PlayersTeam, queueSlot, STATUS_NONE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0); plr->GetSession()->SendPacket(&data); } } @@ -1079,10 +1084,10 @@ BattleGroundMgr::BattleGroundMgr() : m_AutoDistributionTimeChecker(0), m_ArenaTe BattleGroundMgr::~BattleGroundMgr() { - DeleteAlllBattleGrounds(); + DeleteAllBattleGrounds(); } -void BattleGroundMgr::DeleteAlllBattleGrounds() +void BattleGroundMgr::DeleteAllBattleGrounds() { for(uint32 i = BATTLEGROUND_TYPE_NONE; i < MAX_BATTLEGROUND_TYPE_ID; i++) { @@ -1164,7 +1169,7 @@ void BattleGroundMgr::Update(uint32 diff) } } -void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype, uint8 israted) +void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype) { // we can be in 3 queues in same time... if(StatusID == 0) @@ -1181,7 +1186,8 @@ void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGro *data << uint64( uint64(arenatype ? arenatype : bg->GetArenaType()) | (uint64(0x0D) << 8) | (uint64(bg->GetTypeID()) << 16) | (uint64(0x1F90) << 48) ); *data << uint32(0); // unknown // alliance/horde for BG and skirmish/rated for Arenas - *data << uint8(bg->isArena() ? ( israted ? israted : bg->isRated() ) : bg->GetTeamIndexByTeamId(team)); + // following displays the minimap-icon 0 = faction icon 1 = arenaicon + *data << uint8(bg->isArena()); /* *data << uint8(arenatype ? arenatype : bg->GetArenaType()); // team type (0=BG, 2=2x2, 3=3x3, 5=5x5), for arenas // NOT PROPER VALUE IF ARENA ISN'T RUNNING YET!!!! switch(bg->GetTypeID()) // value depends on bg id { @@ -1231,10 +1237,7 @@ void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGro *data << uint16(0x1F90); // unk value 8080 *data << uint32(bg->GetInstanceID()); // instance id - if(bg->isBattleGround()) - *data << uint8(bg->GetTeamIndexByTeamId(team)); // team - else - *data << uint8(israted?israted:bg->isRated()); // is rated battle + *data << uint8(bg->isArena()); // minimap-icon 0=faction 1=arena */ *data << uint32(StatusID); // status switch(StatusID) @@ -1390,10 +1393,10 @@ void BattleGroundMgr::BuildPlaySoundPacket(WorldPacket *data, uint32 soundid) *data << uint32(soundid); } -void BattleGroundMgr::BuildPlayerLeftBattleGroundPacket(WorldPacket *data, Player *plr) +void BattleGroundMgr::BuildPlayerLeftBattleGroundPacket(WorldPacket *data, const uint64& guid) { data->Initialize(SMSG_BATTLEGROUND_PLAYER_LEFT, 8); - *data << uint64(plr->GetGUID()); + *data << uint64(guid); } void BattleGroundMgr::BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Player *plr) diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index 1bd3a7110eb..59041bd8c86 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -176,12 +176,12 @@ class BattleGroundMgr /* Packet Building */ void BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Player *plr); - void BuildPlayerLeftBattleGroundPacket(WorldPacket *data, Player *plr); + void BuildPlayerLeftBattleGroundPacket(WorldPacket *data, const uint64& guid); void BuildBattleGroundListPacket(WorldPacket *data, const uint64& guid, Player *plr, BattleGroundTypeId bgTypeId); void BuildGroupJoinedBattlegroundPacket(WorldPacket *data, BattleGroundTypeId bgTypeId); void BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value); void BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg); - void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype = 0, uint8 israted = 0); + void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype = 0); void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid); void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, const uint64& guid); @@ -201,7 +201,7 @@ class BattleGroundMgr void RemoveBattleGround(uint32 instanceID, BattleGroundTypeId bgTypeId) { m_BattleGrounds[bgTypeId].erase(instanceID); } void CreateInitialBattleGrounds(); - void DeleteAlllBattleGrounds(); + void DeleteAllBattleGrounds(); void SendToBattleGround(Player *pl, uint32 InstanceID, BattleGroundTypeId bgTypeId); diff --git a/src/game/BattleGroundNA.cpp b/src/game/BattleGroundNA.cpp index 70f44deac89..b4c1b22d2de 100644 --- a/src/game/BattleGroundNA.cpp +++ b/src/game/BattleGroundNA.cpp @@ -91,10 +91,7 @@ void BattleGroundNA::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE)); UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE)); - if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) - EndBattleGround(HORDE); - else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE)) - EndBattleGround(ALLIANCE); + CheckArenaWinConditions(); } void BattleGroundNA::HandleKillPlayer(Player *player, Player *killer) @@ -113,16 +110,7 @@ void BattleGroundNA::HandleKillPlayer(Player *player, Player *killer) UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE)); UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE)); - if(!GetAlivePlayersCountByTeam(ALLIANCE)) - { - // all opponents killed - EndBattleGround(HORDE); - } - else if(!GetAlivePlayersCountByTeam(HORDE)) - { - // all opponents killed - EndBattleGround(ALLIANCE); - } + CheckArenaWinConditions(); } bool BattleGroundNA::HandlePlayerUnderMap(Player *player) diff --git a/src/game/BattleGroundRL.cpp b/src/game/BattleGroundRL.cpp index 7ac6d4d1cd5..0e764d3f4c7 100644 --- a/src/game/BattleGroundRL.cpp +++ b/src/game/BattleGroundRL.cpp @@ -91,10 +91,7 @@ void BattleGroundRL::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE)); UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE)); - if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) - EndBattleGround(HORDE); - else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE)) - EndBattleGround(ALLIANCE); + CheckArenaWinConditions(); } void BattleGroundRL::HandleKillPlayer(Player *player, Player *killer) @@ -113,16 +110,7 @@ void BattleGroundRL::HandleKillPlayer(Player *player, Player *killer) UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE)); UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE)); - if(!GetAlivePlayersCountByTeam(ALLIANCE)) - { - // all opponents killed - EndBattleGround(HORDE); - } - else if(!GetAlivePlayersCountByTeam(HORDE)) - { - // all opponents killed - EndBattleGround(ALLIANCE); - } + CheckArenaWinConditions(); } bool BattleGroundRL::HandlePlayerUnderMap(Player *player) diff --git a/src/game/BattleGroundWS.cpp b/src/game/BattleGroundWS.cpp index 6aa16d3dff1..ecf93db7cfa 100644 --- a/src/game/BattleGroundWS.cpp +++ b/src/game/BattleGroundWS.cpp @@ -24,7 +24,6 @@ #include "BattleGroundWS.h" #include "Creature.h" #include "GameObject.h" -#include "Chat.h" #include "ObjectMgr.h" #include "WorldPacket.h" #include "Language.h" @@ -167,7 +166,7 @@ void BattleGroundWS::RespawnFlag(uint32 Team, bool captured) //when map_update will be allowed for battlegrounds this code will be useless SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY); - SendMessageToAll(GetMangosString(LANG_BG_WS_F_PLACED), CHAT_MSG_BG_SYSTEM_NEUTRAL); + SendMessageToAll(LANG_BG_WS_F_PLACED, CHAT_MSG_BG_SYSTEM_NEUTRAL); PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED); // flag respawned sound... } } @@ -181,12 +180,12 @@ void BattleGroundWS::RespawnFlagAfterDrop(uint32 team) if(team == ALLIANCE) { SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY); - SendMessageToAll(GetMangosString(LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED), CHAT_MSG_BG_SYSTEM_NEUTRAL); + SendMessageToAll(LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED, CHAT_MSG_BG_SYSTEM_NEUTRAL); } else { SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); - SendMessageToAll(GetMangosString(LANG_BG_WS_HORDE_FLAG_RESPAWNED), CHAT_MSG_BG_SYSTEM_NEUTRAL); + SendMessageToAll(LANG_BG_WS_HORDE_FLAG_RESPAWNED, CHAT_MSG_BG_SYSTEM_NEUTRAL); } PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED); @@ -205,11 +204,7 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source) if(GetStatus() != STATUS_IN_PROGRESS) return; - uint8 type = 0; uint32 winner = 0; - const char *message = ""; - - //TODO FIX reputation and honor gains for low level players! Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); if(Source->GetTeam() == ALLIANCE) @@ -221,13 +216,10 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source) m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_WAIT_RESPAWN; // Drop Horde Flag from Player Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG); - message = GetTrinityString(LANG_BG_WS_CAPTURED_HF); - type = CHAT_MSG_BG_SYSTEM_ALLIANCE; if(GetTeamScore(ALLIANCE) < BG_WS_MAX_TEAM_SCORE) AddPoint(ALLIANCE, 1); PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_ALLIANCE); - RewardReputationToTeam(890, BG_WSG_Reputation[m_HonorMode][BG_WSG_FLAG_CAP], ALLIANCE); // +35 reputation - RewardHonorToTeam(BG_WSG_Honor[m_HonorMode][BG_WSG_FLAG_CAP], ALLIANCE); // +40 bonushonor + RewardReputationToTeam(890, m_ReputationCapture, ALLIANCE); } else { @@ -238,26 +230,26 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source) m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_WAIT_RESPAWN; // Drop Alliance Flag from Player Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG); - message = GetTrinityString(LANG_BG_WS_CAPTURED_AF); - type = CHAT_MSG_BG_SYSTEM_HORDE; if(GetTeamScore(HORDE) < BG_WS_MAX_TEAM_SCORE) AddPoint(HORDE, 1); PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_HORDE); - RewardReputationToTeam(889, BG_WSG_Reputation[m_HonorMode][BG_WSG_FLAG_CAP], HORDE); // +35 reputation - RewardHonorToTeam(BG_WSG_Honor[m_HonorMode][BG_WSG_FLAG_CAP], HORDE); // +40 bonushonor + RewardReputationToTeam(889, m_ReputationCapture, HORDE); } + //for flag capture is reward 2 honorable kills + RewardHonorToTeam(GetBonusHonorFromKill(2), Source->GetTeam()); SpawnBGObject(BG_WS_OBJECT_H_FLAG, BG_WS_FLAG_RESPAWN_TIME); SpawnBGObject(BG_WS_OBJECT_A_FLAG, BG_WS_FLAG_RESPAWN_TIME); - WorldPacket data; - ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); - SendPacketToAll(&data); + if(Source->GetTeam() == ALLIANCE) + SendMessageToAll(LANG_BG_WS_CAPTURED_HF, CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); + else + SendMessageToAll(LANG_BG_WS_CAPTURED_AF, CHAT_MSG_BG_SYSTEM_HORDE, Source); UpdateFlagState(Source->GetTeam(), 1); // flag state none UpdateTeamScore(Source->GetTeam()); // only flag capture should be updated - UpdatePlayerScore(Source, SCORE_FLAG_CAPTURES, 1); // +1 flag captures... + UpdatePlayerScore(Source, SCORE_FLAG_CAPTURES, 1); // +1 flag captures if(GetTeamScore(ALLIANCE) == BG_WS_MAX_TEAM_SCORE) winner = ALLIANCE; @@ -310,8 +302,6 @@ void BattleGroundWS::EventPlayerDroppedFlag(Player *Source) return; } - const char *message = ""; - uint8 type = 0; bool set = false; if(Source->GetTeam() == ALLIANCE) @@ -323,8 +313,6 @@ void BattleGroundWS::EventPlayerDroppedFlag(Player *Source) SetHordeFlagPicker(0); Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG); m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_GROUND; - message = GetTrinityString(LANG_BG_WS_DROPPED_HF); - type = CHAT_MSG_BG_SYSTEM_HORDE; Source->CastSpell(Source, BG_WS_SPELL_WARSONG_FLAG_DROPPED, true); set = true; } @@ -338,8 +326,6 @@ void BattleGroundWS::EventPlayerDroppedFlag(Player *Source) SetAllianceFlagPicker(0); Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG); m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_GROUND; - message = GetTrinityString(LANG_BG_WS_DROPPED_AF); - type = CHAT_MSG_BG_SYSTEM_ALLIANCE; Source->CastSpell(Source, BG_WS_SPELL_SILVERWING_FLAG_DROPPED, true); set = true; } @@ -350,14 +336,16 @@ void BattleGroundWS::EventPlayerDroppedFlag(Player *Source) Source->CastSpell(Source, SPELL_RECENTLY_DROPPED_FLAG, true); UpdateFlagState(Source->GetTeam(), 1); - WorldPacket data; - ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); - SendPacketToAll(&data); - if(Source->GetTeam() == ALLIANCE) + { + SendMessageToAll(LANG_BG_WS_DROPPED_HF, CHAT_MSG_BG_SYSTEM_HORDE, Source); UpdateWorldState(BG_WS_FLAG_UNK_HORDE, uint32(-1)); + } else + { + SendMessageToAll(LANG_BG_WS_DROPPED_AF, CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, uint32(-1)); + } m_FlagsDropTimer[GetTeamIndexByTeamId(Source->GetTeam()) ? 0 : 1] = BG_WS_FLAG_DROP_TIME; } @@ -368,14 +356,14 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target if(GetStatus() != STATUS_IN_PROGRESS) return; - const char *message; - uint8 type = 0; + int32 message_id = 0; + ChatMsg type; //alliance flag picked up from base if(Source->GetTeam() == HORDE && this->GetFlagState(ALLIANCE) == BG_WS_FLAG_STATE_ON_BASE && this->m_BgObjects[BG_WS_OBJECT_A_FLAG] == target_obj->GetGUID()) { - message = GetTrinityString(LANG_BG_WS_PICKEDUP_AF); + message_id = LANG_BG_WS_PICKEDUP_AF; type = CHAT_MSG_BG_SYSTEM_HORDE; PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP); SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_ONE_DAY); @@ -391,7 +379,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target if (Source->GetTeam() == ALLIANCE && this->GetFlagState(HORDE) == BG_WS_FLAG_STATE_ON_BASE && this->m_BgObjects[BG_WS_OBJECT_H_FLAG] == target_obj->GetGUID()) { - message = GetTrinityString(LANG_BG_WS_PICKEDUP_HF); + message_id = LANG_BG_WS_PICKEDUP_HF; type = CHAT_MSG_BG_SYSTEM_ALLIANCE; PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP); SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_ONE_DAY); @@ -408,7 +396,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target { if(Source->GetTeam() == ALLIANCE) { - message = GetTrinityString(LANG_BG_WS_RETURNED_AF); + message_id = LANG_BG_WS_RETURNED_AF; type = CHAT_MSG_BG_SYSTEM_ALLIANCE; UpdateFlagState(HORDE, BG_WS_FLAG_STATE_WAIT_RESPAWN); RespawnFlag(ALLIANCE, false); @@ -418,7 +406,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target } else { - message = GetTrinityString(LANG_BG_WS_PICKEDUP_AF); + message_id = LANG_BG_WS_PICKEDUP_AF; type = CHAT_MSG_BG_SYSTEM_HORDE; PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP); SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_ONE_DAY); @@ -437,7 +425,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target { if(Source->GetTeam() == HORDE) { - message = GetTrinityString(LANG_BG_WS_RETURNED_HF); + message_id = LANG_BG_WS_RETURNED_HF; type = CHAT_MSG_BG_SYSTEM_HORDE; UpdateFlagState(ALLIANCE, BG_WS_FLAG_STATE_WAIT_RESPAWN); RespawnFlag(HORDE, false); @@ -447,7 +435,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target } else { - message = GetTrinityString(LANG_BG_WS_PICKEDUP_HF); + message_id = LANG_BG_WS_PICKEDUP_HF; type = CHAT_MSG_BG_SYSTEM_ALLIANCE; PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP); SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_ONE_DAY); @@ -461,12 +449,10 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target //target_obj->Delete(); } - if (!type) + if (!message_id) return; - WorldPacket data; - ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL); - SendPacketToAll(&data); + SendMessageToAll(message_id, type, Source); Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); } @@ -628,16 +614,33 @@ void BattleGroundWS::Reset() m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE; m_TeamScores[BG_TEAM_ALLIANCE] = 0; m_TeamScores[BG_TEAM_HORDE] = 0; + bool isBGWeekend = false; //TODO FIXME - call sBattleGroundMgr.IsBGWeekend(m_TypeID); - you must also implement that call! + m_ReputationCapture = (isBGWeekend) ? 45 : 35; + m_HonorWinKills = (isBGWeekend) ? 3 : 1; + m_HonorEndKills = (isBGWeekend) ? 4 : 2; /* Spirit nodes is static at this BG and then not required deleting at BG reset. if(m_BgCreatures[WS_SPIRIT_MAIN_ALLIANCE]) DelCreature(WS_SPIRIT_MAIN_ALLIANCE); - if(m_BgCreatures[WS_SPIRIT_MAIN_HORDE]) DelCreature(WS_SPIRIT_MAIN_HORDE); */ } +void BattleGroundWS::EndBattleGround(uint32 winner) +{ + //win reward + if( winner == ALLIANCE ) + RewardHonorToTeam(GetBonusHonorFromKill(m_HonorWinKills), ALLIANCE); + if( winner == HORDE ) + RewardHonorToTeam(GetBonusHonorFromKill(m_HonorWinKills), HORDE); + //complete map_end rewards (even if no team wins) + RewardHonorToTeam(GetBonusHonorFromKill(m_HonorEndKills), ALLIANCE); + RewardHonorToTeam(GetBonusHonorFromKill(m_HonorEndKills), HORDE); + + BattleGround::EndBattleGround(winner); +} + void BattleGroundWS::HandleKillPlayer(Player *player, Player *killer) { if(GetStatus() != STATUS_IN_PROGRESS) diff --git a/src/game/BattleGroundWS.h b/src/game/BattleGroundWS.h index f551cda1884..7c3edceddd8 100644 --- a/src/game/BattleGroundWS.h +++ b/src/game/BattleGroundWS.h @@ -179,6 +179,7 @@ class BattleGroundWS : public BattleGround void HandleKillPlayer(Player *player, Player *killer); bool SetupBattleGround(); virtual void Reset(); + void EndBattleGround(uint32 winner); virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); void UpdateFlagState(uint32 team, uint32 value); @@ -202,8 +203,9 @@ class BattleGroundWS : public BattleGround int32 m_FlagsTimer[2]; int32 m_FlagsDropTimer[2]; - int32 m_FlagSpellForceTimer; - int32 m_FlagSpellBrutalTimer; + uint32 m_ReputationCapture; + uint32 m_HonorWinKills; + uint32 m_HonorEndKills; }; #endif diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 5f8556fbdb0..ffff83c98c8 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -448,26 +448,25 @@ ChatCommand * ChatHandler::getCommandTable() static ChatCommand npcCommandTable[] = { - { "say", SEC_MODERATOR, false, &ChatHandler::HandleNpcSayCommand, "", NULL }, - { "textemote", SEC_MODERATOR, false, &ChatHandler::HandleNpcTextEmoteCommand, "", NULL }, { "add", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddCommand, "", NULL }, + { "additem", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddVendorItemCommand, "", NULL }, + { "addmove", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddMoveCommand, "", NULL }, + { "changeentry", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcChangeEntryCommand, "", NULL }, + { "changelevel", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcChangeLevelCommand, "", NULL }, { "delete", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcDeleteCommand, "", NULL }, - { "spawndist", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSpawnDistCommand, "", NULL }, - { "spawntime", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSpawnTimeCommand, "", NULL }, { "factionid", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFactionIdCommand, "", NULL }, - { "addmove", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddMoveCommand, "", NULL }, - { "setmovetype", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetMoveTypeCommand, "", NULL }, - { "move", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcMoveCommand, "", NULL }, - { "changelevel", SEC_GAMEMASTER, false, &ChatHandler::HandleChangeLevelCommand, "", NULL }, - { "setmodel", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetModelCommand, "", NULL }, - { "additem", SEC_GAMEMASTER, false, &ChatHandler::HandleAddVendorItemCommand, "", NULL }, - { "delitem", SEC_GAMEMASTER, false, &ChatHandler::HandleDelVendorItemCommand, "", NULL }, { "flag", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFlagCommand, "", NULL }, - { "changeentry", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcChangeEntryCommand, "", NULL }, + { "follow", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFollowCommand, "", NULL }, { "info", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcInfoCommand, "", NULL }, + { "move", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcMoveCommand, "", NULL }, { "playemote", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcPlayEmoteCommand, "", NULL }, - { "follow", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFollowCommand, "", NULL }, + { "setmodel", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetModelCommand, "", NULL }, + { "setmovetype", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetMoveTypeCommand, "", NULL }, { "setphase", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetPhaseCommand, "", NULL }, + { "spawndist", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSpawnDistCommand, "", NULL }, + { "spawntime", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSpawnTimeCommand, "", NULL }, + { "say", SEC_MODERATOR, false, &ChatHandler::HandleNpcSayCommand, "", NULL }, + { "textemote", SEC_MODERATOR, false, &ChatHandler::HandleNpcTextEmoteCommand, "", NULL }, { "unfollow", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcUnFollowCommand, "", NULL }, { "whisper", SEC_MODERATOR, false, &ChatHandler::HandleNpcWhisperCommand, "", NULL }, { "yell", SEC_MODERATOR, false, &ChatHandler::HandleNpcYellCommand, "", NULL }, @@ -477,9 +476,9 @@ ChatCommand * ChatHandler::getCommandTable() { "setdeathstate", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetDeathStateCommand, "", NULL }, //{ TODO: fix or remove this commands - { "name", SEC_GAMEMASTER, false, &ChatHandler::HandleNameCommand, "", NULL }, - { "subname", SEC_GAMEMASTER, false, &ChatHandler::HandleSubNameCommand, "", NULL }, - { "addweapon", SEC_ADMINISTRATOR, false, &ChatHandler::HandleAddWeaponCommand, "", NULL }, + { "addweapon", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcAddWeaponCommand, "", NULL }, + { "name", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcNameCommand, "", NULL }, + { "subname", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSubNameCommand, "", NULL }, //} { NULL, 0, false, NULL, "", NULL } diff --git a/src/game/Chat.h b/src/game/Chat.h index 1cc6d140025..abae5c132af 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -186,10 +186,14 @@ class ChatHandler bool HandleModifyPhaseCommand(const char* args); bool HandleModifyGenderCommand(const char* args); + //-----------------------Npc Commands----------------------- bool HandleNpcAddCommand(const char* args); bool HandleNpcAddMoveCommand(const char* args); + bool HandleNpcAddVendorItemCommand(const char* args); bool HandleNpcChangeEntryCommand(const char *args); + bool HandleNpcChangeLevelCommand(const char* args); bool HandleNpcDeleteCommand(const char* args); + bool HandleNpcDelVendorItemCommand(const char* args); bool HandleNpcFactionIdCommand(const char* args); bool HandleNpcFlagCommand(const char* args); bool HandleNpcFollowCommand(const char* args); @@ -197,6 +201,7 @@ class ChatHandler bool HandleNpcMoveCommand(const char* args); bool HandleNpcPlayEmoteCommand(const char* args); bool HandleNpcSayCommand(const char* args); + bool HandleNpcSetDeathStateCommand(const char* args); bool HandleNpcSetModelCommand(const char* args); bool HandleNpcSetMoveTypeCommand(const char* args); bool HandleNpcSetPhaseCommand(const char* args); @@ -208,7 +213,12 @@ class ChatHandler bool HandleNpcWhisperCommand(const char* args); bool HandleNpcYellCommand(const char* args); bool HandleNpcAddFormationCommand(const char* args); - bool HandleNpcSetDeathStateCommand(const char* args); + + //TODO: NpcCommands that needs to be fixed : + bool HandleNpcAddWeaponCommand(const char* args); + bool HandleNpcNameCommand(const char* args); + bool HandleNpcSubNameCommand(const char* args); + //---------------------------------------------------------- bool HandleReloadAllCommand(const char* args); bool HandleReloadAllAreaCommand(const char* args); @@ -317,13 +327,8 @@ class ChatHandler bool HandleDebugSpellFailCommand(const char* args); bool HandleGUIDCommand(const char* args); - bool HandleNameCommand(const char* args); - bool HandleSubNameCommand(const char* args); bool HandleItemMoveCommand(const char* args); bool HandleDeMorphCommand(const char* args); - bool HandleAddVendorItemCommand(const char* args); - bool HandleDelVendorItemCommand(const char* args); - bool HandleChangeLevelCommand(const char* args); bool HandleSetPoiCommand(const char* args); bool HandleEquipErrorCommand(const char* args); bool HandleGoCreatureCommand(const char* args); @@ -362,7 +367,6 @@ class ChatHandler bool HandleGoXYZCommand(const char* args); bool HandleGoZoneXYCommand(const char* args); bool HandleGoGridCommand(const char* args); - bool HandleAddWeaponCommand(const char* args); bool HandleAllowMovementCommand(const char* args); bool HandleGoCommand(const char* args); diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 04950f1cab5..71f53cdabb0 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -1721,7 +1721,7 @@ SpellEntry const *Creature::reachWithSpellAttack(Unit *pVictim) SpellEntry const *spellInfo = sSpellStore.LookupEntry(m_spells[i] ); if(!spellInfo) { - sLog.outError("WORLD: unknown spell id %i\n", m_spells[i]); + sLog.outError("WORLD: unknown spell id %i", m_spells[i]); continue; } @@ -1771,7 +1771,7 @@ SpellEntry const *Creature::reachWithSpellCure(Unit *pVictim) SpellEntry const *spellInfo = sSpellStore.LookupEntry(m_spells[i] ); if(!spellInfo) { - sLog.outError("WORLD: unknown spell id %i\n", m_spells[i]); + sLog.outError("WORLD: unknown spell id %i", m_spells[i]); continue; } diff --git a/src/game/Debugcmds.cpp b/src/game/Debugcmds.cpp index 4323ef3897b..8a28ae72e00 100644 --- a/src/game/Debugcmds.cpp +++ b/src/game/Debugcmds.cpp @@ -21,6 +21,7 @@ #include "Common.h" #include "Database/DatabaseEnv.h" #include "WorldPacket.h" +#include "Vehicle.h" #include "Player.h" #include "Opcodes.h" #include "Chat.h" diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index 413cc9dda8e..8f620638b01 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -1252,7 +1252,7 @@ void GameObject::Use(Unit* user) Player* player = (Player*)user; - if( player->isAllowUseBattleGroundObject() ) + if( player->CanUseBattleGroundObject() ) { // in battleground check BattleGround *bg = player->GetBattleGround(); @@ -1277,7 +1277,7 @@ void GameObject::Use(Unit* user) Player* player = (Player*)user; - if( player->isAllowUseBattleGroundObject() ) + if( player->CanUseBattleGroundObject() ) { // in battleground check BattleGround *bg = player->GetBattleGround(); diff --git a/src/game/GridNotifiers.h b/src/game/GridNotifiers.h index bb922ce4b23..788f3361595 100644 --- a/src/game/GridNotifiers.h +++ b/src/game/GridNotifiers.h @@ -1032,6 +1032,28 @@ namespace Trinity std::vector<WorldPacket*> i_data_cache; // 0 = default, i => i-1 locale index }; + // Prepare using Builder localized packets with caching and send to player + template<class Builder> + class LocalizedPacketListDo + { + public: + typedef std::vector<WorldPacket*> WorldPacketList; + explicit LocalizedPacketListDo(Builder& builder) : i_builder(builder) {} + + ~LocalizedPacketListDo() + { + for(size_t i = 0; i < i_data_cache.size(); ++i) + for(int j = 0; j < i_data_cache[i].size(); ++j) + delete i_data_cache[i][j]; + } + void operator()( Player* p ); + + private: + Builder& i_builder; + std::vector<WorldPacketList> i_data_cache; + // 0 = default, i => i-1 locale index + }; + #ifndef WIN32 template<> inline void PlayerRelocationNotifier::Visit<Creature>(CreatureMapType &); template<> inline void PlayerRelocationNotifier::Visit<Player>(PlayerMapType &); diff --git a/src/game/GridNotifiersImpl.h b/src/game/GridNotifiersImpl.h index 6ec8c59082e..20e72047055 100644 --- a/src/game/GridNotifiersImpl.h +++ b/src/game/GridNotifiersImpl.h @@ -584,5 +584,28 @@ void MaNGOS::LocalizedPacketDo<Builder>::operator()( Player* p ) p->SendDirectMessage(data); } -#endif // TRINITY_GRIDNOTIFIERSIMPL_H +template<class Builder> +void MaNGOS::LocalizedPacketListDo<Builder>::operator()( Player* p ) +{ + uint32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex(); + uint32 cache_idx = loc_idx+1; + WorldPacketList* data_list; + + // create if not cached yet + if(i_data_cache.size() < cache_idx+1 || i_data_cache[cache_idx].empty()) + { + if(i_data_cache.size() < cache_idx+1) + i_data_cache.resize(cache_idx+1); + + data_list = &i_data_cache[cache_idx]; + + i_builder(*data_list,loc_idx); + } + else + data_list = &i_data_cache[cache_idx]; + + for(size_t i = 0; i < data_list->size(); ++i) + p->SendDirectMessage((*data_list)[i]); +} +#endif // MANGOS_GRIDNOTIFIERSIMPL_H diff --git a/src/game/Guild.cpp b/src/game/Guild.cpp index 2132a69fec1..4aa9f54f682 100644 --- a/src/game/Guild.cpp +++ b/src/game/Guild.cpp @@ -28,6 +28,7 @@ #include "Chat.h" #include "SocialMgr.h" #include "Util.h" +#include "Language.h" Guild::Guild() { @@ -51,27 +52,25 @@ Guild::~Guild() } -bool Guild::create(uint64 lGuid, std::string gname) +bool Guild::create(Player* leader, std::string gname) { - std::string rname; - std::string lName; - - if(!objmgr.GetPlayerNameByGUID(lGuid, lName)) - return false; if(objmgr.GetGuildByName(gname)) return false; - sLog.outDebug("GUILD: creating guild %s to leader: %u", gname.c_str(), GUID_LOPART(lGuid)); + WorldSession* lSession = leader->GetSession(); + if(!lSession) + return false; - leaderGuid = lGuid; + leaderGuid = leader->GetGUID(); name = gname; GINFO = ""; MOTD = "No message set."; guildbank_money = 0; purchased_tabs = 0; - Id = objmgr.GenerateGuildId(); + sLog.outDebug("GUILD: creating guild %s to leader: %u", gname.c_str(), GUID_LOPART(leaderGuid)); + // gname already assigned to Guild::name, use it to encode string for DB CharacterDatabase.escape_string(gname); @@ -89,18 +88,13 @@ bool Guild::create(uint64 lGuid, std::string gname) Id, gname.c_str(), GUID_LOPART(leaderGuid), dbGINFO.c_str(), dbMOTD.c_str(), EmblemStyle, EmblemColor, BorderStyle, BorderColor, BackgroundColor, guildbank_money); CharacterDatabase.CommitTransaction(); - rname = "Guild Master"; - CreateRank(rname,GR_RIGHT_ALL); - rname = "Officer"; - CreateRank(rname,GR_RIGHT_ALL); - rname = "Veteran"; - CreateRank(rname,GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); - rname = "Member"; - CreateRank(rname,GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); - rname = "Initiate"; - CreateRank(rname,GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); - - return AddMember(lGuid, (uint32)GR_GUILDMASTER); + CreateRank(lSession->GetMangosString(LANG_GUILD_MASTER), GR_RIGHT_ALL); + CreateRank(lSession->GetMangosString(LANG_GUILD_OFFICER), GR_RIGHT_ALL); + CreateRank(lSession->GetMangosString(LANG_GUILD_VETERAN), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); + CreateRank(lSession->GetMangosString(LANG_GUILD_MEMBER), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); + CreateRank(lSession->GetMangosString(LANG_GUILD_INITIATE),GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); + + return AddMember(leaderGuid, (uint32)GR_GUILDMASTER); } bool Guild::AddMember(uint64 plGuid, uint32 plRank) diff --git a/src/game/Guild.h b/src/game/Guild.h index fb124bbc8e4..12dea1feb1f 100644 --- a/src/game/Guild.h +++ b/src/game/Guild.h @@ -269,7 +269,7 @@ class Guild Guild(); ~Guild(); - bool create(uint64 lGuid, std::string gname); + bool create(Player* leader, std::string gname); void Disband(); typedef std::map<uint32, MemberSlot> MemberList; diff --git a/src/game/GuildHandler.cpp b/src/game/GuildHandler.cpp index 5c4c18d64d9..358d48292a3 100644 --- a/src/game/GuildHandler.cpp +++ b/src/game/GuildHandler.cpp @@ -64,7 +64,7 @@ void WorldSession::HandleGuildCreateOpcode(WorldPacket& recvPacket) return; Guild *guild = new Guild; - if(!guild->create(GetPlayer()->GetGUID(),gname)) + if(!guild->create(GetPlayer(),gname)) { delete guild; return; diff --git a/src/game/Language.h b/src/game/Language.h index 0bb9ca3318c..be303c294e4 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -710,7 +710,12 @@ enum TrinityStrings LANG_PLAYER_NOT_EXIST_OR_OFFLINE = 808, LANG_ACCOUNT_FOR_PLAYER_NOT_FOUND = 809, LANG_ACHIEVEMENT_EARNED = 810, - // Room for in-game strings 811-999 not used + LANG_GUILD_MASTER = 811, + LANG_GUILD_OFFICER = 812, + LANG_GUILD_VETERAN = 813, + LANG_GUILD_MEMBER = 814, + LANG_GUILD_INITIATE = 815, + // Room for in-game strings 816-999 not used // Level 4 (CLI only commands) LANG_COMMAND_EXIT = 1000, diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index 90b167b06f0..78e32e62574 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -40,6 +40,7 @@ #include "VMapFactory.h" #endif +//-----------------------Npc Commands----------------------- bool ChatHandler::HandleNpcSayCommand(const char* args) { if(!*args) @@ -123,6 +124,7 @@ bool ChatHandler::HandleNpcWhisperCommand(const char* args) return true; } +//---------------------------------------------------------- bool ChatHandler::HandleNameAnnounceCommand(const char* args) { diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 0dd7221403d..870256b36ca 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -733,134 +733,7 @@ bool ChatHandler::HandleModifyRepCommand(const char * args) return true; } -bool ChatHandler::HandleNameCommand(const char* /*args*/) -{ - /* Temp. disabled - if(!*args) - return false; - - if(strlen((char*)args)>75) - { - PSendSysMessage(LANG_TOO_LONG_NAME, strlen((char*)args)-75); - return true; - } - - for (uint8 i = 0; i < strlen(args); i++) - { - if(!isalpha(args[i]) && args[i]!=' ') - { - SendSysMessage(LANG_CHARS_ONLY); - return false; - } - } - - uint64 guid; - guid = m_session->GetPlayer()->GetSelection(); - if (guid == 0) - { - SendSysMessage(LANG_NO_SELECTION); - return true; - } - - Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); - - if(!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - return true; - } - - pCreature->SetName(args); - uint32 idname = objmgr.AddCreatureTemplate(pCreature->GetName()); - pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); - - pCreature->SaveToDB(); - */ - - return true; -} - -bool ChatHandler::HandleSubNameCommand(const char* /*args*/) -{ - /* Temp. disabled - - if(!*args) - args = ""; - - if(strlen((char*)args)>75) - { - - PSendSysMessage(LANG_TOO_LONG_SUBNAME, strlen((char*)args)-75); - return true; - } - - for (uint8 i = 0; i < strlen(args); i++) - { - if(!isalpha(args[i]) && args[i]!=' ') - { - SendSysMessage(LANG_CHARS_ONLY); - return false; - } - } - uint64 guid; - guid = m_session->GetPlayer()->GetSelection(); - if (guid == 0) - { - SendSysMessage(LANG_NO_SELECTION); - return true; - } - - Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); - - if(!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - return true; - } - - uint32 idname = objmgr.AddCreatureSubName(pCreature->GetName(),args,pCreature->GetUInt32Value(UNIT_FIELD_DISPLAYID)); - pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); - - pCreature->SaveToDB(); - */ - return true; -} - -//move item to other slot -bool ChatHandler::HandleItemMoveCommand(const char* args) -{ - if(!*args) - return false; - uint8 srcslot, dstslot; - - char* pParam1 = strtok((char*)args, " "); - if (!pParam1) - return false; - - char* pParam2 = strtok(NULL, " "); - if (!pParam2) - return false; - - srcslot = (uint8)atoi(pParam1); - dstslot = (uint8)atoi(pParam2); - - if(srcslot==dstslot) - return true; - - if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot)) - return false; - - if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot)) - return false; - - uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); - uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); - - m_session->GetPlayer()->SwapItem( src, dst ); - - return true; -} - +//-----------------------Npc Commands----------------------- //add spawn of creature bool ChatHandler::HandleNpcAddCommand(const char* args) { @@ -912,470 +785,334 @@ bool ChatHandler::HandleNpcAddCommand(const char* args) return true; } -bool ChatHandler::HandleNpcDeleteCommand(const char* args) +//add item in vendorlist +bool ChatHandler::HandleNpcAddVendorItemCommand(const char* args) { - Creature* unit = NULL; - - if(*args) - { - // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hcreature"); - if(!cId) - return false; - - uint32 lowguid = atoi(cId); - if(!lowguid) - return false; - - if (CreatureData const* cr_data = objmgr.GetCreatureData(lowguid)) - unit = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT)); - } - else - unit = getSelectedCreature(); + if (!*args) + return false; - if(!unit || unit->isPet() || unit->isTotem() || unit->isVehicle()) + char* pitem = extractKeyFromLink((char*)args,"Hitem"); + if (!pitem) { - SendSysMessage(LANG_SELECT_CREATURE); + SendSysMessage(LANG_COMMAND_NEEDITEMSEND); SetSentErrorMessage(true); return false; } - // Delete the creature - unit->CombatStop(); - unit->DeleteFromDB(); - unit->CleanupsBeforeDelete(); - unit->AddObjectToRemoveList(); - - SendSysMessage(LANG_COMMAND_DELCREATMESSAGE); + uint32 itemId = atol(pitem); - return true; -} + char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0 + uint32 maxcount = 0; + if (fmaxcount) + maxcount = atol(fmaxcount); -//delete object by selection or guid -bool ChatHandler::HandleDelObjectCommand(const char* args) -{ - // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hgameobject"); - if(!cId) - return false; + char* fincrtime = strtok(NULL, " "); //add incrtime, default: 0 + uint32 incrtime = 0; + if (fincrtime) + incrtime = atol(fincrtime); - uint32 lowguid = atoi(cId); - if(!lowguid) - return false; + char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0 + uint32 extendedcost = fextendedcost ? atol(fextendedcost) : 0; - GameObject* obj = NULL; + Creature* vendor = getSelectedCreature(); - // by DB guid - if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) - obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + uint32 vendor_entry = vendor ? vendor->GetEntry() : 0; - if(!obj) + if(!objmgr.IsVendorItemValid(vendor_entry,itemId,maxcount,incrtime,extendedcost,m_session->GetPlayer())) { - PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); SetSentErrorMessage(true); return false; } - uint64 owner_guid = obj->GetOwnerGUID(); - if(owner_guid) - { - Unit* owner = ObjectAccessor::GetUnit(*m_session->GetPlayer(),owner_guid); - if(!owner && !IS_PLAYER_GUID(owner_guid)) - { - PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, GUID_LOPART(owner_guid), obj->GetGUIDLow()); - SetSentErrorMessage(true); - return false; - } - - owner->RemoveGameObject(obj,false); - } - - obj->SetRespawnTime(0); // not save respawn time - obj->Delete(); - obj->DeleteFromDB(); + objmgr.AddVendorItem(vendor_entry,itemId,maxcount,incrtime,extendedcost); - PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, obj->GetGUIDLow()); + ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId); + PSendSysMessage(LANG_ITEM_ADDED_TO_LIST,itemId,pProto->Name1,maxcount,incrtime,extendedcost); return true; } -//turn selected object -bool ChatHandler::HandleTurnObjectCommand(const char* args) +//del item from vendor list +bool ChatHandler::HandleNpcDelVendorItemCommand(const char* args) { - // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hgameobject"); - if(!cId) - return false; - - uint32 lowguid = atoi(cId); - if(!lowguid) + if (!*args) return false; - GameObject* obj = NULL; - - // by DB guid - if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) - obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); - - if(!obj) + Creature* vendor = getSelectedCreature(); + if (!vendor || !vendor->isVendor()) { - PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SendSysMessage(LANG_COMMAND_VENDORSELECTION); SetSentErrorMessage(true); return false; } - char* po = strtok(NULL, " "); - float o; - - if (po) + char* pitem = extractKeyFromLink((char*)args,"Hitem"); + if (!pitem) { - o = (float)atof(po); + SendSysMessage(LANG_COMMAND_NEEDITEMSEND); + SetSentErrorMessage(true); + return false; } - else + uint32 itemId = atol(pitem); + + if(!objmgr.RemoveVendorItem(vendor->GetEntry(),itemId)) { - Player *chr = m_session->GetPlayer(); - o = chr->GetOrientation(); + PSendSysMessage(LANG_ITEM_NOT_IN_LIST,itemId); + SetSentErrorMessage(true); + return false; } - float rot2 = sin(o/2); - float rot3 = cos(o/2); - - Map* map = obj->GetMap(); - map->Remove(obj,false); - - obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o); - - obj->SetFloatValue(GAMEOBJECT_FACING, o); - obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rot2); - obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rot3); - - map->Add(obj); - - obj->SaveToDB(); - obj->Refresh(); - - PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), o); + ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId); + PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST,itemId,pProto->Name1); return true; } -//move selected creature -bool ChatHandler::HandleNpcMoveCommand(const char* args) +//add move for creature +bool ChatHandler::HandleNpcAddMoveCommand(const char* args) { - uint32 lowguid = 0; - - Creature* pCreature = getSelectedCreature(); - - if(!pCreature) - { - // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hcreature"); - if(!cId) - return false; + if(!*args) + return false; - uint32 lowguid = atoi(cId); + char* guid_str = strtok((char*)args, " "); + char* wait_str = strtok((char*)NULL, " "); - /* FIXME: impossibel without entry - if(lowguid) - pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT)); - */ + uint32 lowguid = atoi((char*)guid_str); - // Attempting creature load from DB data - if(!pCreature) - { - CreatureData const* data = objmgr.GetCreatureData(lowguid); - if(!data) - { - PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } + Creature* pCreature = NULL; - uint32 map_id = data->mapid; + /* FIXME: impossible without entry + if(lowguid) + pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT)); + */ - if(m_session->GetPlayer()->GetMapId()!=map_id) - { - PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid); - SetSentErrorMessage(true); - return false; - } - } - else + // attempt check creature existence by DB data + if(!pCreature) + { + CreatureData const* data = objmgr.GetCreatureData(lowguid); + if(!data) { - lowguid = pCreature->GetDBTableGUIDLow(); + PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; } } else { + // obtain real GUID for DB operations lowguid = pCreature->GetDBTableGUIDLow(); } - float x = m_session->GetPlayer()->GetPositionX(); - float y = m_session->GetPlayer()->GetPositionY(); - float z = m_session->GetPlayer()->GetPositionZ(); - float o = m_session->GetPlayer()->GetOrientation(); + int wait = wait_str ? atoi(wait_str) : 0; - if (pCreature) + if(wait < 0) + wait = 0; + + Player* player = m_session->GetPlayer(); + + //WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), wait, 0); + + // update movement type + WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid); + if(pCreature && pCreature->GetWaypointPath()) { - if(CreatureData const* data = objmgr.GetCreatureData(pCreature->GetDBTableGUIDLow())) - { - const_cast<CreatureData*>(data)->posX = x; - const_cast<CreatureData*>(data)->posY = y; - const_cast<CreatureData*>(data)->posZ = z; - const_cast<CreatureData*>(data)->orientation = o; - } - pCreature->GetMap()->CreatureRelocation(pCreature,x, y, z,o); + pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); pCreature->GetMotionMaster()->Initialize(); if(pCreature->isAlive()) // dead creature will reset movement generator at respawn { pCreature->setDeathState(JUST_DIED); pCreature->Respawn(); } + pCreature->SaveToDB(); } - WorldDatabase.PExecuteLog("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid); - PSendSysMessage(LANG_COMMAND_CREATUREMOVED); + SendSysMessage(LANG_WAYPOINT_ADDED); + return true; } -//move selected object -bool ChatHandler::HandleMoveObjectCommand(const char* args) +//change level of creature or pet +bool ChatHandler::HandleNpcChangeLevelCommand(const char* args) { - // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hgameobject"); - if(!cId) + if (!*args) return false; - uint32 lowguid = atoi(cId); - if(!lowguid) + uint8 lvl = (uint8) atoi((char*)args); + if ( lvl < 1 || lvl > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) + 3) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); return false; + } - GameObject* obj = NULL; - - // by DB guid - if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) - obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); - - if(!obj) + Creature* pCreature = getSelectedCreature(); + if(!pCreature) { - PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SendSysMessage(LANG_SELECT_CREATURE); SetSentErrorMessage(true); return false; } - char* px = strtok(NULL, " "); - char* py = strtok(NULL, " "); - char* pz = strtok(NULL, " "); - - if (!px) + if(pCreature->isPet()) { - Player *chr = m_session->GetPlayer(); - - Map* map = obj->GetMap(); - map->Remove(obj,false); - - obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation()); - obj->SetFloatValue(GAMEOBJECT_POS_X, chr->GetPositionX()); - obj->SetFloatValue(GAMEOBJECT_POS_Y, chr->GetPositionY()); - obj->SetFloatValue(GAMEOBJECT_POS_Z, chr->GetPositionZ()); - - map->Add(obj); + ((Pet*)pCreature)->GivePetLevel(lvl); } else { - if(!py || !pz) - return false; - - float x = (float)atof(px); - float y = (float)atof(py); - float z = (float)atof(pz); - - if(!MapManager::IsValidMapCoord(obj->GetMapId(),x,y,z)) - { - PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,obj->GetMapId()); - SetSentErrorMessage(true); - return false; - } - - Map* map = obj->GetMap(); - map->Remove(obj,false); - - obj->Relocate(x, y, z, obj->GetOrientation()); - obj->SetFloatValue(GAMEOBJECT_POS_X, x); - obj->SetFloatValue(GAMEOBJECT_POS_Y, y); - obj->SetFloatValue(GAMEOBJECT_POS_Z, z); - - map->Add(obj); + pCreature->SetMaxHealth( 100 + 30*lvl); + pCreature->SetHealth( 100 + 30*lvl); + pCreature->SetLevel( lvl); + pCreature->SaveToDB(); } - obj->SaveToDB(); - obj->Refresh(); - - PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, obj->GetGUIDLow()); - - return true; -} - -//demorph player or unit -bool ChatHandler::HandleDeMorphCommand(const char* /*args*/) -{ - Unit *target = getSelectedUnit(); - if(!target) - target = m_session->GetPlayer(); - - - // check online security - else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) - return false; - - target->DeMorph(); - return true; } -//add item in vendorlist -bool ChatHandler::HandleAddVendorItemCommand(const char* args) +//set npcflag of creature +bool ChatHandler::HandleNpcFlagCommand(const char* args) { if (!*args) return false; - char* pitem = extractKeyFromLink((char*)args,"Hitem"); - if (!pitem) - { - SendSysMessage(LANG_COMMAND_NEEDITEMSEND); - SetSentErrorMessage(true); - return false; - } - - uint32 itemId = atol(pitem); - - char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0 - uint32 maxcount = 0; - if (fmaxcount) - maxcount = atol(fmaxcount); - - char* fincrtime = strtok(NULL, " "); //add incrtime, default: 0 - uint32 incrtime = 0; - if (fincrtime) - incrtime = atol(fincrtime); - - char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0 - uint32 extendedcost = fextendedcost ? atol(fextendedcost) : 0; - - Creature* vendor = getSelectedCreature(); + uint32 npcFlags = (uint32) atoi((char*)args); - uint32 vendor_entry = vendor ? vendor->GetEntry() : 0; + Creature* pCreature = getSelectedCreature(); - if(!objmgr.IsVendorItemValid(vendor_entry,itemId,maxcount,incrtime,extendedcost,m_session->GetPlayer())) + if(!pCreature) { + SendSysMessage(LANG_SELECT_CREATURE); SetSentErrorMessage(true); return false; } - objmgr.AddVendorItem(vendor_entry,itemId,maxcount,incrtime,extendedcost); + pCreature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags); - ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId); + WorldDatabase.PExecuteLog("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry()); + + SendSysMessage(LANG_VALUE_SAVED_REJOIN); - PSendSysMessage(LANG_ITEM_ADDED_TO_LIST,itemId,pProto->Name1,maxcount,incrtime,extendedcost); return true; } -//del item from vendor list -bool ChatHandler::HandleDelVendorItemCommand(const char* args) +bool ChatHandler::HandleNpcDeleteCommand(const char* args) { - if (!*args) - return false; + Creature* unit = NULL; - Creature* vendor = getSelectedCreature(); - if (!vendor || !vendor->isVendor()) + if(*args) { - SendSysMessage(LANG_COMMAND_VENDORSELECTION); - SetSentErrorMessage(true); - return false; - } + // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hcreature"); + if(!cId) + return false; - char* pitem = extractKeyFromLink((char*)args,"Hitem"); - if (!pitem) - { - SendSysMessage(LANG_COMMAND_NEEDITEMSEND); - SetSentErrorMessage(true); - return false; + uint32 lowguid = atoi(cId); + if(!lowguid) + return false; + + if (CreatureData const* cr_data = objmgr.GetCreatureData(lowguid)) + unit = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT)); } - uint32 itemId = atol(pitem); + else + unit = getSelectedCreature(); - if(!objmgr.RemoveVendorItem(vendor->GetEntry(),itemId)) + if(!unit || unit->isPet() || unit->isTotem() || unit->isVehicle()) { - PSendSysMessage(LANG_ITEM_NOT_IN_LIST,itemId); + SendSysMessage(LANG_SELECT_CREATURE); SetSentErrorMessage(true); return false; } - ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId); + // Delete the creature + unit->CombatStop(); + unit->DeleteFromDB(); + unit->CleanupsBeforeDelete(); + unit->AddObjectToRemoveList(); + + SendSysMessage(LANG_COMMAND_DELCREATMESSAGE); - PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST,itemId,pProto->Name1); return true; } -//add move for creature -bool ChatHandler::HandleNpcAddMoveCommand(const char* args) +//move selected creature +bool ChatHandler::HandleNpcMoveCommand(const char* args) { - if(!*args) - return false; + uint32 lowguid = 0; - char* guid_str = strtok((char*)args, " "); - char* wait_str = strtok((char*)NULL, " "); + Creature* pCreature = getSelectedCreature(); - uint32 lowguid = atoi((char*)guid_str); + if(!pCreature) + { + // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hcreature"); + if(!cId) + return false; - Creature* pCreature = NULL; + uint32 lowguid = atoi(cId); - /* FIXME: impossible without entry - if(lowguid) - pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT)); - */ + /* FIXME: impossibel without entry + if(lowguid) + pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT)); + */ - // attempt check creature existence by DB data - if(!pCreature) - { - CreatureData const* data = objmgr.GetCreatureData(lowguid); - if(!data) + // Attempting creature load from DB data + if(!pCreature) { - PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; + CreatureData const* data = objmgr.GetCreatureData(lowguid); + if(!data) + { + PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + uint32 map_id = data->mapid; + + if(m_session->GetPlayer()->GetMapId()!=map_id) + { + PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid); + SetSentErrorMessage(true); + return false; + } + } + else + { + lowguid = pCreature->GetDBTableGUIDLow(); } } else { - // obtain real GUID for DB operations lowguid = pCreature->GetDBTableGUIDLow(); } - int wait = wait_str ? atoi(wait_str) : 0; - - if(wait < 0) - wait = 0; - - Player* player = m_session->GetPlayer(); + float x = m_session->GetPlayer()->GetPositionX(); + float y = m_session->GetPlayer()->GetPositionY(); + float z = m_session->GetPlayer()->GetPositionZ(); + float o = m_session->GetPlayer()->GetOrientation(); - // update movement type - WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid); - if(pCreature && pCreature->GetWaypointPath()) + if (pCreature) { - pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); + if(CreatureData const* data = objmgr.GetCreatureData(pCreature->GetDBTableGUIDLow())) + { + const_cast<CreatureData*>(data)->posX = x; + const_cast<CreatureData*>(data)->posY = y; + const_cast<CreatureData*>(data)->posZ = z; + const_cast<CreatureData*>(data)->orientation = o; + } + pCreature->GetMap()->CreatureRelocation(pCreature,x, y, z,o); pCreature->GetMotionMaster()->Initialize(); if(pCreature->isAlive()) // dead creature will reset movement generator at respawn { pCreature->setDeathState(JUST_DIED); pCreature->Respawn(); } - pCreature->SaveToDB(); } + WorldDatabase.PExecuteLog("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid); + PSendSysMessage(LANG_COMMAND_CREATUREMOVED); return true; } -/** +/**HandleNpcSetMoveTypeCommand * Set the movement type for an NPC.<br/> * <br/> * Valid movement types are: @@ -1490,6 +1227,10 @@ bool ChatHandler::HandleNpcSetMoveTypeCommand(const char* args) else return false; + // update movement type + //if(doNotDelete == false) + // WaypointMgr.DeletePath(lowguid); + if(pCreature) { // update movement type @@ -1515,23 +1256,49 @@ bool ChatHandler::HandleNpcSetMoveTypeCommand(const char* args) } return true; -} // HandleNpcSetMoveTypeCommand +} -//change level of creature or pet -bool ChatHandler::HandleChangeLevelCommand(const char* args) +//set model of creature +bool ChatHandler::HandleNpcSetModelCommand(const char* args) { if (!*args) return false; - uint8 lvl = (uint8) atoi((char*)args); - if ( lvl < 1 || lvl > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) + 3) + uint32 displayId = (uint32) atoi((char*)args); + + Creature *pCreature = getSelectedCreature(); + + if(!pCreature || pCreature->isPet()) { - SendSysMessage(LANG_BAD_VALUE); + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->SetDisplayId(displayId); + pCreature->SetNativeDisplayId(displayId); + + pCreature->SaveToDB(); + + return true; +} +//set faction of creature +bool ChatHandler::HandleNpcFactionIdCommand(const char* args) +{ + if (!*args) + return false; + + uint32 factionId = (uint32) atoi((char*)args); + + if (!sFactionTemplateStore.LookupEntry(factionId)) + { + PSendSysMessage(LANG_WRONG_FACTION, factionId); SetSentErrorMessage(true); return false; } Creature* pCreature = getSelectedCreature(); + if(!pCreature) { SendSysMessage(LANG_SELECT_CREATURE); @@ -1539,57 +1306,253 @@ bool ChatHandler::HandleChangeLevelCommand(const char* args) return false; } - if(pCreature->isPet()) + pCreature->setFaction(factionId); + + // faction is set in creature_template - not inside creature + + // update in memory + if(CreatureInfo const *cinfo = pCreature->GetCreatureInfo()) { - ((Pet*)pCreature)->GivePetLevel(lvl); + const_cast<CreatureInfo*>(cinfo)->faction_A = factionId; + const_cast<CreatureInfo*>(cinfo)->faction_H = factionId; + } + + // and DB + WorldDatabase.PExecuteLog("UPDATE creature_template SET faction_A = '%u', faction_H = '%u' WHERE entry = '%u'", factionId, factionId, pCreature->GetEntry()); + + return true; +} +//set spawn dist of creature +bool ChatHandler::HandleNpcSpawnDistCommand(const char* args) +{ + if(!*args) + return false; + + float option = atof((char*)args); + if (option < 0.0f) + { + SendSysMessage(LANG_BAD_VALUE); + return false; } + + MovementGeneratorType mtype = IDLE_MOTION_TYPE; + if (option >0.0f) + mtype = RANDOM_MOTION_TYPE; + + Creature *pCreature = getSelectedCreature(); + uint32 u_guidlow = 0; + + if (pCreature) + u_guidlow = pCreature->GetDBTableGUIDLow(); else + return false; + + pCreature->SetRespawnRadius((float)option); + pCreature->SetDefaultMovementType(mtype); + pCreature->GetMotionMaster()->Initialize(); + if(pCreature->isAlive()) // dead creature will reset movement generator at respawn { - pCreature->SetMaxHealth( 100 + 30*lvl); - pCreature->SetHealth( 100 + 30*lvl); - pCreature->SetLevel( lvl); - pCreature->SaveToDB(); + pCreature->setDeathState(JUST_DIED); + pCreature->Respawn(); } + WorldDatabase.PExecuteLog("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow); + PSendSysMessage(LANG_COMMAND_SPAWNDIST,option); return true; } +//spawn time handling +bool ChatHandler::HandleNpcSpawnTimeCommand(const char* args) +{ + if(!*args) + return false; -//set npcflag of creature -bool ChatHandler::HandleNpcFlagCommand(const char* args) + char* stime = strtok((char*)args, " "); + + if (!stime) + return false; + + int i_stime = atoi((char*)stime); + + if (i_stime < 0) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Creature *pCreature = getSelectedCreature(); + uint32 u_guidlow = 0; + + if (pCreature) + u_guidlow = pCreature->GetDBTableGUIDLow(); + else + return false; + + WorldDatabase.PExecuteLog("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow); + pCreature->SetRespawnDelay((uint32)i_stime); + PSendSysMessage(LANG_COMMAND_SPAWNTIME,i_stime); + + return true; +} +//npc follow handling +bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/) { - if (!*args) + Player *player = m_session->GetPlayer(); + Creature *creature = getSelectedCreature(); + + if(!creature) + { + PSendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); return false; + } - uint32 npcFlags = (uint32) atoi((char*)args); + // Follow player - Using pet's default dist and angle + creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); - Creature* pCreature = getSelectedCreature(); + PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName()); + return true; +} +//npc unfollow handling +bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/) +{ + Player *player = m_session->GetPlayer(); + Creature *creature = getSelectedCreature(); - if(!pCreature) + if(!creature) { - SendSysMessage(LANG_SELECT_CREATURE); + PSendSysMessage(LANG_SELECT_CREATURE); SetSentErrorMessage(true); return false; } - pCreature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags); + if (/*creature->GetMotionMaster()->empty() ||*/ + creature->GetMotionMaster()->GetCurrentMovementGeneratorType ()!=TARGETED_MOTION_TYPE) + { + PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU); + SetSentErrorMessage(true); + return false; + } - WorldDatabase.PExecuteLog("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry()); + TargetedMovementGenerator<Creature> const* mgen + = static_cast<TargetedMovementGenerator<Creature> const*>((creature->GetMotionMaster()->top())); - SendSysMessage(LANG_VALUE_SAVED_REJOIN); + if(mgen->GetTarget()!=player) + { + PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU); + SetSentErrorMessage(true); + return false; + } + // reset movement + creature->GetMotionMaster()->MovementExpired(true); + + PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName()); return true; } +//npc tame handling +bool ChatHandler::HandleNpcTameCommand(const char* /*args*/) +{ + Creature *creatureTarget = getSelectedCreature (); + if (!creatureTarget || creatureTarget->isPet ()) + { + PSendSysMessage (LANG_SELECT_CREATURE); + SetSentErrorMessage (true); + return false; + } -//set model of creature -bool ChatHandler::HandleNpcSetModelCommand(const char* args) + Player *player = m_session->GetPlayer (); + + if(player->GetPetGUID ()) + { + SendSysMessage (LANG_YOU_ALREADY_HAVE_PET); + SetSentErrorMessage (true); + return false; + } + + CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo(); + + if (!cInfo->isTameable ()) + { + PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry); + SetSentErrorMessage (true); + return false; + } + + // Everything looks OK, create new pet + Pet* pet = player->CreateTamedPetFrom (creatureTarget); + if (!pet) + { + PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry); + SetSentErrorMessage (true); + return false; + } + + // place pet before player + float x,y,z; + player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE); + pet->Relocate (x,y,z,M_PI-player->GetOrientation ()); + + // set pet to defensive mode by default (some classes can't control controlled pets in fact). + pet->SetReactState(REACT_DEFENSIVE); + + // calculate proper level + uint32 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel(); + + // prepare visual effect for levelup + pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1); + + // add to world + pet->GetMap()->Add((Creature*)pet); + + // visual effect for levelup + pet->SetUInt32Value(UNIT_FIELD_LEVEL, level); + + // caster have pet now + player->SetPet(pet); + + pet->SavePetToDB(PET_SAVE_AS_CURRENT); + player->PetSpellInitialize(); + + return true; +} +//npc phasemask handling +//change phasemask of creature or pet +bool ChatHandler::HandleNpcSetPhaseCommand(const char* args) { if (!*args) return false; - uint32 displayId = (uint32) atoi((char*)args); + uint32 phasemask = (uint32) atoi((char*)args); + if ( phasemask == 0 ) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } - Creature *pCreature = getSelectedCreature(); + Creature* pCreature = getSelectedCreature(); + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->SetPhaseMask(phasemask,true); + + if(!pCreature->isPet()) + pCreature->SaveToDB(); + + return true; +} +//npc deathstate handling +bool ChatHandler::HandleNpcSetDeathStateCommand(const char* args) +{ + if (!*args) + return false; + Creature* pCreature = getSelectedCreature(); if(!pCreature || pCreature->isPet()) { SendSysMessage(LANG_SELECT_CREATURE); @@ -1597,72 +1560,373 @@ bool ChatHandler::HandleNpcSetModelCommand(const char* args) return false; } - pCreature->SetDisplayId(displayId); - pCreature->SetNativeDisplayId(displayId); + if (strncmp(args, "on", 3) == 0) + pCreature->SetDeadByDefault(true); + else if (strncmp(args, "off", 4) == 0) + pCreature->SetDeadByDefault(false); + else + { + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; + } pCreature->SaveToDB(); + pCreature->Respawn(); return true; } -//morph creature or player -bool ChatHandler::HandleMorphCommand(const char* args) +//TODO: NpcCommands that need to be fixed : + +bool ChatHandler::HandleNpcNameCommand(const char* /*args*/) { - if (!*args) + /* Temp. disabled + if(!*args) return false; - uint16 display_id = (uint16)atoi((char*)args); + if(strlen((char*)args)>75) + { + PSendSysMessage(LANG_TOO_LONG_NAME, strlen((char*)args)-75); + return true; + } - Unit *target = getSelectedUnit(); - if(!target) - target = m_session->GetPlayer(); + for (uint8 i = 0; i < strlen(args); i++) + { + if(!isalpha(args[i]) && args[i]!=' ') + { + SendSysMessage(LANG_CHARS_ONLY); + return false; + } + } - // check online security - else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) + uint64 guid; + guid = m_session->GetPlayer()->GetSelection(); + if (guid == 0) + { + SendSysMessage(LANG_NO_SELECTION); + return true; + } + + Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); + + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + return true; + } + + pCreature->SetName(args); + uint32 idname = objmgr.AddCreatureTemplate(pCreature->GetName()); + pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); + + pCreature->SaveToDB(); + */ + + return true; +} + +bool ChatHandler::HandleNpcSubNameCommand(const char* /*args*/) +{ + /* Temp. disabled + + if(!*args) + args = ""; + + if(strlen((char*)args)>75) + { + + PSendSysMessage(LANG_TOO_LONG_SUBNAME, strlen((char*)args)-75); + return true; + } + + for (uint8 i = 0; i < strlen(args); i++) + { + if(!isalpha(args[i]) && args[i]!=' ') + { + SendSysMessage(LANG_CHARS_ONLY); + return false; + } + } + uint64 guid; + guid = m_session->GetPlayer()->GetSelection(); + if (guid == 0) + { + SendSysMessage(LANG_NO_SELECTION); + return true; + } + + Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); + + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + return true; + } + + uint32 idname = objmgr.AddCreatureSubName(pCreature->GetName(),args,pCreature->GetUInt32Value(UNIT_FIELD_DISPLAYID)); + pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); + + pCreature->SaveToDB(); + */ + return true; +} + +//move item to other slot +bool ChatHandler::HandleItemMoveCommand(const char* args) +{ + if(!*args) return false; + uint8 srcslot, dstslot; - target->SetDisplayId(display_id); + char* pParam1 = strtok((char*)args, " "); + if (!pParam1) + return false; + + char* pParam2 = strtok(NULL, " "); + if (!pParam2) + return false; + + srcslot = (uint8)atoi(pParam1); + dstslot = (uint8)atoi(pParam2); + + if(srcslot==dstslot) + return true; + + if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot)) + return false; + + if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot)) + return false; + + uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); + uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); + + m_session->GetPlayer()->SwapItem( src, dst ); return true; } -//set faction of creature -bool ChatHandler::HandleNpcFactionIdCommand(const char* args) +//delete object by selection or guid +bool ChatHandler::HandleDelObjectCommand(const char* args) { - if (!*args) + // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if(!cId) return false; - uint32 factionId = (uint32) atoi((char*)args); + uint32 lowguid = atoi(cId); + if(!lowguid) + return false; - if (!sFactionTemplateStore.LookupEntry(factionId)) + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) + obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + + if(!obj) { - PSendSysMessage(LANG_WRONG_FACTION, factionId); + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); SetSentErrorMessage(true); return false; } - Creature* pCreature = getSelectedCreature(); + uint64 owner_guid = obj->GetOwnerGUID(); + if(owner_guid) + { + Unit* owner = ObjectAccessor::GetUnit(*m_session->GetPlayer(),owner_guid); + if(!owner && !IS_PLAYER_GUID(owner_guid)) + { + PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, GUID_LOPART(owner_guid), obj->GetGUIDLow()); + SetSentErrorMessage(true); + return false; + } - if(!pCreature) + owner->RemoveGameObject(obj,false); + } + + obj->SetRespawnTime(0); // not save respawn time + obj->Delete(); + obj->DeleteFromDB(); + + PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, obj->GetGUIDLow()); + + return true; +} + +//turn selected object +bool ChatHandler::HandleTurnObjectCommand(const char* args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if(!cId) + return false; + + uint32 lowguid = atoi(cId); + if(!lowguid) + return false; + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) + obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + + if(!obj) { - SendSysMessage(LANG_SELECT_CREATURE); + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); SetSentErrorMessage(true); return false; } - pCreature->setFaction(factionId); + char* po = strtok(NULL, " "); + float o; - // faction is set in creature_template - not inside creature + if (po) + { + o = (float)atof(po); + } + else + { + Player *chr = m_session->GetPlayer(); + o = chr->GetOrientation(); + } - // update in memory - if(CreatureInfo const *cinfo = pCreature->GetCreatureInfo()) + float rot2 = sin(o/2); + float rot3 = cos(o/2); + + Map* map = obj->GetMap(); + map->Remove(obj,false); + + obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o); + + obj->SetFloatValue(GAMEOBJECT_FACING, o); + obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rot2); + obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rot3); + + map->Add(obj); + + obj->SaveToDB(); + obj->Refresh(); + + PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), o); + + return true; +} + +//move selected object +bool ChatHandler::HandleMoveObjectCommand(const char* args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if(!cId) + return false; + + uint32 lowguid = atoi(cId); + if(!lowguid) + return false; + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) + obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + + if(!obj) { - const_cast<CreatureInfo*>(cinfo)->faction_A = factionId; - const_cast<CreatureInfo*>(cinfo)->faction_H = factionId; + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; } - // and DB - WorldDatabase.PExecuteLog("UPDATE creature_template SET faction_A = '%u', faction_H = '%u' WHERE entry = '%u'", factionId, factionId, pCreature->GetEntry()); + char* px = strtok(NULL, " "); + char* py = strtok(NULL, " "); + char* pz = strtok(NULL, " "); + + if (!px) + { + Player *chr = m_session->GetPlayer(); + + Map* map = obj->GetMap(); + map->Remove(obj,false); + + obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation()); + obj->SetFloatValue(GAMEOBJECT_POS_X, chr->GetPositionX()); + obj->SetFloatValue(GAMEOBJECT_POS_Y, chr->GetPositionY()); + obj->SetFloatValue(GAMEOBJECT_POS_Z, chr->GetPositionZ()); + + map->Add(obj); + } + else + { + if(!py || !pz) + return false; + + float x = (float)atof(px); + float y = (float)atof(py); + float z = (float)atof(pz); + + if(!MapManager::IsValidMapCoord(obj->GetMapId(),x,y,z)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,obj->GetMapId()); + SetSentErrorMessage(true); + return false; + } + + Map* map = obj->GetMap(); + map->Remove(obj,false); + + obj->Relocate(x, y, z, obj->GetOrientation()); + obj->SetFloatValue(GAMEOBJECT_POS_X, x); + obj->SetFloatValue(GAMEOBJECT_POS_Y, y); + obj->SetFloatValue(GAMEOBJECT_POS_Z, z); + + map->Add(obj); + } + + obj->SaveToDB(); + obj->Refresh(); + + PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, obj->GetGUIDLow()); + + return true; +} + +//demorph player or unit +bool ChatHandler::HandleDeMorphCommand(const char* /*args*/) +{ + Unit *target = getSelectedUnit(); + if(!target) + target = m_session->GetPlayer(); + + + // check online security + else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) + return false; + + target->DeMorph(); + + return true; +} + +//morph creature or player +bool ChatHandler::HandleMorphCommand(const char* args) +{ + if (!*args) + return false; + + uint16 display_id = (uint16)atoi((char*)args); + + Unit *target = getSelectedUnit(); + if(!target) + target = m_session->GetPlayer(); + + // check online security + else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) + return false; + + target->SetDisplayId(display_id); return true; } @@ -2144,81 +2408,30 @@ bool ChatHandler::HandleDelTicketCommand(const char *args) return true; }*/ -//set spawn dist of creature -bool ChatHandler::HandleNpcSpawnDistCommand(const char* args) -{ - if(!*args) - return false; - - float option = atof((char*)args); - if (option < 0.0f) - { - SendSysMessage(LANG_BAD_VALUE); - return false; - } - - MovementGeneratorType mtype = IDLE_MOTION_TYPE; - if (option >0.0f) - mtype = RANDOM_MOTION_TYPE; - - Creature *pCreature = getSelectedCreature(); - uint32 u_guidlow = 0; - - if (pCreature) - u_guidlow = pCreature->GetDBTableGUIDLow(); - else - return false; - - pCreature->SetRespawnRadius((float)option); - pCreature->SetDefaultMovementType(mtype); - pCreature->GetMotionMaster()->Initialize(); - if(pCreature->isAlive()) // dead creature will reset movement generator at respawn - { - pCreature->setDeathState(JUST_DIED); - pCreature->Respawn(); - } - - WorldDatabase.PExecuteLog("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow); - PSendSysMessage(LANG_COMMAND_SPAWNDIST,option); - return true; -} - -bool ChatHandler::HandleNpcSpawnTimeCommand(const char* args) -{ - if(!*args) - return false; - - char* stime = strtok((char*)args, " "); - - if (!stime) - return false; - - int i_stime = atoi((char*)stime); - - if (i_stime < 0) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Creature *pCreature = getSelectedCreature(); - uint32 u_guidlow = 0; - - if (pCreature) - u_guidlow = pCreature->GetDBTableGUIDLow(); - else - return false; - - WorldDatabase.PExecuteLog("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow); - pCreature->SetRespawnDelay((uint32)i_stime); - PSendSysMessage(LANG_COMMAND_SPAWNTIME,i_stime); - - return true; -} /////WAYPOINT COMMANDS +/** + * Add a waypoint to a creature. + * + * The user can either select an npc or provide its GUID. + * + * The user can even select a visual waypoint - then the new waypoint + * is placed *after* the selected one - this makes insertion of new + * waypoints possible. + * + * eg: + * .wp add 12345 + * -> adds a waypoint to the npc with the GUID 12345 + * + * .wp add + * -> adds a waypoint to the currently selected creature + * + * + * @param args if the user did not provide a GUID, it is NULL + * + * @return true - command did succeed, false - something went wrong + */ bool ChatHandler::HandleWpAddCommand(const char* args) { sLog.outDebug("DEBUG: HandleWpAddCommand"); @@ -4017,128 +4230,6 @@ bool ChatHandler::HandleWaterwalkCommand(const char* args) return true; } -bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/) -{ - Player *player = m_session->GetPlayer(); - Creature *creature = getSelectedCreature(); - - if(!creature) - { - PSendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - // Follow player - Using pet's default dist and angle - creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); - - PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName()); - return true; -} - -bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/) -{ - Player *player = m_session->GetPlayer(); - Creature *creature = getSelectedCreature(); - - if(!creature) - { - PSendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (/*creature->GetMotionMaster()->empty() ||*/ - creature->GetMotionMaster()->GetCurrentMovementGeneratorType ()!=TARGETED_MOTION_TYPE) - { - PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU); - SetSentErrorMessage(true); - return false; - } - - TargetedMovementGenerator<Creature> const* mgen - = static_cast<TargetedMovementGenerator<Creature> const*>((creature->GetMotionMaster()->top())); - - if(mgen->GetTarget()!=player) - { - PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU); - SetSentErrorMessage(true); - return false; - } - - // reset movement - creature->GetMotionMaster()->MovementExpired(true); - - PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName()); - return true; -} - -bool ChatHandler::HandleNpcTameCommand(const char* /*args*/) -{ - Creature *creatureTarget = getSelectedCreature (); - if (!creatureTarget || creatureTarget->isPet ()) - { - PSendSysMessage (LANG_SELECT_CREATURE); - SetSentErrorMessage (true); - return false; - } - - Player *player = m_session->GetPlayer (); - - if(player->GetPetGUID ()) - { - SendSysMessage (LANG_YOU_ALREADY_HAVE_PET); - SetSentErrorMessage (true); - return false; - } - - CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo(); - - if (!cInfo->isTameable ()) - { - PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry); - SetSentErrorMessage (true); - return false; - } - - // Everything looks OK, create new pet - Pet* pet = player->CreateTamedPetFrom (creatureTarget); - if (!pet) - { - PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry); - SetSentErrorMessage (true); - return false; - } - - // place pet before player - float x,y,z; - player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE); - pet->Relocate (x,y,z,M_PI-player->GetOrientation ()); - - // set pet to defensive mode by default (some classes can't control controlled pets in fact). - pet->SetReactState(REACT_DEFENSIVE); - - // calculate proper level - uint32 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel(); - - // prepare visual effect for levelup - pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1); - - // add to world - pet->GetMap()->Add((Creature*)pet); - - // visual effect for levelup - pet->SetUInt32Value(UNIT_FIELD_LEVEL, level); - - // caster have pet now - player->SetPet(pet); - - pet->SavePetToDB(PET_SAVE_AS_CURRENT); - player->PetSpellInitialize(); - - return true; -} - bool ChatHandler::HandleCreatePetCommand(const char* args) { Player *player = m_session->GetPlayer(); @@ -4439,102 +4530,3 @@ bool ChatHandler::HandleNpcAddFormationCommand(const char* args) return true; } - -//change phasemask of creature or pet -bool ChatHandler::HandleNpcSetPhaseCommand(const char* args) -{ - if (!*args) - return false; - - uint32 phasemask = (uint32) atoi((char*)args); - if ( phasemask == 0 ) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Creature* pCreature = getSelectedCreature(); - if(!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - pCreature->SetPhaseMask(phasemask,true); - - if(!pCreature->isPet()) - pCreature->SaveToDB(); - - return true; -} - -//set pahsemask for selected object -bool ChatHandler::HandleGOPhaseCommand(const char* args) -{ - // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hgameobject"); - if(!cId) - return false; - - uint32 lowguid = atoi(cId); - if(!lowguid) - return false; - - GameObject* obj = NULL; - // by DB guid - if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) - obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); - - if(!obj) - { - PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - char* phaseStr = strtok (NULL, " "); - uint32 phasemask = phaseStr? atoi(phaseStr) : 0; - if ( phasemask == 0 ) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - obj->SetPhaseMask(phasemask,true); - obj->SaveToDB(); - return true; -} - -bool ChatHandler::HandleNpcSetDeathStateCommand(const char* args) -{ - if (!*args) - return false; - - Creature* pCreature = getSelectedCreature(); - if(!pCreature || pCreature->isPet()) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (strncmp(args, "on", 3) == 0) - pCreature->SetDeadByDefault(true); - else if (strncmp(args, "off", 4) == 0) - pCreature->SetDeadByDefault(false); - else - { - SendSysMessage(LANG_USE_BOL); - SetSentErrorMessage(true); - return false; - } - - pCreature->SaveToDB(); - pCreature->Respawn(); - - return true; -} - diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 7b967693f6b..80d73d4dffe 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -3636,7 +3636,7 @@ bool ChatHandler::HandleGuildCreateCommand(const char* args) } Guild *guild = new Guild; - if (!guild->create (player->GetGUID (),guildname)) + if (!guild->create (player,guildname)) { delete guild; SendSysMessage (LANG_GUILD_NOT_CREATED); @@ -3831,77 +3831,6 @@ bool ChatHandler::HandleGetDistanceCommand(const char* args) return true; } -// FIX-ME!!! - -bool ChatHandler::HandleAddWeaponCommand(const char* /*args*/) -{ - /*if (!*args) - return false; - - uint64 guid = m_session->GetPlayer()->GetSelection(); - if (guid == 0) - { - SendSysMessage(LANG_NO_SELECTION); - return true; - } - - Creature *pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); - - if(!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - return true; - } - - char* pSlotID = strtok((char*)args, " "); - if (!pSlotID) - return false; - - char* pItemID = strtok(NULL, " "); - if (!pItemID) - return false; - - uint32 ItemID = atoi(pItemID); - uint32 SlotID = atoi(pSlotID); - - ItemPrototype* tmpItem = objmgr.GetItemPrototype(ItemID); - - bool added = false; - if(tmpItem) - { - switch(SlotID) - { - case 1: - pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, ItemID); - added = true; - break; - case 2: - pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_01, ItemID); - added = true; - break; - case 3: - pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_02, ItemID); - added = true; - break; - default: - PSendSysMessage(LANG_ITEM_SLOT_NOT_EXIST,SlotID); - added = false; - break; - } - if(added) - { - PSendSysMessage(LANG_ITEM_ADDED_TO_SLOT,ItemID,tmpItem->Name1,SlotID); - } - } - else - { - PSendSysMessage(LANG_ITEM_NOT_FOUND,ItemID); - return true; - } - */ - return true; -} - bool ChatHandler::HandleDieCommand(const char* /*args*/) { Unit* target = getSelectedUnit(); @@ -4236,21 +4165,28 @@ bool ChatHandler::HandleNearGraveCommand(const char* args) return true; } -//play npc emote -bool ChatHandler::HandleNpcPlayEmoteCommand(const char* args) +//-----------------------Npc Commands----------------------- +bool ChatHandler::HandleNpcChangeEntryCommand(const char *args) { - uint32 emote = atoi((char*)args); + if(!args) + return false; - Creature* target = getSelectedCreature(); - if(!target) + uint32 newEntryNum = atoi(args); + if(!newEntryNum) + return false; + + Unit* unit = getSelectedUnit(); + if(!unit || unit->GetTypeId() != TYPEID_UNIT) { SendSysMessage(LANG_SELECT_CREATURE); SetSentErrorMessage(true); return false; } - - target->SetUInt32Value(UNIT_NPC_EMOTESTATE,emote); - + Creature* creature = (Creature*)unit; + if(creature->UpdateEntry(newEntryNum)) + SendSysMessage(LANG_DONE); + else + SendSysMessage(LANG_ERROR); return true; } @@ -4299,6 +4235,95 @@ bool ChatHandler::HandleNpcInfoCommand(const char* /*args*/) return true; } +//play npc emote +bool ChatHandler::HandleNpcPlayEmoteCommand(const char* args) +{ + uint32 emote = atoi((char*)args); + + Creature* target = getSelectedCreature(); + if(!target) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + target->SetUInt32Value(UNIT_NPC_EMOTESTATE,emote); + + return true; +} + +//TODO: NpcCommands that needs to be fixed : + +bool ChatHandler::HandleNpcAddWeaponCommand(const char* /*args*/) +{ + /*if (!*args) + return false; + + uint64 guid = m_session->GetPlayer()->GetSelection(); + if (guid == 0) + { + SendSysMessage(LANG_NO_SELECTION); + return true; + } + + Creature *pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); + + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + return true; + } + + char* pSlotID = strtok((char*)args, " "); + if (!pSlotID) + return false; + + char* pItemID = strtok(NULL, " "); + if (!pItemID) + return false; + + uint32 ItemID = atoi(pItemID); + uint32 SlotID = atoi(pSlotID); + + ItemPrototype* tmpItem = objmgr.GetItemPrototype(ItemID); + + bool added = false; + if(tmpItem) + { + switch(SlotID) + { + case 1: + pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, ItemID); + added = true; + break; + case 2: + pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_01, ItemID); + added = true; + break; + case 3: + pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_02, ItemID); + added = true; + break; + default: + PSendSysMessage(LANG_ITEM_SLOT_NOT_EXIST,SlotID); + added = false; + break; + } + + if(added) + PSendSysMessage(LANG_ITEM_ADDED_TO_SLOT,ItemID,tmpItem->Name1,SlotID); + } + else + { + PSendSysMessage(LANG_ITEM_NOT_FOUND,ItemID); + return true; + } + */ + return true; +} +//---------------------------------------------------------- + bool ChatHandler::HandleExploreCheatCommand(const char* args) { if (!*args) @@ -6257,30 +6282,6 @@ bool ChatHandler::HandleLoadPDumpCommand(const char *args) return true; } -bool ChatHandler::HandleNpcChangeEntryCommand(const char *args) -{ - if(!args) - return false; - - uint32 newEntryNum = atoi(args); - if(!newEntryNum) - return false; - - Unit* unit = getSelectedUnit(); - if(!unit || unit->GetTypeId() != TYPEID_UNIT) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - Creature* creature = (Creature*)unit; - if(creature->UpdateEntry(newEntryNum)) - SendSysMessage(LANG_DONE); - else - SendSysMessage(LANG_ERROR); - return true; -} - bool ChatHandler::HandleWritePDumpCommand(const char *args) { if(!args) diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 1fa040640bb..2a9d417079d 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -43,9 +43,6 @@ #define DEFAULT_GRID_EXPIRY 300 #define MAX_GRID_LOAD_TIME 50 -// magic *.map header -const char MAP_MAGIC[] = "MAP_3.00"; - GridState* si_GridStates[MAX_GRID_STATE]; Map::~Map() @@ -68,9 +65,9 @@ bool Map::ExistMap(uint32 mapid,int x,int y) return false; } - char magic[8]; - fread(magic,1,8,pf); - if(strncmp(MAP_MAGIC,magic,8)) + map_fileheader header; + fread(&header, sizeof(header), 1, pf); + if (header.mapMagic != MAP_MAGIC || header.versionMagic != MAP_VERSION_MAGIC) { sLog.outError("Map file '%s' is non-compatible version (outdated?). Please, create new using ad.exe program.",tmp); delete [] tmp; @@ -80,7 +77,6 @@ bool Map::ExistMap(uint32 mapid,int x,int y) delete [] tmp; fclose(pf); - return true; } @@ -159,29 +155,13 @@ void Map::LoadMap(uint32 mapid, uint32 instanceid, int x,int y) snprintf(tmp, len, (char *)(sWorld.GetDataPath()+"maps/%03u%02u%02u.map").c_str(),mapid,x,y); sLog.outDetail("Loading map %s",tmp); // loading data - FILE *pf=fopen(tmp,"rb"); - if(!pf) + GridMaps[x][y] = new GridMap(); + if (!GridMaps[x][y]->loadData(tmp)) { - delete [] tmp; - return; + sLog.outError("Error load map file: \n %s\n", tmp); } - - char magic[8]; - fread(magic,1,8,pf); - if(strncmp(MAP_MAGIC,magic,8)) - { - sLog.outError("Map file '%s' is non-compatible version (outdated?). Please, create new using ad.exe program.",tmp); - delete [] tmp; - fclose(pf); //close file before return - return; - } - delete [] tmp; - - GridMap * buf= new GridMap; - fread(buf,1,sizeof(GridMap),pf); - fclose(pf); - - GridMaps[x][y] = buf; + delete [] tmp; + return; } void Map::LoadMapAndVMap(uint32 mapid, uint32 instanceid, int x,int y) @@ -1141,7 +1121,11 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool unloadAll) { if (i_InstanceId == 0) { - if(GridMaps[gx][gy]) delete (GridMaps[gx][gy]); + if(GridMaps[gx][gy]) + { + GridMaps[gx][gy]->unloadData(); + delete GridMaps[gx][gy]; + } // x and y are swapped VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(GetId(), gy, gx); } @@ -1166,99 +1150,527 @@ void Map::UnloadAll() } } -float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const +//***************************** +// Grid function +//***************************** +GridMap::GridMap() { - GridPair p = Trinity::ComputeGridPair(x, y); + m_flags = 0; + // Area data + m_gridArea = 0; + m_area_map = NULL; + // Height level data + m_gridHeight = INVALID_HEIGHT; + m_gridGetHeight = &GridMap::getHeightFromFlat; + m_V9 = NULL; + m_V8 = NULL; + // Liquid data + m_liquidType = 0; + m_liquid_offX = 0; + m_liquid_offY = 0; + m_liquid_width = 0; + m_liquid_height = 0; + m_liquidLevel = INVALID_HEIGHT; + m_liquid_type = NULL; + m_liquid_map = NULL; +} - // half opt method - int gx=(int)(32-x/SIZE_OF_GRIDS); //grid x - int gy=(int)(32-y/SIZE_OF_GRIDS); //grid y +GridMap::~GridMap() +{ + unloadData(); +} - float lx=MAP_RESOLUTION*(32 -x/SIZE_OF_GRIDS - gx); - float ly=MAP_RESOLUTION*(32 -y/SIZE_OF_GRIDS - gy); +bool GridMap::loadData(char *filename) +{ + // Unload old data if exist + unloadData(); - // ensure GridMap is loaded - const_cast<Map*>(this)->EnsureGridCreated(GridPair(63-gx,63-gy)); + map_fileheader header; + // Not return error if file not found + FILE *in = fopen(filename, "rb"); + if (!in) + return true; + fread(&header, sizeof(header),1,in); + if (header.mapMagic == MAP_MAGIC && header.versionMagic == MAP_VERSION_MAGIC) + { + // loadup area data + if (header.areaMapOffset && !loadAreaData(in, header.areaMapOffset, header.areaMapSize)) + { + sLog.outError("Error loading map area data\n"); + fclose(in); + return false; + } + // loadup height data + if (header.heightMapOffset && !loadHeihgtData(in, header.heightMapOffset, header.heightMapSize)) + { + sLog.outError("Error loading map height data\n"); + fclose(in); + return false; + } + // loadup liquid data + if (header.liquidMapOffset && !loadLiquidData(in, header.liquidMapOffset, header.liquidMapSize)) + { + sLog.outError("Error loading map liquids data\n"); + fclose(in); + return false; + } + fclose(in); + return true; + } + sLog.outError("Map file '%s' is non-compatible version (outdated?). Please, create new using ad.exe program.", filename); + fclose(in); + return false; +} - // find raw .map surface under Z coordinates - float mapHeight; - if(GridMap* gmap = GridMaps[gx][gy]) - { - int lx_int = (int)lx; - int ly_int = (int)ly; - - // In some very rare case this will happen. Need find a better way. - //if(lx_int == MAP_RESOLUTION) --lx_int; - //if(ly_int == MAP_RESOLUTION) --ly_int; - - lx -= lx_int; - ly -= ly_int; - - // Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid - // +--------------> X - // | h1-------h2 Coordinates is: - // | | \ 1 / | h1 0,0 - // | | \ / | h2 0,1 - // | | 2 h5 3 | h3 1,0 - // | | / \ | h4 1,1 - // | | / 4 \ | h5 1/2,1/2 - // | h3-------h4 - // V Y - // For find height need - // 1 - detect triangle - // 2 - solve linear equation from triangle points - - // Calculate coefficients for solve h = a*x + b*y + c - float a,b,c; - // Select triangle: - if (lx+ly < 1) +void GridMap::unloadData() +{ + if (m_area_map) delete[] m_area_map; + if (m_V9) delete[] m_V9; + if (m_V8) delete[] m_V8; + if (m_liquid_type) delete[] m_liquid_type; + if (m_liquid_map) delete[] m_liquid_map; + m_area_map = NULL; + m_V9 = NULL; + m_V8 = NULL; + m_liquid_type = NULL; + m_liquid_map = NULL; + m_gridGetHeight = &GridMap::getHeightFromFlat; +} + +bool GridMap::loadAreaData(FILE *in, uint32 offset, uint32 size) +{ + map_areaHeader header; + fseek(in, offset, SEEK_SET); + fread(&header, sizeof(header), 1, in); + if (header.fourcc != MAP_AREA_MAGIC) + return false; + + m_gridArea = header.gridArea; + if (!(header.flags&MAP_AREA_NO_AREA)) + { + m_area_map = new uint16 [16*16]; + fread(m_area_map, sizeof(uint16), 16*16, in); + } + return true; +} + +bool GridMap::loadHeihgtData(FILE *in, uint32 offset, uint32 size) +{ + map_heightHeader header; + fseek(in, offset, SEEK_SET); + fread(&header, sizeof(header), 1, in); + if (header.fourcc != MAP_HEIGTH_MAGIC) + return false; + + m_gridHeight = header.gridHeight; + if (!(header.flags&MAP_HEIGHT_NO_HIGHT)) + { + if ((header.flags&MAP_HEIGHT_AS_INT16)) { - if (lx > ly) - { - // 1 triangle (h1, h2, h5 points) - float h1 = gmap->v9[lx_int][ly_int]; - float h2 = gmap->v9[lx_int+1][ly_int]; - float h5 = 2 * gmap->v8[lx_int][ly_int]; - a = h2-h1; - b = h5-h1-h2; - c = h1; - } - else - { - // 2 triangle (h1, h3, h5 points) - float h1 = gmap->v9[lx_int][ly_int]; - float h3 = gmap->v9[lx_int][ly_int+1]; - float h5 = 2 * gmap->v8[lx_int][ly_int]; - a = h5 - h1 - h3; - b = h3 - h1; - c = h1; - } + m_uint16_V9 = new uint16 [129*129]; + m_uint16_V8 = new uint16 [128*128]; + fread(m_uint16_V9, sizeof(uint16), 129*129, in); + fread(m_uint16_V8, sizeof(uint16), 128*128, in); + m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 65535; + m_gridGetHeight = &GridMap::getHeightFromUint16; + } + else if ((header.flags&MAP_HEIGHT_AS_INT8)) + { + m_uint8_V9 = new uint8 [129*129]; + m_uint8_V8 = new uint8 [128*128]; + fread(m_uint8_V9, sizeof(uint8), 129*129, in); + fread(m_uint8_V8, sizeof(uint8), 128*128, in); + m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 255; + m_gridGetHeight = &GridMap::getHeightFromUint8; } else { - if (lx > ly) - { - // 3 triangle (h2, h4, h5 points) - float h2 = gmap->v9[lx_int+1][ly_int]; - float h4 = gmap->v9[lx_int+1][ly_int+1]; - float h5 = 2 * gmap->v8[lx_int][ly_int]; - a = h2 + h4 - h5; - b = h4 - h2; - c = h5 - h4; - } - else - { - // 4 triangle (h3, h4, h5 points) - float h3 = gmap->v9[lx_int][ly_int+1]; - float h4 = gmap->v9[lx_int+1][ly_int+1]; - float h5 = 2 * gmap->v8[lx_int][ly_int]; - a = h4 - h3; - b = h3 + h4 - h5; - c = h5 - h4; - } + m_V9 = new float [129*129]; + m_V8 = new float [128*128]; + fread(m_V9, sizeof(float), 129*129, in); + fread(m_V8, sizeof(float), 128*128, in); + m_gridGetHeight = &GridMap::getHeightFromFloat; } - // Calculate height - float _mapheight = a * lx + b * ly + c; + } + else + m_gridGetHeight = &GridMap::getHeightFromFlat; + return true; +} + +bool GridMap::loadLiquidData(FILE *in, uint32 offset, uint32 size) +{ + map_liquidHeader header; + fseek(in, offset, SEEK_SET); + fread(&header, sizeof(header), 1, in); + if (header.fourcc != MAP_LIQUID_MAGIC) + return false; + + m_liquidType = header.liquidType; + m_liquid_offX = header.offsetX; + m_liquid_offY = header.offsetY; + m_liquid_width = header.width; + m_liquid_height= header.height; + m_liquidLevel = header.liquidLevel; + + if (!(header.flags&MAP_LIQUID_NO_TYPE)) + { + m_liquid_type = new uint8 [16*16]; + fread(m_liquid_type, sizeof(uint8), 16*16, in); + } + if (!(header.flags&MAP_LIQUID_NO_HIGHT)) + { + m_liquid_map = new float [m_liquid_width*m_liquid_height]; + fread(m_liquid_map, sizeof(float), m_liquid_width*m_liquid_height, in); + } + return true; +} + +uint16 GridMap::getArea(float x, float y) +{ + if (!m_area_map) + return m_gridArea; + + x = 16 * (32 - x/SIZE_OF_GRIDS); + y = 16 * (32 - y/SIZE_OF_GRIDS); + int lx = (int)x & 15; + int ly = (int)y & 15; + return m_area_map[lx*16 + ly]; +} + +float GridMap::getHeightFromFlat(float x, float y) const +{ + return m_gridHeight; +} + +float GridMap::getHeightFromFloat(float x, float y) const +{ + if (!m_V8 || !m_V9) + return m_gridHeight; + + x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); + y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); + + int x_int = (int)x; + int y_int = (int)y; + x -= x_int; + y -= y_int; + x_int&=(MAP_RESOLUTION - 1); + y_int&=(MAP_RESOLUTION - 1); + + // Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid + // +--------------> X + // | h1-------h2 Coordinates is: + // | | \ 1 / | h1 0,0 + // | | \ / | h2 0,1 + // | | 2 h5 3 | h3 1,0 + // | | / \ | h4 1,1 + // | | / 4 \ | h5 1/2,1/2 + // | h3-------h4 + // V Y + // For find height need + // 1 - detect triangle + // 2 - solve linear equation from triangle points + // Calculate coefficients for solve h = a*x + b*y + c + + float a,b,c; + // Select triangle: + if (x+y < 1) + { + if (x > y) + { + // 1 triangle (h1, h2, h5 points) + float h1 = m_V9[(x_int )*129 + y_int]; + float h2 = m_V9[(x_int+1)*129 + y_int]; + float h5 = 2 * m_V8[x_int*128 + y_int]; + a = h2-h1; + b = h5-h1-h2; + c = h1; + } + else + { + // 2 triangle (h1, h3, h5 points) + float h1 = m_V9[x_int*129 + y_int ]; + float h3 = m_V9[x_int*129 + y_int+1]; + float h5 = 2 * m_V8[x_int*128 + y_int]; + a = h5 - h1 - h3; + b = h3 - h1; + c = h1; + } + } + else + { + if (x > y) + { + // 3 triangle (h2, h4, h5 points) + float h2 = m_V9[(x_int+1)*129 + y_int ]; + float h4 = m_V9[(x_int+1)*129 + y_int+1]; + float h5 = 2 * m_V8[x_int*128 + y_int]; + a = h2 + h4 - h5; + b = h4 - h2; + c = h5 - h4; + } + else + { + // 4 triangle (h3, h4, h5 points) + float h3 = m_V9[(x_int )*129 + y_int+1]; + float h4 = m_V9[(x_int+1)*129 + y_int+1]; + float h5 = 2 * m_V8[x_int*128 + y_int]; + a = h4 - h3; + b = h3 + h4 - h5; + c = h5 - h4; + } + } + // Calculate height + return a * x + b * y + c; +} + +float GridMap::getHeightFromUint8(float x, float y) const +{ + if (!m_uint8_V8 || !m_uint8_V9) + return m_gridHeight; + + x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); + y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); + + int x_int = (int)x; + int y_int = (int)y; + x -= x_int; + y -= y_int; + x_int&=(MAP_RESOLUTION - 1); + y_int&=(MAP_RESOLUTION - 1); + + int32 a, b, c; + uint8 *V9_h1_ptr = &m_uint8_V9[x_int*128 + x_int + y_int]; + if (x+y < 1) + { + if (x > y) + { + // 1 triangle (h1, h2, h5 points) + int32 h1 = V9_h1_ptr[ 0]; + int32 h2 = V9_h1_ptr[129]; + int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int]; + a = h2-h1; + b = h5-h1-h2; + c = h1; + } + else + { + // 2 triangle (h1, h3, h5 points) + int32 h1 = V9_h1_ptr[0]; + int32 h3 = V9_h1_ptr[1]; + int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int]; + a = h5 - h1 - h3; + b = h3 - h1; + c = h1; + } + } + else + { + if (x > y) + { + // 3 triangle (h2, h4, h5 points) + int32 h2 = V9_h1_ptr[129]; + int32 h4 = V9_h1_ptr[130]; + int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int]; + a = h2 + h4 - h5; + b = h4 - h2; + c = h5 - h4; + } + else + { + // 4 triangle (h3, h4, h5 points) + int32 h3 = V9_h1_ptr[ 1]; + int32 h4 = V9_h1_ptr[130]; + int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int]; + a = h4 - h3; + b = h3 + h4 - h5; + c = h5 - h4; + } + } + // Calculate height + return (float)((a * x) + (b * y) + c)*m_gridIntHeightMultiplier + m_gridHeight; +} + +float GridMap::getHeightFromUint16(float x, float y) const +{ + if (!m_uint16_V8 || !m_uint16_V9) + return m_gridHeight; + + x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); + y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); + + int x_int = (int)x; + int y_int = (int)y; + x -= x_int; + y -= y_int; + x_int&=(MAP_RESOLUTION - 1); + y_int&=(MAP_RESOLUTION - 1); + + int32 a, b, c; + uint16 *V9_h1_ptr = &m_uint16_V9[x_int*128 + x_int + y_int]; + if (x+y < 1) + { + if (x > y) + { + // 1 triangle (h1, h2, h5 points) + int32 h1 = V9_h1_ptr[ 0]; + int32 h2 = V9_h1_ptr[129]; + int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int]; + a = h2-h1; + b = h5-h1-h2; + c = h1; + } + else + { + // 2 triangle (h1, h3, h5 points) + int32 h1 = V9_h1_ptr[0]; + int32 h3 = V9_h1_ptr[1]; + int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int]; + a = h5 - h1 - h3; + b = h3 - h1; + c = h1; + } + } + else + { + if (x > y) + { + // 3 triangle (h2, h4, h5 points) + int32 h2 = V9_h1_ptr[129]; + int32 h4 = V9_h1_ptr[130]; + int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int]; + a = h2 + h4 - h5; + b = h4 - h2; + c = h5 - h4; + } + else + { + // 4 triangle (h3, h4, h5 points) + int32 h3 = V9_h1_ptr[ 1]; + int32 h4 = V9_h1_ptr[130]; + int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int]; + a = h4 - h3; + b = h3 + h4 - h5; + c = h5 - h4; + } + } + // Calculate height + return (float)((a * x) + (b * y) + c)*m_gridIntHeightMultiplier + m_gridHeight; +} + +float GridMap::getLiquidLevel(float x, float y) +{ + if (!m_liquid_map) + return m_liquidLevel; + + x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); + y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); + + int cx_int = ((int)x & (MAP_RESOLUTION-1)) - m_liquid_offY; + int cy_int = ((int)y & (MAP_RESOLUTION-1)) - m_liquid_offX; + + if (cx_int < 0 || cx_int >=m_liquid_height) + return INVALID_HEIGHT; + if (cy_int < 0 || cy_int >=m_liquid_width ) + return INVALID_HEIGHT; + + return m_liquid_map[cx_int*m_liquid_width + cy_int]; +} + +uint8 GridMap::getTerrainType(float x, float y) +{ + if (!m_liquid_type) + return m_liquidType; + + x = 16 * (32 - x/SIZE_OF_GRIDS); + y = 16 * (32 - y/SIZE_OF_GRIDS); + int lx = (int)x & 15; + int ly = (int)y & 15; + return m_liquid_type[lx*16 + ly]; +} + +// Get water state on map +inline ZLiquidStatus GridMap::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data) +{ + // Check water type (if no water return) + if (!m_liquid_type && !m_liquidType) + return LIQUID_MAP_NO_WATER; + + // Get cell + float cx = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); + float cy = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); + + int x_int = (int)cx & (MAP_RESOLUTION-1); + int y_int = (int)cy & (MAP_RESOLUTION-1); + + // Check water type in cell + uint8 type = m_liquid_type ? m_liquid_type[(x_int>>3)*16 + (y_int>>3)] : m_liquidType; + if (type == 0) + return LIQUID_MAP_NO_WATER; + + // Check req liquid type mask + if (ReqLiquidType && !(ReqLiquidType&type)) + return LIQUID_MAP_NO_WATER; + + // Check water level: + // Check water height map + int lx_int = x_int - m_liquid_offY; + int ly_int = y_int - m_liquid_offX; + if (lx_int < 0 || lx_int >=m_liquid_height) + return LIQUID_MAP_NO_WATER; + if (ly_int < 0 || ly_int >=m_liquid_width ) + return LIQUID_MAP_NO_WATER; + + // Get water level + float liquid_level = m_liquid_map ? m_liquid_map[lx_int*m_liquid_width + ly_int] : m_liquidLevel; + // Get ground level (sub 0.2 for fix some errors) + float ground_level = getHeight(x, y); + + // Check water level and ground level + if (liquid_level < ground_level || z < ground_level - 2) + return LIQUID_MAP_NO_WATER; + + // All ok in water -> store data + if (data) + { + data->type = type; + data->level = liquid_level; + data->depth_level = ground_level; + } + + // For speed check as int values + int delta = (liquid_level - z) * 10; + + // Get position delta + if (delta > 20) // Under water + return LIQUID_MAP_UNDER_WATER; + if (delta > 0 ) // In water + return LIQUID_MAP_IN_WATER; + if (delta > -1) // Walk on water + return LIQUID_MAP_WATER_WALK; + // Above water + return LIQUID_MAP_ABOVE_WATER; +} + +inline GridMap *Map::GetGrid(float x, float y) +{ + // half opt method + int gx=(int)(32-x/SIZE_OF_GRIDS); //grid x + int gy=(int)(32-y/SIZE_OF_GRIDS); //grid y + + // ensure GridMap is loaded + EnsureGridCreated(GridPair(63-gx,63-gy)); + + return GridMaps[gx][gy]; +} + +float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const +{ + // find raw .map surface under Z coordinates + float mapHeight; + if(GridMap *gmap = const_cast<Map*>(this)->GetGrid(x, y)) + { + float _mapheight = gmap->getHeight(x,y); // look from a bit higher pos to find the floor, ignore under surface case if(z + 2.0f > _mapheight) @@ -1337,25 +1749,9 @@ float Map::GetVmapHeight(float x, float y, float z, bool useMaps) const uint16 Map::GetAreaFlag(float x, float y, float z) const { - //local x,y coords - float lx,ly; - int gx,gy; - GridPair p = Trinity::ComputeGridPair(x, y); - - // half opt method - gx=(int)(32-x/SIZE_OF_GRIDS) ; //grid x - gy=(int)(32-y/SIZE_OF_GRIDS); //grid y - - lx=16*(32 -x/SIZE_OF_GRIDS - gx); - ly=16*(32 -y/SIZE_OF_GRIDS - gy); - //DEBUG_LOG("my %d %d si %d %d",gx,gy,p.x_coord,p.y_coord); - - // ensure GridMap is loaded - const_cast<Map*>(this)->EnsureGridCreated(GridPair(63-gx,63-gy)); - uint16 areaflag; - if(GridMaps[gx][gy]) - areaflag = GridMaps[gx][gy]->area_flag[(int)(lx)][(int)(ly)]; + if(GridMap *gmap = const_cast<Map*>(this)->GetGrid(x, y)) + areaflag = gmap->getArea(x, y); // this used while not all *.map files generated (instances) else areaflag = GetAreaFlagByMapId(i_id); @@ -1386,44 +1782,24 @@ uint16 Map::GetAreaFlag(float x, float y, float z) const uint8 Map::GetTerrainType(float x, float y ) const { - //local x,y coords - float lx,ly; - int gx,gy; - - // half opt method - gx=(int)(32-x/SIZE_OF_GRIDS) ; //grid x - gy=(int)(32-y/SIZE_OF_GRIDS); //grid y - - lx=16*(32 -x/SIZE_OF_GRIDS - gx); - ly=16*(32 -y/SIZE_OF_GRIDS - gy); - - // ensure GridMap is loaded - const_cast<Map*>(this)->EnsureGridCreated(GridPair(63-gx,63-gy)); - - if(GridMaps[gx][gy]) - return GridMaps[gx][gy]->terrain_type[(int)(lx)][(int)(ly)]; + if(GridMap *gmap = const_cast<Map*>(this)->GetGrid(x, y)) + return gmap->getTerrainType(x, y); else return 0; } -float Map::GetWaterLevel(float x, float y ) const +ZLiquidStatus Map::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data) const { - //local x,y coords - float lx,ly; - int gx,gy; - - // half opt method - gx=(int)(32-x/SIZE_OF_GRIDS) ; //grid x - gy=(int)(32-y/SIZE_OF_GRIDS); //grid y - - lx=128*(32 -x/SIZE_OF_GRIDS - gx); - ly=128*(32 -y/SIZE_OF_GRIDS - gy); - - // ensure GridMap is loaded - const_cast<Map*>(this)->EnsureGridCreated(GridPair(63-gx,63-gy)); + if(GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y)) + return gmap->getLiquidStatus(x, y, z, ReqLiquidType, data); + else + return LIQUID_MAP_NO_WATER; +} - if(GridMaps[gx][gy]) - return GridMaps[gx][gy]->liquid_level[(int)(lx)][(int)(ly)]; +float Map::GetWaterLevel(float x, float y ) const +{ + if(GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y)) + return gmap->getLiquidLevel(x, y); else return 0; } @@ -1450,24 +1826,27 @@ uint32 Map::GetZoneId(uint16 areaflag,uint32 map_id) bool Map::IsInWater(float x, float y, float pZ) const { - // This method is called too often to use vamps for that (4. parameter = false). - // The pZ pos is taken anyway for future use - float z = GetHeight(x,y,pZ,false); // use .map base surface height - - // underground or instance without vmap - if(z <= INVALID_HEIGHT) - return false; - - float water_z = GetWaterLevel(x,y); - uint8 flag = GetTerrainType(x,y); - return (z < (water_z-2)) && (flag & 0x01); + // Check surface in x, y point for liquid + if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y)) + { + LiquidData liquid_status; + if (getLiquidStatus(x, y, pZ, MAP_ALL_LIQUIDS, &liquid_status)) + { + if (liquid_status.level - liquid_status.depth_level > 2) + return true; + } + } + return false; } bool Map::IsUnderWater(float x, float y, float z) const { - float water_z = GetWaterLevel(x,y); - uint8 flag = GetTerrainType(x,y); - return (z < (water_z-2)) && (flag & 0x01); + if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y)) + { + if (getLiquidStatus(x, y, z, MAP_LIQUID_TYPE_WATER|MAP_LIQUID_TYPE_OCEAN)&LIQUID_MAP_UNDER_WATER) + return true; + } + return false; } bool Map::CheckGridIntegrity(Creature* c, bool moved) const @@ -2061,7 +2440,7 @@ void InstanceMap::PermBindAllPlayers(Player *player) InstanceSave *save = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); if(!save) { - sLog.outError("Cannot bind players, no instance save available for map!\n"); + sLog.outError("Cannot bind players, no instance save available for map!"); return; } diff --git a/src/game/Map.h b/src/game/Map.h index 22f015ad588..0d03970e102 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -70,14 +70,135 @@ typedef RGuard<GridRWLock, ZThread::Lockable> GridReadGuard; typedef WGuard<GridRWLock, ZThread::Lockable> GridWriteGuard; typedef Trinity::SingleThreaded<GridRWLock>::Lock NullGuard; -typedef struct +//****************************************** +// Map file format defines +//****************************************** +#define MAP_MAGIC 'SPAM' +#define MAP_VERSION_MAGIC '0.1v' +#define MAP_AREA_MAGIC 'AERA' +#define MAP_HEIGTH_MAGIC 'TGHM' +#define MAP_LIQUID_MAGIC 'QILM' + +struct map_fileheader{ + uint32 mapMagic; + uint32 versionMagic; + uint32 areaMapOffset; + uint32 areaMapSize; + uint32 heightMapOffset; + uint32 heightMapSize; + uint32 liquidMapOffset; + uint32 liquidMapSize; +}; + +#define MAP_AREA_NO_AREA 0x0001 +struct map_areaHeader{ + uint32 fourcc; + uint16 flags; + uint16 gridArea; +}; + +#define MAP_HEIGHT_NO_HIGHT 0x0001 +#define MAP_HEIGHT_AS_INT16 0x0002 +#define MAP_HEIGHT_AS_INT8 0x0004 + +struct map_heightHeader{ + uint32 fourcc; + uint32 flags; + float gridHeight; + float gridMaxHeight; +}; + +#define MAP_LIQUID_NO_TYPE 0x0001 +#define MAP_LIQUID_NO_HIGHT 0x0002 +struct map_liquidHeader{ + uint32 fourcc; + uint16 flags; + uint16 liquidType; + uint8 offsetX; + uint8 offsetY; + uint8 width; + uint8 height; + float liquidLevel; +}; + +enum ZLiquidStatus{ + LIQUID_MAP_NO_WATER = 0x00000000, + LIQUID_MAP_ABOVE_WATER = 0x00000001, + LIQUID_MAP_WATER_WALK = 0x00000002, + LIQUID_MAP_IN_WATER = 0x00000004, + LIQUID_MAP_UNDER_WATER = 0x00000008 +}; + +#define MAP_LIQUID_TYPE_NO_WATER 0x00 +#define MAP_LIQUID_TYPE_WATER 0x01 +#define MAP_LIQUID_TYPE_OCEAN 0x02 +#define MAP_LIQUID_TYPE_MAGMA 0x04 +#define MAP_LIQUID_TYPE_SLIME 0x08 + +#define MAP_ALL_LIQUIDS (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN | MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME) + +#define MAP_LIQUID_TYPE_DARK_WATER 0x10 +#define MAP_LIQUID_TYPE_WMO_WATER 0x20 + +struct LiquidData{ + uint32 type; + float level; + float depth_level; +}; + +class GridMap { - uint16 area_flag[16][16]; - uint8 terrain_type[16][16]; - float liquid_level[128][128]; - float v9[MAP_RESOLUTION + 1][MAP_RESOLUTION + 1]; - float v8[MAP_RESOLUTION][MAP_RESOLUTION]; -}GridMap; + uint32 m_flags; + // Area data + uint16 m_gridArea; + uint16 *m_area_map; + // Height level data + float m_gridHeight; + float m_gridIntHeightMultiplier; + union{ + float *m_V9; + uint16 *m_uint16_V9; + uint8 *m_uint8_V9; + }; + union{ + float *m_V8; + uint16 *m_uint16_V8; + uint8 *m_uint8_V8; + }; + // Liquid data + uint16 m_liquidType; + uint8 m_liquid_offX; + uint8 m_liquid_offY; + uint8 m_liquid_width; + uint8 m_liquid_height; + float m_liquidLevel; + uint8 *m_liquid_type; + float *m_liquid_map; + + bool loadAreaData(FILE *in, uint32 offset, uint32 size); + bool loadHeihgtData(FILE *in, uint32 offset, uint32 size); + bool loadLiquidData(FILE *in, uint32 offset, uint32 size); + + // Get height functions and pointers + typedef float (GridMap::*pGetHeightPtr) (float x, float y) const; + pGetHeightPtr m_gridGetHeight; + float getHeightFromFloat(float x, float y) const; + float getHeightFromUint16(float x, float y) const; + float getHeightFromUint8(float x, float y) const; + float getHeightFromFlat(float x, float y) const; + +public: + GridMap(); + ~GridMap(); + bool loadData(char *filaname); + void unloadData(); + + uint16 getArea(float x, float y); + inline float getHeight(float x, float y) {return (this->*m_gridGetHeight)(x, y);} + float getLiquidLevel(float x, float y); + uint8 getTerrainType(float x, float y); + ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data = 0); +}; struct CreatureMover { @@ -192,6 +313,8 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O float GetVmapHeight(float x, float y, float z, bool useMaps) const; bool IsInWater(float x, float y, float z) const; // does not use z pos. This is for future use + ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data = 0) const; + uint16 GetAreaFlag(float x, float y, float z) const; uint8 GetTerrainType(float x, float y ) const; float GetWaterLevel(float x, float y ) const; @@ -288,6 +411,7 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O private: void LoadVMap(int pX, int pY); void LoadMap(uint32 mapid, uint32 instanceid, int x,int y); + GridMap *GetGrid(float x, float y); void SetTimer(uint32 t) { i_gridExpiry = t < MIN_GRID_DELAY ? MIN_GRID_DELAY : t; } //uint64 CalculateGridMask(const uint32 &y) const; diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index d8ce6c0a46a..e2bbf8b956b 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -25,6 +25,7 @@ #include "Log.h" #include "Corpse.h" #include "Player.h" +#include "Vehicle.h" #include "MapManager.h" #include "Transports.h" #include "BattleGround.h" diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 3cb5d31b6cc..9fdca51777a 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -27,6 +27,7 @@ #include "Object.h" #include "Creature.h" #include "Player.h" +#include "Vehicle.h" #include "ObjectMgr.h" #include "UpdateData.h" #include "UpdateMask.h" diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index e89149a88ed..cc4231fa14a 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -25,6 +25,7 @@ #include "Creature.h" #include "GameObject.h" #include "DynamicObject.h" +#include "Vehicle.h" #include "WorldPacket.h" #include "Item.h" #include "Corpse.h" @@ -409,7 +410,7 @@ ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid, bool insignia) return NULL; } - DEBUG_LOG("Deleting Corpse and spawning bones.\n"); + DEBUG_LOG("Deleting Corpse and spawning bones."); // remove corpse from player_guid -> corpse map RemoveCorpse(corpse); diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h index c6144ec4d5b..fea2331695c 100644 --- a/src/game/ObjectAccessor.h +++ b/src/game/ObjectAccessor.h @@ -33,7 +33,6 @@ #include "GridDefines.h" #include "Object.h" #include "Player.h" -#include "Vehicle.h" #include <set> @@ -42,6 +41,7 @@ class Corpse; class Unit; class GameObject; class DynamicObject; +class Vehicle; class WorldObject; class Map; diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 2c32c7ea909..081acb07621 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -1859,7 +1859,10 @@ void ObjectMgr::LoadPetLevelInfo() if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum sLog.outErrorDb("Wrong (> %u) level %u in `pet_levelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); else + { sLog.outDetail("Unused (> MaxPlayerLevel in Trinityd.conf) level %u in `pet_levelstats` table, ignoring.",current_level); + ++count; // make result loading percent "expected" correct in case disabled detail mode for example. + } continue; } else if(current_level < 1) @@ -2242,7 +2245,10 @@ void ObjectMgr::LoadPlayerInfo() if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum sLog.outErrorDb("Wrong (> %u) level %u in `player_classlevelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); else + { sLog.outDetail("Unused (> MaxPlayerLevel in Trinityd.conf) level %u in `player_classlevelstats` table, ignoring.",current_level); + ++count; // make result loading percent "expected" correct in case disabled detail mode for example. + } continue; } @@ -2337,7 +2343,10 @@ void ObjectMgr::LoadPlayerInfo() if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum sLog.outErrorDb("Wrong (> %u) level %u in `player_levelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); else + { sLog.outDetail("Unused (> MaxPlayerLevel in Trinityd.conf) level %u in `player_levelstats` table, ignoring.",current_level); + ++count; // make result loading percent "expected" correct in case disabled detail mode for example. + } continue; } @@ -2445,7 +2454,10 @@ void ObjectMgr::LoadPlayerInfo() if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum sLog.outErrorDb("Wrong (> %u) level %u in `player_xp_for_level` table, ignoring.", STRONG_MAX_LEVEL,current_level); else + { sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `player_xp_for_levels` table, ignoring.",current_level); + ++count; // make result loading percent "expected" correct in case disabled detail mode for example. + } continue; } //PlayerXPperLevel @@ -3369,14 +3381,15 @@ void ObjectMgr::LoadQuests() if(qinfo->NextQuestInChain) { - if(mQuestTemplates.find(qinfo->NextQuestInChain) == mQuestTemplates.end()) + QuestMap::iterator qNextItr = mQuestTemplates.find(qinfo->NextQuestInChain); + if(qNextItr == mQuestTemplates.end()) { sLog.outErrorDb("Quest %u has `NextQuestInChain` = %u but quest %u does not exist, quest chain will not work.", qinfo->GetQuestId(),qinfo->NextQuestInChain ,qinfo->NextQuestInChain ); qinfo->NextQuestInChain = 0; } else - mQuestTemplates[qinfo->NextQuestInChain]->prevChainQuests.push_back(qinfo->GetQuestId()); + qNextItr->second->prevChainQuests.push_back(qinfo->GetQuestId()); } // fill additional data stores @@ -3394,14 +3407,15 @@ void ObjectMgr::LoadQuests() if(qinfo->NextQuestId) { - if (mQuestTemplates.find(abs(qinfo->GetNextQuestId())) == mQuestTemplates.end()) + QuestMap::iterator qNextItr = mQuestTemplates.find(abs(qinfo->GetNextQuestId())); + if (qNextItr == mQuestTemplates.end()) { sLog.outErrorDb("Quest %d has NextQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetNextQuestId()); } else { int32 signedQuestId = qinfo->NextQuestId < 0 ? -int32(qinfo->GetQuestId()) : int32(qinfo->GetQuestId()); - mQuestTemplates[abs(qinfo->GetNextQuestId())]->prevQuests.push_back(signedQuestId); + qNextItr->second->prevQuests.push_back(signedQuestId); } } @@ -5159,7 +5173,8 @@ void ObjectMgr::LoadAccessRequirements() if(ar.heroicQuest) { - if(!mQuestTemplates[ar.heroicQuest]) + QuestMap::iterator qReqItr = mQuestTemplates.find(ar.heroicQuest); + if(qReqItr != mQuestTemplates.end()) { sLog.outErrorDb("Required Heroic Quest %u not exist for trigger %u, remove heroic quest done requirement.",ar.heroicQuest,requiremt_ID); ar.heroicQuest = 0; @@ -5168,7 +5183,8 @@ void ObjectMgr::LoadAccessRequirements() if(ar.quest) { - if(!mQuestTemplates[ar.quest]) + QuestMap::iterator qReqItr = mQuestTemplates.find(ar.quest); + if(qReqItr != mQuestTemplates.end()) { sLog.outErrorDb("Required Quest %u not exist for trigger %u, remove quest done requirement.",ar.quest,requiremt_ID); ar.quest = 0; diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index b5dbce89089..2cc049ebd84 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -46,16 +46,16 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) // used also for charmed creature Unit* pet= ObjectAccessor::GetUnit(*_player, guid1); - sLog.outDetail("HandlePetAction.Pet %u flag is %u, spellid is %u, target %u.\n", uint32(GUID_LOPART(guid1)), flag, spellid, uint32(GUID_LOPART(guid2)) ); + sLog.outDetail("HandlePetAction.Pet %u flag is %u, spellid is %u, target %u.", uint32(GUID_LOPART(guid1)), flag, spellid, uint32(GUID_LOPART(guid2)) ); if(!pet) { - sLog.outError( "Pet %u not exist.\n", uint32(GUID_LOPART(guid1)) ); + sLog.outError( "Pet %u not exist.", uint32(GUID_LOPART(guid1)) ); return; } if(pet != GetPlayer()->GetPet() && pet != GetPlayer()->GetCharm()) { - sLog.outError("HandlePetAction.Pet %u isn't pet of player %s.\n", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName() ); + sLog.outError("HandlePetAction.Pet %u isn't pet of player %s.", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName() ); return; } @@ -159,7 +159,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) _player->Uncharm(); break; default: - sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.\n", flag, spellid); + sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", flag, spellid); } break; case ACT_REACTION: // 0x600 @@ -188,7 +188,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid ); if(!spellInfo) { - sLog.outError("WORLD: unknown PET spell id %i\n", spellid); + sLog.outError("WORLD: unknown PET spell id %i", spellid); return; } @@ -278,7 +278,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) break; } default: - sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.\n", flag, spellid); + sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", flag, spellid); } } @@ -286,7 +286,7 @@ void WorldSession::HandlePetNameQuery( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,4+8); - sLog.outDetail( "HandlePetNameQuery. CMSG_PET_NAME_QUERY\n" ); + sLog.outDetail( "HandlePetNameQuery. CMSG_PET_NAME_QUERY" ); uint32 petnumber; uint64 petguid; @@ -326,7 +326,7 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data, 8+4+2+2); - sLog.outDetail( "HandlePetSetAction. CMSG_PET_SET_ACTION\n" ); + sLog.outDetail( "HandlePetSetAction. CMSG_PET_SET_ACTION" ); uint64 petguid; uint32 position; @@ -345,7 +345,7 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data ) if(!pet || (pet != _player->GetPet() && pet != _player->GetCharm())) { - sLog.outError( "HandlePetSetAction: Unknown pet or pet owner.\n" ); + sLog.outError( "HandlePetSetAction: Unknown pet or pet owner." ); return; } @@ -363,7 +363,7 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data ) recv_data >> spell_id; recv_data >> act_state; - sLog.outDetail( "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X\n", _player->GetName(), position, spell_id, act_state); + sLog.outDetail( "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X", _player->GetName(), position, spell_id, act_state); //if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add if(!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE) && spell_id && !pet->HasSpell(spell_id))) @@ -395,7 +395,7 @@ void WorldSession::HandlePetRename( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data, 8+1); - sLog.outDetail( "HandlePetRename. CMSG_PET_RENAME\n" ); + sLog.outDetail( "HandlePetRename. CMSG_PET_RENAME" ); uint64 petguid; uint8 isdeclined; @@ -511,7 +511,7 @@ void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket) if(guid != pet->GetGUID()) { - sLog.outError( "HandlePetUnlearnOpcode.Pet %u isn't pet of player %s .\n", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); + sLog.outError( "HandlePetUnlearnOpcode.Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); return; } @@ -545,7 +545,7 @@ void WorldSession::HandlePetSpellAutocastOpcode( WorldPacket& recvPacket ) if(!pet || (pet != _player->GetPet() && pet != _player->GetCharm())) { - sLog.outError( "HandlePetSpellAutocastOpcode.Pet %u isn't pet of player %s .\n", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); + sLog.outError( "HandlePetSpellAutocastOpcode.Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); return; } @@ -595,7 +595,7 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) if(!caster || (caster != _player->GetPet() && caster != _player->GetCharm())) { - sLog.outError( "HandlePetCastSpellOpcode: Pet %u isn't pet of player %s .\n", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); + sLog.outError( "HandlePetCastSpellOpcode: Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); return; } @@ -605,7 +605,7 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid); if(!spellInfo) { - sLog.outError("WORLD: unknown PET spell id %i\n", spellid); + sLog.outError("WORLD: unknown PET spell id %i", spellid); return; } @@ -803,5 +803,5 @@ void WorldSession::HandlePetLearnTalent( WorldPacket & recv_data ) // learn! (other talent ranks will unlearned at learning) pet->learnSpell(spellid); - sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talent_id, requested_rank, spellid); + sLog.outDetail("TalentID: %u Rank: %u Spell: %u", talent_id, requested_rank, spellid); } diff --git a/src/game/PetitionsHandler.cpp b/src/game/PetitionsHandler.cpp index df9761a7f53..2b225283749 100644 --- a/src/game/PetitionsHandler.cpp +++ b/src/game/PetitionsHandler.cpp @@ -826,7 +826,7 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data) if(type == 9) // create guild { Guild* guild = new Guild; - if(!guild->create(_player->GetGUID(), name)) + if(!guild->create(_player, name)) { delete guild; delete result; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index b73c548e56c..7ad1be5a478 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -29,6 +29,7 @@ #include "WorldSession.h" #include "UpdateMask.h" #include "Player.h" +#include "Vehicle.h" #include "SkillDiscovery.h" #include "QuestDef.h" #include "GossipDef.h" @@ -354,8 +355,11 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this) m_regenTimer = 0; m_weaponChangeTimer = 0; - m_breathTimer = 0; - m_isunderwater = UNDERWATER_NONE; + for (int i=0; i<MAX_TIMERS; i++) + m_MirrorTimer[i] = DISABLED_MIRROR_TIMER; + + m_MirrorTimerFlags = UNDERWATER_NONE; + m_MirrorTimerFlagsLast = UNDERWATER_NONE; m_isInWater = false; m_drunkTimer = 0; m_drunk = 0; @@ -855,25 +859,14 @@ bool Player::StoreNewItemInBestSlots(uint32 titem_id, uint32 titem_amount) return false; } -void Player::StartMirrorTimer(MirrorTimerType Type, uint32 MaxValue) -{ - uint32 BreathRegen = (uint32)-1; - - WorldPacket data(SMSG_START_MIRROR_TIMER, (21)); - data << (uint32)Type; - data << MaxValue; - data << MaxValue; - data << BreathRegen; - data << (uint8)0; - data << (uint32)0; // spell id - GetSession()->SendPacket(&data); -} - -void Player::ModifyMirrorTimer(MirrorTimerType Type, uint32 MaxValue, uint32 CurrentValue, uint32 Regen) +void Player::SendMirrorTimer(MirrorTimerType Type, uint32 MaxValue, uint32 CurrentValue, int32 Regen) { - if(Type==BREATH_TIMER) - m_breathTimer = ((MaxValue + 1*IN_MILISECONDS) - CurrentValue) / Regen; - + if (MaxValue == DISABLED_MIRROR_TIMER) + { + if (CurrentValue!=DISABLED_MIRROR_TIMER) + StopMirrorTimer(Type); + return; + } WorldPacket data(SMSG_START_MIRROR_TIMER, (21)); data << (uint32)Type; data << CurrentValue; @@ -886,9 +879,7 @@ void Player::ModifyMirrorTimer(MirrorTimerType Type, uint32 MaxValue, uint32 Cur void Player::StopMirrorTimer(MirrorTimerType Type) { - if(Type==BREATH_TIMER) - m_breathTimer = 0; - + m_MirrorTimer[Type] = DISABLED_MIRROR_TIMER; WorldPacket data(SMSG_STOP_MIRROR_TIMER, 4); data << (uint32)Type; GetSession()->SendPacket( &data ); @@ -899,12 +890,22 @@ void Player::EnvironmentalDamage(uint64 guid, EnviromentalDamage type, uint32 da if(!isAlive() || isGameMaster()) return; + // Absorb, resist some environmental damage type + uint32 absorb = 0; + uint32 resist = 0; + if (type == DAMAGE_LAVA) + CalcAbsorbResist(this, SPELL_SCHOOL_MASK_FIRE, DIRECT_DAMAGE, damage, &absorb, &resist); + else if (type == DAMAGE_SLIME) + CalcAbsorbResist(this, SPELL_SCHOOL_MASK_NATURE, DIRECT_DAMAGE, damage, &absorb, &resist); + + damage-=absorb+resist; + WorldPacket data(SMSG_ENVIRONMENTALDAMAGELOG, (21)); data << (uint64)guid; data << (uint8)(type!=DAMAGE_FALL_TO_VOID ? type : DAMAGE_FALL); data << (uint32)damage; - data << (uint32)0; - data << (uint32)0; + data << (uint32)absorb; // absorb + data << (uint32)resist; // resist SendMessageToSet(&data, true); DealDamage(this, damage, NULL, SELF_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); @@ -924,96 +925,153 @@ void Player::EnvironmentalDamage(uint64 guid, EnviromentalDamage type, uint32 da } } -void Player::HandleDrowning() +int32 Player::getMaxTimer(MirrorTimerType timer) { - if(!(m_isunderwater&~UNDERWATER_INLAVA)) - return; - - //if player is GM, have waterbreath, is dead or if breathing is disabled then return - if(isGameMaster() || !isAlive() || HasAuraType(SPELL_AURA_WATER_BREATHING) || GetSession()->GetSecurity() >= sWorld.getConfig(CONFIG_DISABLE_BREATHING)) + switch (timer) { - StopMirrorTimer(BREATH_TIMER); - // drop every flag _except_ LAVA - otherwise waterbreathing will prevent lava damage - m_isunderwater &= UNDERWATER_INLAVA; - return; + case FATIGUE_TIMER: + return MINUTE*IN_MILISECONDS; + case BREATH_TIMER: + { + if (!isAlive() || HasAuraType(SPELL_AURA_WATER_BREATHING) || GetSession()->GetSecurity() >= sWorld.getConfig(CONFIG_DISABLE_BREATHING)) + return DISABLED_MIRROR_TIMER; + int32 UnderWaterTime = 3*MINUTE*IN_MILISECONDS; + AuraList const& mModWaterBreathing = GetAurasByType(SPELL_AURA_MOD_WATER_BREATHING); + for(AuraList::const_iterator i = mModWaterBreathing.begin(); i != mModWaterBreathing.end(); ++i) + UnderWaterTime = uint32(UnderWaterTime * (100.0f + (*i)->GetModifier()->m_amount) / 100.0f); + return UnderWaterTime; + } + case FIRE_TIMER: + { + if (!isAlive()) + return DISABLED_MIRROR_TIMER; + return 1*IN_MILISECONDS; + } + default: + return 0; } + return 0; +} - uint32 UnderWaterTime = 3*MINUTE*IN_MILISECONDS; // default duration +void Player::UpdateMirrorTimers() +{ + // Desync flags for update on next HandleDrowning + if (m_MirrorTimerFlags) + m_MirrorTimerFlagsLast = ~m_MirrorTimerFlags; +} - AuraList const& mModWaterBreathing = GetAurasByType(SPELL_AURA_MOD_WATER_BREATHING); - for(AuraList::const_iterator i = mModWaterBreathing.begin(); i != mModWaterBreathing.end(); ++i) - UnderWaterTime = uint32(UnderWaterTime * (100.0f + (*i)->GetModifier()->m_amount) / 100.0f); +void Player::HandleDrowning(uint32 time_diff) +{ + if (!m_MirrorTimerFlags) + return; - if ((m_isunderwater & UNDERWATER_INWATER) && !(m_isunderwater & UNDERWATER_INLAVA) && isAlive()) + // In water + if (m_MirrorTimerFlags & UNDERWATER_INWATER) { - //single trigger timer - if (!(m_isunderwater & UNDERWATER_WATER_TRIGGER)) - { - m_isunderwater|= UNDERWATER_WATER_TRIGGER; - m_breathTimer = UnderWaterTime + 1*IN_MILISECONDS; - } - //single trigger "show Breathbar" - if ( m_breathTimer <= UnderWaterTime && !(m_isunderwater & UNDERWATER_WATER_BREATHB)) + // Breath timer not activated - activate it + if (m_MirrorTimer[BREATH_TIMER] == DISABLED_MIRROR_TIMER) { - m_isunderwater|= UNDERWATER_WATER_BREATHB; - StartMirrorTimer(BREATH_TIMER, UnderWaterTime); + m_MirrorTimer[BREATH_TIMER] = getMaxTimer(BREATH_TIMER); + SendMirrorTimer(BREATH_TIMER, m_MirrorTimer[BREATH_TIMER], m_MirrorTimer[BREATH_TIMER], -1); } - //continuous trigger drowning "Damage" - if ((m_breathTimer == 0) && (m_isunderwater & UNDERWATER_INWATER)) + else // If activated - do tick { - //TODO: Check this formula - uint64 guid = GetGUID(); - uint32 damage = GetMaxHealth() / 5 + urand(0, getLevel()-1); - - EnvironmentalDamage(guid, DAMAGE_DROWNING,damage); - m_breathTimer = 2000; + m_MirrorTimer[BREATH_TIMER]-=time_diff; + // Timer limit - need deal damage + if (m_MirrorTimer[BREATH_TIMER] < 0) + { + m_MirrorTimer[BREATH_TIMER]+= 1*IN_MILISECONDS; + // Calculate and deal damage + // TODO: Check this formula + uint32 damage = GetMaxHealth() / 5 + urand(0, getLevel()-1); + EnvironmentalDamage(GetGUID(), DAMAGE_DROWNING, damage); + } + else if (!(m_MirrorTimerFlagsLast & UNDERWATER_INWATER)) // Update time in client if need + SendMirrorTimer(BREATH_TIMER, getMaxTimer(BREATH_TIMER), m_MirrorTimer[BREATH_TIMER], -1); } } - //single trigger retract bar - else if (!(m_isunderwater & UNDERWATER_INWATER) && (m_isunderwater & UNDERWATER_WATER_TRIGGER) && (m_breathTimer > 0) && isAlive()) + else if (m_MirrorTimer[BREATH_TIMER] != DISABLED_MIRROR_TIMER) // Regen timer { - uint32 BreathRegen = 10; - // m_breathTimer will be reduced in ModifyMirrorTimer - ModifyMirrorTimer(BREATH_TIMER, UnderWaterTime, m_breathTimer,BreathRegen); - m_isunderwater = UNDERWATER_WATER_BREATHB_RETRACTING; + int32 UnderWaterTime = getMaxTimer(BREATH_TIMER); + // Need breath regen + m_MirrorTimer[BREATH_TIMER]+=10*time_diff; + if (m_MirrorTimer[BREATH_TIMER] >= UnderWaterTime || !isAlive()) + StopMirrorTimer(BREATH_TIMER); + else if (m_MirrorTimerFlagsLast & UNDERWATER_INWATER) + SendMirrorTimer(BREATH_TIMER, UnderWaterTime, m_MirrorTimer[BREATH_TIMER], 10); } - //remove bar - else if ((m_breathTimer < 50) && !(m_isunderwater & UNDERWATER_INWATER) && (m_isunderwater == UNDERWATER_WATER_BREATHB_RETRACTING)) - { - StopMirrorTimer(BREATH_TIMER); - m_isunderwater = UNDERWATER_NONE; - } -} -void Player::HandleLava() -{ - if ((m_isunderwater & UNDERWATER_INLAVA) && isAlive()) + // In dark water + if (m_MirrorTimerFlags & UNDERWARER_INDARKWATER) { - /* - * arrai: how is this supposed to work? UNDERWATER_INLAVA is always set in this scope! - // Single trigger Set BreathTimer - if (!(m_isunderwater & UNDERWATER_INLAVA)) + // Fatigue timer not activated - activate it + if (m_MirrorTimer[FATIGUE_TIMER] == DISABLED_MIRROR_TIMER) { - m_isunderwater|= UNDERWATER_WATER_BREATHB; - m_breathTimer = 1*IN_MILISECONDS; + m_MirrorTimer[FATIGUE_TIMER] = getMaxTimer(FATIGUE_TIMER); + SendMirrorTimer(FATIGUE_TIMER, m_MirrorTimer[FATIGUE_TIMER], m_MirrorTimer[FATIGUE_TIMER], -1); } - */ - // Reset BreathTimer and still in the lava - if (!m_breathTimer) + else { - uint64 guid = GetGUID(); - uint32 damage = urand(600, 700); // TODO: Get more detailed information about lava damage - - EnvironmentalDamage(guid, DAMAGE_LAVA, damage); - - m_breathTimer = 1*IN_MILISECONDS; + m_MirrorTimer[FATIGUE_TIMER]-=time_diff; + // Timer limit - need deal damage or teleport ghost to graveyard + if (m_MirrorTimer[FATIGUE_TIMER] < 0) + { + m_MirrorTimer[FATIGUE_TIMER]+= 1*IN_MILISECONDS; + if (isAlive()) // Calculate and deal damage + { + uint32 damage = GetMaxHealth() / 5 + urand(0, getLevel()-1); + EnvironmentalDamage(GetGUID(), DAMAGE_EXHAUSTED, damage); + } + else if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) // Teleport ghost to graveyard + RepopAtGraveyard(); + } + else if (!(m_MirrorTimerFlagsLast & UNDERWARER_INDARKWATER)) + SendMirrorTimer(FATIGUE_TIMER, getMaxTimer(FATIGUE_TIMER), m_MirrorTimer[FATIGUE_TIMER], -1); } } - else if (!isAlive()) // Disable breath timer and reset underwater flags + else if (m_MirrorTimer[FATIGUE_TIMER] != DISABLED_MIRROR_TIMER) // Regen timer { - m_breathTimer = 0; - m_isunderwater = UNDERWATER_NONE; + int32 DarkWaterTime = getMaxTimer(FATIGUE_TIMER); + m_MirrorTimer[FATIGUE_TIMER]+=10*time_diff; + if (m_MirrorTimer[FATIGUE_TIMER] >= DarkWaterTime || !isAlive()) + StopMirrorTimer(FATIGUE_TIMER); + else if (m_MirrorTimerFlagsLast & UNDERWARER_INDARKWATER) + SendMirrorTimer(FATIGUE_TIMER, DarkWaterTime, m_MirrorTimer[FATIGUE_TIMER], 10); } + + if (m_MirrorTimerFlags & (UNDERWATER_INLAVA|UNDERWATER_INSLIME)) + { + // Breath timer not activated - activate it + if (m_MirrorTimer[FIRE_TIMER] == DISABLED_MIRROR_TIMER) + m_MirrorTimer[FIRE_TIMER] = getMaxTimer(FIRE_TIMER); + else + { + m_MirrorTimer[FIRE_TIMER]-=time_diff; + if (m_MirrorTimer[FIRE_TIMER] < 0) + { + m_MirrorTimer[FIRE_TIMER]+= 1*IN_MILISECONDS; + // Calculate and deal damage + // TODO: Check this formula + uint32 damage = urand(600, 700); + if (m_MirrorTimerFlags&UNDERWATER_INLAVA) + EnvironmentalDamage(GetGUID(), DAMAGE_LAVA, damage); + else + EnvironmentalDamage(GetGUID(), DAMAGE_SLIME, damage); + } + } + } + else + m_MirrorTimer[FIRE_TIMER] = DISABLED_MIRROR_TIMER; + + // Recheck timers flag + m_MirrorTimerFlags&=~UNDERWATER_EXIST_TIMERS; + for (int i = 0; i< MAX_TIMERS; ++i) + if (m_MirrorTimer[i]!=DISABLED_MIRROR_TIMER) + { + m_MirrorTimerFlags|=UNDERWATER_EXIST_TIMERS; + break; + } + m_MirrorTimerFlagsLast = m_MirrorTimerFlags; } ///The player sobers by 256 every 10 seconds @@ -1278,21 +1336,8 @@ void Player::Update( uint32 p_time ) } } - //Breathtimer - if(m_breathTimer > 0) - { - if(p_time >= m_breathTimer) - m_breathTimer = 0; - else - m_breathTimer -= p_time; - - } - //Handle Water/drowning - HandleDrowning(); - - //Handle lava - HandleLava(); + HandleDrowning(p_time); //Handle detect stealth players if (m_DetectInvTimer > 0) @@ -14656,7 +14701,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) SetBGTeam(bgteam); //join player to battleground group - currentBg->PlayerRelogin(this); + currentBg->EventPlayerLoggedIn(this, GetGUID()); currentBg->AddOrSetPlayerToCorrectBgGroup(this, GetGUID(), bgteam); SetInviteForBattleGroundQueueType(bgQueueTypeId,currentBg->GetInstanceID()); @@ -16114,7 +16159,7 @@ bool Player::_LoadHomeBind(QueryResult *result) CharacterDatabase.PExecute("INSERT INTO character_homebind (guid,map,zone,position_x,position_y,position_z) VALUES ('%u', '%u', '%u', '%f', '%f', '%f')", GetGUIDLow(), m_homebindMapId, (uint32)m_homebindZoneId, m_homebindX, m_homebindY, m_homebindZ); } - DEBUG_LOG("Setting player home position: mapid is: %u, zoneid is %u, X is %f, Y is %f, Z is %f\n", + DEBUG_LOG("Setting player home position: mapid is: %u, zoneid is %u, X is %f, Y is %f, Z is %f", m_homebindMapId, m_homebindZoneId, m_homebindX, m_homebindY, m_homebindZ); return true; @@ -19982,21 +20027,48 @@ PartyResult Player::CanUninviteFromGroup() const void Player::UpdateUnderwaterState( Map* m, float x, float y, float z ) { - float water_z = m->GetWaterLevel(x,y); - float terrain_z = m->GetHeight(x,y,z, false); // use .map base surface height - uint8 flag1 = m->GetTerrainType(x,y); + LiquidData liquid_status; + ZLiquidStatus res = m->getLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &liquid_status); + if (!res) + { + m_MirrorTimerFlags &= ~(UNDERWATER_INWATER|UNDERWATER_INLAVA|UNDERWATER_INSLIME|UNDERWARER_INDARKWATER); + // Small hack for enable breath in WMO + if (IsInWater()) + m_MirrorTimerFlags|=UNDERWATER_INWATER; + return; + } - //!Underwater check, not in water if underground or above water level - take UC royal quater for example - if (terrain_z <= INVALID_HEIGHT || z < (terrain_z-2) || z > (water_z - 2) ) - m_isunderwater &= ~UNDERWATER_INWATER; - else if ((z < (water_z - 2)) && (flag1 & 0x01)) - m_isunderwater |= UNDERWATER_INWATER; + // All liquids type - check under water position + if (liquid_status.type&(MAP_LIQUID_TYPE_WATER|MAP_LIQUID_TYPE_OCEAN|MAP_LIQUID_TYPE_MAGMA|MAP_LIQUID_TYPE_SLIME)) + { + if ( res & LIQUID_MAP_UNDER_WATER) + m_MirrorTimerFlags |= UNDERWATER_INWATER; + else + m_MirrorTimerFlags &= ~UNDERWATER_INWATER; + } - //!in lava check, anywhere under lava level - if ((terrain_z <= INVALID_HEIGHT || z < (terrain_z - 0)) && (flag1 == 0x00) && IsInWater()) - m_isunderwater |= UNDERWATER_INLAVA; + // Allow travel in dark water on taxi or transport + if (liquid_status.type & MAP_LIQUID_TYPE_DARK_WATER && !isInFlight() && !(GetUnitMovementFlags()&MOVEMENTFLAG_ONTRANSPORT)) + m_MirrorTimerFlags |= UNDERWARER_INDARKWATER; else - m_isunderwater &= ~UNDERWATER_INLAVA; + m_MirrorTimerFlags &= ~UNDERWARER_INDARKWATER; + + // in lava check, anywhere in lava level + if (liquid_status.type&MAP_LIQUID_TYPE_MAGMA) + { + if (res & (LIQUID_MAP_UNDER_WATER|LIQUID_MAP_IN_WATER|LIQUID_MAP_WATER_WALK)) + m_MirrorTimerFlags |= UNDERWATER_INLAVA; + else + m_MirrorTimerFlags &= ~UNDERWATER_INLAVA; + } + // in slime check, anywhere in slime level + if (liquid_status.type&MAP_LIQUID_TYPE_SLIME) + { + if (res & (LIQUID_MAP_UNDER_WATER|LIQUID_MAP_IN_WATER|LIQUID_MAP_WATER_WALK)) + m_MirrorTimerFlags |= UNDERWATER_INSLIME; + else + m_MirrorTimerFlags &= ~UNDERWATER_INSLIME; + } } void Player::SetCanParry( bool value ) @@ -20103,15 +20175,23 @@ void Player::SetFarsightTarget(WorldObject* obj) SetFarSightGUID(obj->GetGUID()); } -bool Player::isAllowUseBattleGroundObject() +bool Player::CanUseBattleGroundObject() { - return ( //InBattleGround() && // in battleground - not need, check in other cases - !IsMounted() && // not mounted - !isTotalImmunity() && // not totally immuned - !HasStealthAura() && // not stealthed - !HasInvisibilityAura() && // not invisible - !HasAura(SPELL_RECENTLY_DROPPED_FLAG, 0) && // can't pickup - isAlive() // live player + return ( //InBattleGround() && // in battleground - not need, check in other cases + //!IsMounted() && - not correct, player is dismounted when he clicks on flag + !HasStealthAura() && // not stealthed + !HasInvisibilityAura() && // not invisible + !HasAura(SPELL_RECENTLY_DROPPED_FLAG, 0) && // can't pickup + //TODO player cannot use object when he is invulnerable (immune) - (ice block, divine shield, divine protection, divine intervention ...) + isAlive() // live player + ); +} + +bool Player::CanCaptureTowerPoint() +{ + return ( !HasStealthAura() && // not stealthed + !HasInvisibilityAura() && // not invisible + isAlive() // live player ); } @@ -20638,4 +20718,4 @@ void Player::HandleFall(MovementInfo const& movementInfo) void Player::UpdateAchievementCriteria( AchievementCriteriaTypes type, uint32 miscvalue1/*=0*/, uint32 miscvalue2/*=0*/, Unit *unit/*=NULL*/, uint32 time/*=0*/ ) { GetAchievementMgr().UpdateAchievementCriteria(type, miscvalue1,miscvalue2,unit,time); -}
\ No newline at end of file +} diff --git a/src/game/Player.h b/src/game/Player.h index 932961c79c6..196c3e6fcfa 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -72,10 +72,11 @@ enum PlayerUnderwaterState { UNDERWATER_NONE = 0x00, UNDERWATER_INWATER = 0x01, // terrain type is water and player is afflicted by it - UNDERWATER_WATER_TRIGGER = 0x02, // m_breathTimer has been initialized - UNDERWATER_WATER_BREATHB = 0x04, // breathbar has been send to client - UNDERWATER_WATER_BREATHB_RETRACTING = 0x10, // breathbar is currently refilling - the player is above water level - UNDERWATER_INLAVA = 0x80 // terrain type is lava and player is afflicted by it + UNDERWATER_INLAVA = 0x02, // terrain type is lava and player is afflicted by it + UNDERWATER_INSLIME = 0x04, // terrain type is lava and player is afflicted by it + UNDERWARER_INDARKWATER = 0x08, // terrain type is dark water and player is afflicted by it + + UNDERWATER_EXIST_TIMERS = 0x10 }; enum PlayerSpellState @@ -501,6 +502,8 @@ enum MirrorTimerType BREATH_TIMER = 1, FIRE_TIMER = 2 }; +#define MAX_TIMERS 3 +#define DISABLED_MIRROR_TIMER -1 // 2^n values enum PlayerExtraFlags @@ -1722,6 +1725,7 @@ class TRINITY_DLL_SPEC Player : public Unit uint32 DurabilityRepairAll(bool cost, float discountMod, bool guildBank); uint32 DurabilityRepair(uint16 pos, bool cost, float discountMod, bool guildBank); + void UpdateMirrorTimers(); void StopMirrorTimers() { StopMirrorTimer(FATIGUE_TIMER); @@ -1984,8 +1988,9 @@ class TRINITY_DLL_SPEC Player : public Unit void ClearAfkReports() { m_bgAfkReporter.clear(); } bool GetBGAccessByLevel(BattleGroundTypeId bgTypeId) const; - bool isAllowUseBattleGroundObject(); bool isTotalImmunity(); + bool CanUseBattleGroundObject(); + bool CanCaptureTowerPoint(); /*********************************************************/ /*** OUTDOOR PVP SYSTEM ***/ @@ -2039,7 +2044,6 @@ class TRINITY_DLL_SPEC Player : public Unit bool IsFlying() const { return HasUnitMovementFlag(MOVEMENTFLAG_FLYING); } bool IsAllowUseFlyMountsHere() const; - void HandleDrowning(); void HandleFallUnderMap(); void SetClientControl(Unit* target, uint8 allowMove); @@ -2267,12 +2271,14 @@ class TRINITY_DLL_SPEC Player : public Unit /*********************************************************/ /*** ENVIRONMENTAL SYSTEM ***/ /*********************************************************/ - void HandleLava(); void HandleSobering(); - void StartMirrorTimer(MirrorTimerType Type, uint32 MaxValue); - void ModifyMirrorTimer(MirrorTimerType Type, uint32 MaxValue, uint32 CurrentValue, uint32 Regen); + void SendMirrorTimer(MirrorTimerType Type, uint32 MaxValue, uint32 CurrentValue, int32 Regen); void StopMirrorTimer(MirrorTimerType Type); - uint8 m_isunderwater; + void HandleDrowning(uint32 time_diff); + int32 getMaxTimer(MirrorTimerType timer); + int32 m_MirrorTimer[MAX_TIMERS]; + uint8 m_MirrorTimerFlags; + uint8 m_MirrorTimerFlagsLast; bool m_isInWater; /*********************************************************/ @@ -2356,7 +2362,6 @@ class TRINITY_DLL_SPEC Player : public Unit bool m_DailyQuestChanged; time_t m_lastDailyQuestTime; - uint32 m_breathTimer; uint32 m_drunkTimer; uint16 m_drunk; uint32 m_weaponChangeTimer; diff --git a/src/game/SkillHandler.cpp b/src/game/SkillHandler.cpp index 154328af049..a6d854d25ce 100644 --- a/src/game/SkillHandler.cpp +++ b/src/game/SkillHandler.cpp @@ -128,7 +128,7 @@ void WorldSession::HandleLearnTalentOpcode( WorldPacket & recv_data ) // learn! (other talent ranks will unlearned at learning) GetPlayer( )->learnSpell(spellid,false); - sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talent_id, requested_rank, spellid); + sLog.outDetail("TalentID: %u Rank: %u Spell: %u", talent_id, requested_rank, spellid); // update free talent points GetPlayer()->SetFreeTalentPoints(CurTalentPoints - 1); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 54b2e582531..6c04104d619 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -3306,7 +3306,7 @@ uint8 Spell::CheckRuneCost(uint32 runeCostID) runeCost[i] = src->RuneCost[i]; } - runeCost[RUNE_DEATH] = 0; // calculated later + runeCost[RUNE_DEATH] = MAX_RUNES; // calculated later for(uint32 i = 0; i < MAX_RUNES; ++i) { @@ -3325,7 +3325,7 @@ uint8 Spell::CheckRuneCost(uint32 runeCostID) } } - if(runeCost[RUNE_DEATH] > 0) + if(runeCost[RUNE_DEATH] > MAX_RUNES) return SPELL_FAILED_NO_POWER; // not sure if result code is correct return 0; @@ -3483,7 +3483,7 @@ void Spell::HandleEffects(Unit *pUnitTarget,Item *pItemTarget,GameObject *pGOTar EffectEnchantItemTmp(i); else { - sLog.outError("SPELL: unknown effect %u spell id %u\n", + sLog.outError("SPELL: unknown effect %u spell id %u", eff, m_spellInfo->Id); } } @@ -4070,7 +4070,7 @@ uint8 Spell::CanCast(bool strict) // In BattleGround players can use only flags and banners if( ((Player*)m_caster)->InBattleGround() && - !((Player*)m_caster)->isAllowUseBattleGroundObject() ) + !((Player*)m_caster)->CanUseBattleGroundObject() ) return SPELL_FAILED_TRY_AGAIN; // get the lock entry diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index c38e22d8c97..e05711a2381 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -2338,15 +2338,9 @@ void Aura::HandleAuraHover(bool apply, bool Real) void Aura::HandleWaterBreathing(bool apply, bool Real) { - if(!apply && !m_target->HasAuraType(SPELL_AURA_WATER_BREATHING)) - { - // update for enable timer in case not moving target - if(m_target->GetTypeId()==TYPEID_PLAYER && m_target->IsInWorld()) - { - ((Player*)m_target)->UpdateUnderwaterState(m_target->GetMap(),m_target->GetPositionX(),m_target->GetPositionY(),m_target->GetPositionZ()); - ((Player*)m_target)->HandleDrowning(); - } - } + // update timers in client + if(m_target->GetTypeId()==TYPEID_PLAYER) + ((Player*)m_target)->UpdateMirrorTimers(); } void Aura::HandleAuraModShapeshift(bool apply, bool Real) @@ -2965,7 +2959,7 @@ void Aura::HandleModPossessPet(bool apply, bool Real) else pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); - ((Player*)caster)->SetFarSightGUID(apply ? pet->GetGUID() : NULL); + ((Player*)caster)->SetFarSightGUID(apply ? pet->GetGUID() : 0); ((Player*)caster)->SetCharm(apply ? pet : NULL); ((Player*)caster)->SetClientControl(pet, apply ? 1 : 0); @@ -3930,7 +3924,7 @@ void Aura::HandleAuraPeriodicDummy(bool apply, bool Real) { // Explosive Shot if (apply && !loading && caster) - m_modifier.m_amount +=caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 16 / 100; + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 16 / 100); break; } } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 1f143bacf88..8215d18d8a2 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -662,6 +662,11 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) int32 count = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget); damage += count * int32(averange * IN_MILISECONDS) / m_caster->GetAttackTime(BASE_ATTACK); } + // Shield of Righteousness + else if(m_spellInfo->SpellFamilyFlags&0x0010000000000000LL) + { + damage+=int32(m_caster->GetShieldBlockValue()); + } break; } } @@ -929,7 +934,7 @@ void Spell::EffectDummy(uint32 i) return; GameObject* Crystal_Prison = m_caster->SummonGameObject(179644, creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(), creatureTarget->GetOrientation(), 0, 0, 0, 0, creatureTarget->GetRespawnTime()-time(NULL)); - sLog.outDebug("SummonGameObject at SpellEfects.cpp EffectDummy for Spell 23019\n"); + sLog.outDebug("SummonGameObject at SpellEfects.cpp EffectDummy for Spell 23019"); creatureTarget->setDeathState(JUST_DIED); creatureTarget->RemoveCorpse(); @@ -1393,7 +1398,7 @@ void Spell::EffectDummy(uint32 i) if (m_spellInfo->SpellFamilyFlags[0] & 0x40000) { // In 303 exist spirit depend - uint32 spirit = m_caster->GetStat(STAT_SPIRIT); + uint32 spirit = uint32(m_caster->GetStat(STAT_SPIRIT)); switch (m_spellInfo->Id) { case 1454: damage+=spirit; break; @@ -1772,7 +1777,7 @@ void Spell::EffectDummy(uint32 i) if(!spellInfo) { - sLog.outError("WORLD: unknown spell id %i\n", spell_id); + sLog.outError("WORLD: unknown spell id %i", spell_id); return; } @@ -1919,7 +1924,7 @@ void Spell::EffectTriggerSpellWithValue(uint32 i) if(!spellInfo) { - sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id,triggered_spell_id); + sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id); return; } @@ -2168,26 +2173,85 @@ void Spell::EffectTeleportUnits(uint32 i) // If not exist data for dest location - return if(!m_targets.HasDest()) { - sLog.outError( "Spell::EffectTeleportUnits - does not have destination for spell ID %u\n", m_spellInfo->Id ); - return; - } - // Init dest coordinates - int32 mapid = m_targets.m_mapId; - if(mapid < 0) mapid = (int32)unitTarget->GetMapId(); - float x = m_targets.m_destX; - float y = m_targets.m_destY; - float z = m_targets.m_destZ; - float orientation = m_targets.getUnitTarget() ? m_targets.getUnitTarget()->GetOrientation() : unitTarget->GetOrientation(); - sLog.outDebug("Spell::EffectTeleportUnits - teleport unit to %u %f %f %f\n", mapid, x, y, z); - // Teleport - if(unitTarget->GetTypeId() == TYPEID_PLAYER) - ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0)); - else - { - MapManager::Instance().GetMap(mapid, m_caster)->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation); - WorldPacket data; - unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation); - unitTarget->SendMessageToSet(&data, false); + case TARGET_INNKEEPER_COORDINATES: + { + // Only players can teleport to innkeeper + if (unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + ((Player*)unitTarget)->TeleportTo(((Player*)unitTarget)->m_homebindMapId,((Player*)unitTarget)->m_homebindX,((Player*)unitTarget)->m_homebindY,((Player*)unitTarget)->m_homebindZ,unitTarget->GetOrientation(),unitTarget==m_caster ? TELE_TO_SPELL : 0); + return; + } + case TARGET_TABLE_X_Y_Z_COORDINATES: + { + // TODO: Only players can teleport? + if (unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id); + if(!st) + { + sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo->Id ); + return; + } + ((Player*)unitTarget)->TeleportTo(st->target_mapId,st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster ? TELE_TO_SPELL : 0); + break; + } + case TARGET_BEHIND_VICTIM: + { + // Get selected target for player (or victim for units) + Unit *pTarget = NULL; + if(m_caster->GetTypeId() == TYPEID_PLAYER) + pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection()); + else + pTarget = m_caster->getVictim(); + // No target present - return + if (!pTarget) + return; + // Init dest coordinates + uint32 mapid = m_caster->GetMapId(); + float x = m_targets.m_destX; + float y = m_targets.m_destY; + float z = m_targets.m_destZ; + float orientation = pTarget->GetOrientation(); + // Teleport + if(unitTarget->GetTypeId() == TYPEID_PLAYER) + ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0)); + else + { + m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation); + WorldPacket data; + unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation); + unitTarget->SendMessageToSet(&data, false); + } + return; + } + default: + { + // If not exist data for dest location - return + if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)) + { + sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id ); + return; + } + // Init dest coordinates + uint32 mapid = m_caster->GetMapId(); + float x = m_targets.m_destX; + float y = m_targets.m_destY; + float z = m_targets.m_destZ; + float orientation = unitTarget->GetOrientation(); + // Teleport + if(unitTarget->GetTypeId() == TYPEID_PLAYER) + ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0)); + else + { + m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation); + WorldPacket data; + unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation); + unitTarget->SendMessageToSet(&data, false); + } + return; + } +>>>>>>> 49353326cacc281efc169f4e4e8ccb517157ff23:src/game/SpellEffects.cpp } // post effects for TARGET_TABLE_X_Y_Z_COORDINATES @@ -3054,7 +3118,7 @@ void Spell::EffectOpenLock(uint32 /*i*/) if( goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune || goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK ) { - //isAllowUseBattleGroundObject() already called in CanCast() + //CanUseBattleGroundObject() already called in CanCast() // in battleground check if(BattleGround *bg = player->GetBattleGround()) { @@ -3066,7 +3130,7 @@ void Spell::EffectOpenLock(uint32 /*i*/) } else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND) { - //isAllowUseBattleGroundObject() already called in CanCast() + //CanUseBattleGroundObject() already called in CanCast() // in battleground check if(BattleGround *bg = player->GetBattleGround()) { @@ -4803,7 +4867,7 @@ void Spell::EffectScriptEffect(uint32 effIndex) unitTarget->CastSpell(unitTarget, 25863, false); else unitTarget->CastSpell(unitTarget, 26655, false); - break; + return; } // Piccolo of the Flaming Fire case 17512: @@ -4811,7 +4875,14 @@ void Spell::EffectScriptEffect(uint32 effIndex) if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE); - break; + return; + } + // Escape artist + case 20589: + { + m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT); + m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED); + return; } // Escape artist case 20589: @@ -6485,7 +6556,7 @@ void Spell::EffectTransmitted(uint32 effIndex) //pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() ); pGameObj->SetSpellId(m_spellInfo->Id); - DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n"); + DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted"); //m_caster->AddGameObject(pGameObj); //m_ObjToDel.push_back(pGameObj); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 51739d7fd95..5b44e218e0c 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -1127,7 +1127,7 @@ void Unit::CastCustomSpell(Unit* Victim,uint32 spellId, int32 const* bp0, int32 if(!spellInfo) { - sLog.outError("CastCustomSpell: unknown spell id %i\n", spellId); + sLog.outError("CastCustomSpell: unknown spell id %i", spellId); return; } @@ -6717,7 +6717,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB //else if (auraSpellInfo->Id==47300) // Dark Flame Aura else if (auraSpellInfo->Id==57345) // Darkmoon Card: Greatness { - uint32 stat = 0; + float stat = 0.0f; // strength if (GetStat(STAT_STRENGTH) > stat) { trigger_spell_id = 60229;stat = GetStat(STAT_STRENGTH); } // agility diff --git a/src/game/World.cpp b/src/game/World.cpp index aea3bff3cd1..91662e53152 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -23,7 +23,6 @@ */ #include "Common.h" -//#include "WorldSocket.h" #include "Database/DatabaseEnv.h" #include "Config/ConfigEnv.h" #include "SystemConfig.h" @@ -33,6 +32,7 @@ #include "WorldPacket.h" #include "Weather.h" #include "Player.h" +#include "Vehicle.h" #include "SkillExtraItems.h" #include "SkillDiscovery.h" #include "World.h" @@ -2548,129 +2548,102 @@ void World::SendGlobalMessage(WorldPacket *packet, WorldSession *self, uint32 te } } -void World::SendGlobalGMMessage(WorldPacket *packet, WorldSession *self, uint32 team) +namespace MaNGOS { - SessionMap::iterator itr; - for (itr = m_sessions.begin(); itr != m_sessions.end(); itr++) + class WorldWorldTextBuilder { - if (itr->second && - itr->second->GetPlayer() && - itr->second->GetPlayer()->IsInWorld() && - itr->second != self && - itr->second->GetSecurity() >SEC_PLAYER && - (team == 0 || itr->second->GetPlayer()->GetTeam() == team) ) - { - itr->second->SendPacket(packet); - } - } -} - -/// Send a System Message to all players (except self if mentioned) -void World::SendWorldText(int32 string_id, ...) -{ - std::vector<std::vector<WorldPacket*> > data_cache; // 0 = default, i => i-1 locale index + public: + typedef std::vector<WorldPacket*> WorldPacketList; + explicit WorldWorldTextBuilder(int32 textId, va_list* args = NULL) : i_textId(textId), i_args(args) {} + void operator()(WorldPacketList& data_list, int32 loc_idx) + { + char const* text = objmgr.GetMangosString(i_textId,loc_idx); - for(SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) - { - if(!itr->second || !itr->second->GetPlayer() || !itr->second->GetPlayer()->IsInWorld() ) - continue; + if(i_args) + { + // we need copy va_list before use or original va_list will corrupted + va_list ap; + va_copy(ap,*i_args); - uint32 loc_idx = itr->second->GetSessionDbLocaleIndex(); - uint32 cache_idx = loc_idx+1; + char str [2048]; + vsnprintf(str,2048,text, ap ); + va_end(ap); - std::vector<WorldPacket*>* data_list; + do_helper(data_list,&str[0]); + } + else + do_helper(data_list,(char*)text); + } + private: + char* lineFromMessage(char*& pos) { char* start = strtok(pos,"\n"); pos = NULL; return start; } + void do_helper(WorldPacketList& data_list, char* text) + { + char* pos = text; - // create if not cached yet - if(data_cache.size() < cache_idx+1 || data_cache[cache_idx].empty()) - { - if(data_cache.size() < cache_idx+1) - data_cache.resize(cache_idx+1); + while(char* line = lineFromMessage(pos)) + { + WorldPacket* data = new WorldPacket(); - data_list = &data_cache[cache_idx]; + uint32 lineLength = (line ? strlen(line) : 0) + 1; - char const* text = objmgr.GetTrinityString(string_id,loc_idx); + data->Initialize(SMSG_MESSAGECHAT, 100); // guess size + *data << uint8(CHAT_MSG_SYSTEM); + *data << uint32(LANG_UNIVERSAL); + *data << uint64(0); + *data << uint32(0); // can be chat msg group or something + *data << uint64(0); + *data << uint32(lineLength); + *data << line; + *data << uint8(0); - char buf[1000]; + data_list.push_back(data); + } + } - va_list argptr; - va_start( argptr, string_id ); - vsnprintf( buf,1000, text, argptr ); - va_end( argptr ); + int32 i_textId; + va_list* i_args; + }; +} // namespace MaNGOS - char* pos = &buf[0]; +/// Send a System Message to all players (except self if mentioned) +void World::SendWorldText(int32 string_id, ...) +{ + va_list ap; + va_start(ap, string_id); - while(char* line = ChatHandler::LineFromMessage(pos)) - { - WorldPacket* data = new WorldPacket(); - ChatHandler::FillMessageData(data, NULL, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, 0, line, NULL); - data_list->push_back(data); - } - } - else - data_list = &data_cache[cache_idx]; + MaNGOS::WorldWorldTextBuilder wt_builder(string_id, &ap); + MaNGOS::LocalizedPacketListDo<MaNGOS::WorldWorldTextBuilder> wt_do(wt_builder); + for(SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) + { + if(!itr->second || !itr->second->GetPlayer() || !itr->second->GetPlayer()->IsInWorld() ) + continue; - for(int i = 0; i < data_list->size(); ++i) - itr->second->SendPacket((*data_list)[i]); + wt_do(itr->second->GetPlayer()); } - // free memory - for(int i = 0; i < data_cache.size(); ++i) - for(int j = 0; j < data_cache[i].size(); ++j) - delete data_cache[i][j]; + va_end(ap); } +/// Send a System Message to all GMs (except self if mentioned) void World::SendGMText(int32 string_id, ...) { - std::vector<std::vector<WorldPacket*> > data_cache; // 0 = default, i => i-1 locale index + va_list ap; + va_start(ap, string_id); + MaNGOS::WorldWorldTextBuilder wt_builder(string_id, &ap); + MaNGOS::LocalizedPacketListDo<MaNGOS::WorldWorldTextBuilder> wt_do(wt_builder); for(SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) { if(!itr->second || !itr->second->GetPlayer() || !itr->second->GetPlayer()->IsInWorld() ) continue; - uint32 loc_idx = itr->second->GetSessionDbLocaleIndex(); - uint32 cache_idx = loc_idx+1; - - std::vector<WorldPacket*>* data_list; - - // create if not cached yet - if(data_cache.size() < cache_idx+1 || data_cache[cache_idx].empty()) - { - if(data_cache.size() < cache_idx+1) - data_cache.resize(cache_idx+1); - - data_list = &data_cache[cache_idx]; - - char const* text = objmgr.GetTrinityString(string_id,loc_idx); - - char buf[1000]; - - va_list argptr; - va_start( argptr, string_id ); - vsnprintf( buf,1000, text, argptr ); - va_end( argptr ); - - char* pos = &buf[0]; - - while(char* line = ChatHandler::LineFromMessage(pos)) - { - WorldPacket* data = new WorldPacket(); - ChatHandler::FillMessageData(data, NULL, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, 0, line, NULL); - data_list->push_back(data); - } - } - else - data_list = &data_cache[cache_idx]; + if(!itr->second->GetSecurity()) + continue; - for(int i = 0; i < data_list->size(); ++i) - if(itr->second->GetSecurity()>0) - itr->second->SendPacket((*data_list)[i]); + wt_do(itr->second->GetPlayer()); } - // free memory - for(int i = 0; i < data_cache.size(); ++i) - for(int j = 0; j < data_cache[i].size(); ++j) - delete data_cache[i][j]; + va_end(ap); } /// DEPRICATED, only for debug purpose. Send a System Message to all players (except self if mentioned) diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index 8e7c2595923..01459930788 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -304,7 +304,7 @@ void WorldSession::LogoutPlayer(bool Save) } //drop a flag if player is carrying it if(BattleGround *bg = _player->GetBattleGround()) - bg->EventPlayerDroppedFlag(_player); + bg->EventPlayerLoggedOut(_player); ///- Teleport to home if the player is in an invalid instance if(!_player->m_InstanceValid && !_player->isGameMaster()) diff --git a/src/game/WorldSocket.cpp b/src/game/WorldSocket.cpp index 6c94dbd8cb4..077c7a0d7e9 100644 --- a/src/game/WorldSocket.cpp +++ b/src/game/WorldSocket.cpp @@ -317,7 +317,7 @@ int WorldSocket::handle_input (ACE_HANDLE) } case 0: { - DEBUG_LOG ("WorldSocket::handle_input: Peer has closed connection\n"); + DEBUG_LOG ("WorldSocket::handle_input: Peer has closed connection"); errno = ECONNRESET; return -1; diff --git a/src/mangosd/WorldRunnable.cpp b/src/mangosd/WorldRunnable.cpp index 0fb24577e32..689b1d216a9 100644 --- a/src/mangosd/WorldRunnable.cpp +++ b/src/mangosd/WorldRunnable.cpp @@ -89,7 +89,7 @@ void WorldRunnable::run() sWorld.UpdateSessions( 1 ); // real players unload required UpdateSessions call // unload battleground templates before different singletons destroyed - sBattleGroundMgr.DeleteAlllBattleGrounds(); + sBattleGroundMgr.DeleteAllBattleGrounds(); sWorldSocketMgr->StopNetwork(); diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index b0562c95096..b2bc2d5f779 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -234,8 +234,9 @@ AddonChannel = 1 # 0 = Minimum; 1 = Error; 2 = Detail; 3 = Full/Debug # Default: 0 # -# LogFilter_TransportMoves +# LogFilter_AchievementUpdates # LogFilter_CreatureMoves +# LogFilter_TransportMoves # LogFilter_VisibilityChanges # Log filters # Default: 1 - not include with any log level @@ -304,8 +305,9 @@ LogTime = 0 LogFile = "Server.log" LogTimestamp = 0 LogFileLevel = 0 -LogFilter_TransportMoves = 1 +LogFilter_AchievementUpdates = 1 LogFilter_CreatureMoves = 1 +LogFilter_TransportMoves = 1 LogFilter_VisibilityChanges = 1 WorldLogFile = "" DBErrorLogFile = "db_errors.log" diff --git a/src/shared/Database/dbcfile.cpp b/src/shared/Database/dbcfile.cpp index c40c8b223e1..1de121bb17d 100644 --- a/src/shared/Database/dbcfile.cpp +++ b/src/shared/Database/dbcfile.cpp @@ -39,23 +39,35 @@ bool DBCFile::Load(const char *filename, const char *fmt) delete [] data; data=NULL; } + FILE * f=fopen(filename,"rb"); if(!f)return false; - fread(&header,4,1,f); // Number of records + if(fread(&header,4,1,f)!=1) // Number of records + return false; + EndianConvert(header); if(header!=0x43424457) - { - //printf("not dbc file"); return false; //'WDBC' - } - fread(&recordCount,4,1,f); // Number of records + + if(fread(&recordCount,4,1,f)!=1) // Number of records + return false; + EndianConvert(recordCount); - fread(&fieldCount,4,1,f); // Number of fields + + if(fread(&fieldCount,4,1,f)!=1) // Number of fields + return false; + EndianConvert(fieldCount); - fread(&recordSize,4,1,f); // Size of a record + + if(fread(&recordSize,4,1,f)!=1) // Size of a record + return false; + EndianConvert(recordSize); - fread(&stringSize,4,1,f); // String size + + if(fread(&stringSize,4,1,f)!=1) // String size + return false; + EndianConvert(stringSize); fieldsOffset = new uint32[fieldCount]; @@ -71,7 +83,10 @@ bool DBCFile::Load(const char *filename, const char *fmt) data = new unsigned char[recordSize*recordCount+stringSize]; stringTable = data + recordSize*recordCount; - fread(data,recordSize*recordCount+stringSize,1,f); + + if(fread(data,recordSize*recordCount+stringSize,1,f)!=1) + return false; + fclose(f); return true; } diff --git a/src/shared/Log.cpp b/src/shared/Log.cpp index c0f70f4790b..2d756f65159 100644 --- a/src/shared/Log.cpp +++ b/src/shared/Log.cpp @@ -245,6 +245,8 @@ void Log::Initialize() m_logFilter |= LOG_FILTER_CREATURE_MOVES; if(sConfig.GetBoolDefault("LogFilter_VisibilityChanges", true)) m_logFilter |= LOG_FILTER_VISIBILITY_CHANGES; + if(sConfig.GetBoolDefault("LogFilter_AchievementUpdates", true)) + m_logFilter |= LOG_FILTER_ACHIEVEMENT_UPDATES; // Char log settings m_charLog_Dump = sConfig.GetBoolDefault("CharLogDump", false); diff --git a/src/shared/Log.h b/src/shared/Log.h index b4344eac262..6913cc3c12c 100644 --- a/src/shared/Log.h +++ b/src/shared/Log.h @@ -31,7 +31,8 @@ enum LogFilters { LOG_FILTER_TRANSPORT_MOVES = 1, LOG_FILTER_CREATURE_MOVES = 2, - LOG_FILTER_VISIBILITY_CHANGES = 4 + LOG_FILTER_VISIBILITY_CHANGES = 4, + LOG_FILTER_ACHIEVEMENT_UPDATES= 8 }; enum Color diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 87863ccbe8e..eceadf30029 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 "7403" + #define REVISION_NR "7434" #endif // __REVISION_NR_H__ |