aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/framework/Platform/Define.h2
-rw-r--r--src/game/AchievementMgr.cpp60
-rw-r--r--src/game/ArenaTeam.cpp22
-rw-r--r--src/game/ArenaTeam.h1
-rw-r--r--src/game/BattleGround.cpp445
-rw-r--r--src/game/BattleGround.h32
-rw-r--r--src/game/BattleGroundAB.cpp118
-rw-r--r--src/game/BattleGroundAB.h30
-rw-r--r--src/game/BattleGroundAV.cpp8
-rw-r--r--src/game/BattleGroundBE.cpp16
-rw-r--r--src/game/BattleGroundEY.cpp117
-rw-r--r--src/game/BattleGroundEY.h5
-rw-r--r--src/game/BattleGroundHandler.cpp34
-rw-r--r--src/game/BattleGroundMgr.cpp57
-rw-r--r--src/game/BattleGroundMgr.h6
-rw-r--r--src/game/BattleGroundNA.cpp16
-rw-r--r--src/game/BattleGroundRL.cpp16
-rw-r--r--src/game/BattleGroundWS.cpp89
-rw-r--r--src/game/BattleGroundWS.h6
-rw-r--r--src/game/Chat.cpp31
-rw-r--r--src/game/Chat.h18
-rw-r--r--src/game/Creature.cpp4
-rw-r--r--src/game/Debugcmds.cpp1
-rw-r--r--src/game/GameObject.cpp4
-rw-r--r--src/game/GridNotifiers.h22
-rw-r--r--src/game/GridNotifiersImpl.h25
-rw-r--r--src/game/Guild.cpp36
-rw-r--r--src/game/Guild.h2
-rw-r--r--src/game/GuildHandler.cpp2
-rw-r--r--src/game/Language.h7
-rw-r--r--src/game/Level1.cpp2
-rw-r--r--src/game/Level2.cpp1584
-rw-r--r--src/game/Level3.cpp209
-rw-r--r--src/game/Map.cpp733
-rw-r--r--src/game/Map.h138
-rw-r--r--src/game/MovementHandler.cpp1
-rw-r--r--src/game/Object.cpp1
-rw-r--r--src/game/ObjectAccessor.cpp3
-rw-r--r--src/game/ObjectAccessor.h2
-rw-r--r--src/game/ObjectMgr.cpp28
-rw-r--r--src/game/PetHandler.cpp32
-rw-r--r--src/game/PetitionsHandler.cpp2
-rw-r--r--src/game/Player.cpp338
-rw-r--r--src/game/Player.h27
-rw-r--r--src/game/SkillHandler.cpp2
-rw-r--r--src/game/Spell.cpp8
-rw-r--r--src/game/SpellAuras.cpp16
-rw-r--r--src/game/SpellEffects.cpp129
-rw-r--r--src/game/Unit.cpp4
-rw-r--r--src/game/World.cpp165
-rw-r--r--src/game/WorldSession.cpp2
-rw-r--r--src/game/WorldSocket.cpp2
-rw-r--r--src/mangosd/WorldRunnable.cpp2
-rw-r--r--src/mangosd/mangosd.conf.dist.in6
-rw-r--r--src/shared/Database/dbcfile.cpp33
-rw-r--r--src/shared/Log.cpp2
-rw-r--r--src/shared/Log.h3
-rw-r--r--src/shared/revision_nr.h2
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__