Merge branch 'master' into 310

Conflicts:
	src/game/Level2.cpp
	src/game/PetHandler.cpp
	src/game/Player.cpp
	src/game/Player.h
	src/game/SkillHandler.cpp
This commit is contained in:
tomrus88 2009-03-11 12:22:58 +03:00
commit 31b3ee95ad
163 changed files with 5278 additions and 3233 deletions

View file

@ -55,6 +55,8 @@
# define MANGOS_GET_PROC_ADDR dlsym
# if defined(__APPLE_CC__) && defined(BIG_ENDIAN)
# define MANGOS_IMPORT __attribute__ ((longcall))
# elif defined(__x86_64__)
# define MANGOS_IMPORT
# else
# define MANGOS_IMPORT __attribute__ ((cdecl))
# endif //__APPLE_CC__ && BIG_ENDIAN

View file

@ -21,10 +21,10 @@
#include "Player.h"
#include "WorldPacket.h"
#include "Database/DBCEnums.h"
#include "GameEventMgr.h"
#include "ObjectMgr.h"
#include "Guild.h"
#include "Database/DatabaseEnv.h"
#include "GameEvent.h"
#include "World.h"
#include "SpellMgr.h"
#include "ArenaTeam.h"
@ -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:
@ -606,8 +658,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
{
if(Player::GetDrunkenstateByValue(GetPlayer()->GetDrunkValue()) != DRUNKEN_SMASHED)
continue;
// TODO: hardcoding eventid is bad, it can differ from DB to DB - maye implement something using HolidayNames.dbc?
if(!gameeventmgr.IsActiveEvent(26))
if(!IsHolidayActive(HOLIDAY_BREWFEST))
continue;
}
// miscvalue1 is the ingame fallheight*100 as stored in dbc
@ -730,6 +781,31 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
}
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
{
// miscvalue1 = emote
// miscvalue2 = achievement->ID for special requirement
if(!miscvalue1)
continue;
if(miscvalue1 != achievementCriteria->do_emote.emoteID)
continue;
if(achievementCriteria->do_emote.count)
{
// harcoded case
if(achievement->ID==247)
{
if (!unit || unit->GetTypeId() != TYPEID_PLAYER ||
unit->isAlive() || ((Player*)unit)->GetDeathTimer() == 0)
continue;
}
// expected as scripted case
else if(!miscvalue2 || !achievement->ID != miscvalue2)
continue;
}
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
}
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
{
uint32 spellCount = 0;
@ -798,7 +874,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
@ -927,6 +1002,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
return progress->counter >= achievementCriteria->roll_greed_on_loot.count;
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
return progress->counter >= achievementCriteria->do_emote.count;
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
return progress->counter >= achievementCriteria->quest_reward_money.goldInCopper;
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY:
@ -998,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);
@ -1024,8 +1103,12 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
newValue = changeValue;
break;
case PROGRESS_ACCUMULATE:
newValue = progress->counter + changeValue;
{
// avoid overflow
uint32 max_value = std::numeric_limits<uint32>::max();
newValue = max_value - progress->counter > changeValue ? progress->counter + changeValue : max_value;
break;
}
case PROGRESS_HIGHEST:
newValue = progress->counter < changeValue ? changeValue : progress->counter;
break;

View file

@ -19,7 +19,6 @@
#include "AggressorAI.h"
#include "Errors.h"
#include "Creature.h"
#include "Player.h"
#include "ObjectAccessor.h"
#include "VMapFactory.h"
#include "World.h"

View file

@ -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

View file

@ -198,6 +198,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);

View file

@ -25,7 +25,6 @@
#include "ArenaTeam.h"
#include "World.h"
#include "SocialMgr.h"
#include "Language.h"
void WorldSession::HandleInspectArenaStatsOpcode(WorldPacket & recv_data)
{

View file

@ -21,9 +21,7 @@
#include "ObjectMgr.h"
#include "Database/DatabaseEnv.h"
#include "Log.h"
#include "WorldPacket.h"
#include "UpdateData.h"
#include "WorldSession.h"
Bag::Bag( ): Item()
{

View file

@ -23,7 +23,6 @@
#include "Creature.h"
#include "MapManager.h"
#include "Language.h"
#include "Chat.h"
#include "SpellAuras.h"
#include "ArenaTeam.h"
#include "World.h"
@ -31,12 +30,105 @@
#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()
{
m_TypeID = BattleGroundTypeId(0);
m_InstanceID = 0;
m_Status = STATUS_NONE;
m_ClientInstanceID = 0;
m_EndTime = 0;
m_LastResurrectTime = 0;
m_QueueId = QUEUE_ID_MAX_LEVEL_19;
@ -88,6 +180,16 @@ BattleGround::BattleGround()
m_PrematureCountDown = false;
m_PrematureCountDown = 0;
m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_2M;
m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_1M;
m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_30S;
m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set to some default existing values
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN;
}
BattleGround::~BattleGround()
@ -126,50 +228,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;
/*********************************************************/
/*** BATTLEGROUND RESSURECTION SYSTEM ***/
/*********************************************************/
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)
}
}
//this should be handled by spell system:
//this should be handled by spell system
m_LastResurrectTime += diff;
if (m_LastResurrectTime >= RESURRECTION_INTERVAL)
{
@ -219,6 +301,10 @@ void BattleGround::Update(uint32 diff)
m_ResurrectQueue.clear();
}
/*********************************************************/
/*** BATTLEGROUND BALLANCE SYSTEM ***/
/*********************************************************/
// if less then minimum players are in on one side, then start premature finish timer
if(GetStatus() == STATUS_IN_PROGRESS && !isArena() && sBattleGroundMgr.GetPrematureFinishTime() && (GetPlayersCountByTeam(ALLIANCE) < GetMinPlayersPerTeam() || GetPlayersCountByTeam(HORDE) < GetMinPlayersPerTeam()))
{
@ -226,39 +312,137 @@ void BattleGround::Update(uint32 diff)
{
m_PrematureCountDown = true;
m_PrematureCountDownTimer = sBattleGroundMgr.GetPrematureFinishTime();
SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING);
}
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
{
uint32 newtime = m_PrematureCountDownTimer - diff;
// announce every minute
if(m_PrematureCountDownTimer != sBattleGroundMgr.GetPrematureFinishTime() && newtime / 60000 != m_PrematureCountDownTimer / 60000)
SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING);
if( newtime > (MINUTE * IN_MILISECONDS) )
{
if( newtime / (MINUTE * IN_MILISECONDS) != 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, NULL, (uint32)(m_PrematureCountDownTimer / IN_MILISECONDS));
}
m_PrematureCountDownTimer = newtime;
}
}
else if (m_PrematureCountDown)
m_PrematureCountDown = false;
/*********************************************************/
/*** BATTLEGROUND STARTING SYSTEM ***/
/*********************************************************/
if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize())
{
ModifyStartDelayTime(diff);
if (!(m_Events & BG_STARTING_EVENT_1))
{
m_Events |= BG_STARTING_EVENT_1;
// setup here, only when at least one player has ported to the map
if(!SetupBattleGround())
{
EndNow();
return;
}
StartingEventCloseDoors();
SetStartDelayTime(m_StartDelayTimes[BG_STARTING_EVENT_FIRST]);
//first start warning - 2 or 1 minute
SendMessageToAll(m_StartMessageIds[BG_STARTING_EVENT_FIRST], CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
// After 1 minute or 30 seconds, warning is signalled
else if (GetStartDelayTime() <= m_StartDelayTimes[BG_STARTING_EVENT_SECOND] && !(m_Events & BG_STARTING_EVENT_2))
{
m_Events |= BG_STARTING_EVENT_2;
SendMessageToAll(m_StartMessageIds[BG_STARTING_EVENT_SECOND], CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
// After 30 or 15 seconds, warning is signalled
else if (GetStartDelayTime() <= m_StartDelayTimes[BG_STARTING_EVENT_THIRD] && !(m_Events & BG_STARTING_EVENT_3))
{
m_Events |= BG_STARTING_EVENT_3;
SendMessageToAll(m_StartMessageIds[BG_STARTING_EVENT_THIRD], CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
// delay expired (atfer 2 or 1 minute)
else if (GetStartDelayTime() <= 0 && !(m_Events & BG_STARTING_EVENT_4))
{
m_Events |= BG_STARTING_EVENT_4;
StartingEventOpenDoors();
SendMessageToAll(m_StartMessageIds[BG_STARTING_EVENT_FOURTH], CHAT_MSG_BG_SYSTEM_NEUTRAL);
SetStatus(STATUS_IN_PROGRESS);
SetStartDelayTime(m_StartDelayTimes[BG_STARTING_EVENT_FOURTH]);
//remove preparation
if( isArena() )
{
//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);
CheckArenaWinConditions();
}
else
{
PlaySoundToAll(SOUND_BG_START);
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
if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) )
{
sWorld.SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, GetName(), GetMinLevel(), GetMaxLevel());
}
}
}
}
/*********************************************************/
/*** BATTLEGROUND ENDING SYSTEM ***/
/*********************************************************/
if(GetStatus() == STATUS_WAIT_LEAVE)
{
// remove all players from battleground after 2 minutes
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
}
}
}
void BattleGround::SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, float O)
@ -272,7 +456,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)
@ -284,7 +468,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);
@ -316,7 +500,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);
@ -339,7 +523,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);
@ -359,7 +543,7 @@ void BattleGround::CastSpellOnTeam(uint32 SpellID, uint32 TeamID)
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);
@ -384,7 +568,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);
@ -425,15 +609,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 = GetMangosString(LANG_BG_A_WINS);
else
winmsg = GetMangosString(LANG_ARENA_GOLD_WINS);
winmsg_id = isBattleGround() ? LANG_BG_A_WINS : LANG_ARENA_GOLD_WINS;
PlaySoundToAll(SOUND_ALLIANCE_WINS); // alliance wins sound
@ -441,10 +621,7 @@ void BattleGround::EndBattleGround(uint32 winner)
}
else if(winner == HORDE)
{
if(isBattleGround())
winmsg = GetMangosString(LANG_BG_H_WINS);
else
winmsg = GetMangosString(LANG_ARENA_GREEN_WINS);
winmsg_id = isBattleGround() ? LANG_BG_H_WINS : LANG_ARENA_GREEN_WINS;
PlaySoundToAll(SOUND_HORDE_WINS); // horde wins sound
@ -461,33 +638,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
{
@ -496,11 +657,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;
}
@ -515,8 +686,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)
@ -529,10 +700,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
@ -548,7 +716,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);
}
@ -570,11 +738,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
@ -723,10 +894,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;
@ -755,21 +926,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())
@ -784,65 +955,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());
}
@ -900,7 +1070,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
@ -963,7 +1133,7 @@ void BattleGround::AddPlayer(Player *plr)
}
// setup BG group membership
PlayerRelogin(plr);
PlayerAddedToBGCheckIfBGIsRunning(plr);
AddOrSetPlayerToCorrectBgGroup(plr, guid, team);
// Log
@ -992,6 +1162,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()
@ -1024,7 +1226,7 @@ void BattleGround::RemoveFromBGFreeSlotQueue()
// returns the number how many players can join battleground to MaxPlayersPerTeam
uint32 BattleGround::GetFreeSlotsForTeam(uint32 Team) const
{
//if BG is starting ... invite anyone
//return free slot count to MaxPlayerPerTeam
if (GetStatus() == STATUS_WAIT_JOIN || GetStatus() == STATUS_IN_PROGRESS)
return (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0;
@ -1357,19 +1559,30 @@ bool BattleGround::AddSpiritGuide(uint32 type, float x, float y, float z, float
return true;
}
void BattleGround::SendMessageToAll(char const* text)
void BattleGround::SendMessageToAll(int32 entry, ChatMsg type, Player const* source)
{
WorldPacket data;
ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, 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)
void BattleGround::PSendMessageToAll(int32 entry, ChatMsg type, Player const* source, ...)
{
char const* text = GetMangosString(entry);
WorldPacket data;
ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, 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);
}
void BattleGround::SendMessage2ToAll(int32 entry, ChatMsg type, Player const* source, int32 arg1, int32 arg2)
{
MaNGOS::BattleGround2ChatBuilder bg_builder(type, entry, source, arg1, arg2);
MaNGOS::LocalizedPacketDo<MaNGOS::BattleGround2ChatBuilder> bg_do(bg_builder);
BroadcastWorker(bg_do);
}
void BattleGround::EndNow()
@ -1381,13 +1594,6 @@ 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
const char *BattleGround::GetMangosString(int32 entry)
{
// FIXME: now we have different DBC locales and need localized message for each target client
return objmgr.GetMangosStringForDBCLocale(entry);
}
/*
important notice:
buffs aren't spawned/despawned when players captures anything
@ -1441,7 +1647,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);
@ -1461,21 +1667,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;
@ -1488,14 +1699,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)
{
@ -1507,6 +1718,14 @@ uint32 BattleGround::GetAlivePlayersCountByTeam(uint32 Team) const
return count;
}
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];
@ -1518,4 +1737,4 @@ void BattleGround::SetBgRaid( uint32 TeamID, Group *bg_raid )
WorldSafeLocsEntry const* BattleGround::GetClosestGraveYard( Player* player )
{
return objmgr.GetClosestGraveYard( player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetMapId(), player->GetTeam() );
}
}

View file

@ -89,15 +89,19 @@ enum BattleGroundTimeIntervals
INVITATION_REMIND_TIME = 60000, // ms
INVITE_ACCEPT_WAIT_TIME = 80000, // ms
TIME_TO_AUTOREMOVE = 120000, // ms
MAX_OFFLINE_TIME = 300000, // ms
START_DELAY0 = 120000, // ms
START_DELAY1 = 60000, // ms
START_DELAY2 = 30000, // ms
START_DELAY3 = 15000, // ms used only in arena
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
{
BG_START_DELAY_2M = 120000, // ms (2 minutes)
BG_START_DELAY_1M = 60000, // ms (1 minute)
BG_START_DELAY_30S = 30000, // ms (30 seconds)
BG_START_DELAY_15S = 15000, // ms (15 seconds) Used only in arena
BG_START_DELAY_NONE = 0, // ms
};
enum BattleGroundBuffObjects
@ -120,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
};
@ -214,6 +218,24 @@ enum BattleGroundTeamId
};
#define BG_TEAMS_COUNT 2
enum BattleGroundStartingEvents
{
BG_STARTING_EVENT_NONE = 0x00,
BG_STARTING_EVENT_1 = 0x01,
BG_STARTING_EVENT_2 = 0x02,
BG_STARTING_EVENT_3 = 0x04,
BG_STARTING_EVENT_4 = 0x08
};
enum BattleGroundStartingEventsIds
{
BG_STARTING_EVENT_FIRST = 0,
BG_STARTING_EVENT_SECOND = 1,
BG_STARTING_EVENT_THIRD = 2,
BG_STARTING_EVENT_FOURTH = 3
};
#define BG_STARTING_EVENT_COUNT 4
enum BattleGroundJoinError
{
BG_JOIN_ERR_OK = 0,
@ -266,6 +288,8 @@ class BattleGround
return true;
}
virtual void Reset(); // resets all common properties for battlegrounds, must be implemented and called in BG subclass
virtual void StartingEventCloseDoors() {}
virtual void StartingEventOpenDoors() {}
/* Battleground */
// Get methods:
@ -274,6 +298,7 @@ class BattleGround
BGQueueIdBasedOnLevel GetQueueId() const { return m_QueueId; }
uint32 GetInstanceID() const { return m_InstanceID; }
BattleGroundStatus GetStatus() const { return m_Status; }
uint32 GetClientInstanceID() const { return m_ClientInstanceID; }
uint32 GetStartTime() const { return m_StartTime; }
uint32 GetEndTime() const { return m_EndTime; }
uint32 GetLastResurrectTime() const { return m_LastResurrectTime; }
@ -290,6 +315,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; }
@ -303,6 +329,7 @@ class BattleGround
}
void SetInstanceID(uint32 InstanceID) { m_InstanceID = InstanceID; }
void SetStatus(BattleGroundStatus Status) { m_Status = Status; }
void SetClientInstanceID(uint32 InstanceID) { m_ClientInstanceID = InstanceID; }
void SetStartTime(uint32 Time) { m_StartTime = Time; }
void SetEndTime(uint32 Time) { m_EndTime = Time; }
void SetLastResurrectTime(uint32 Time) { m_LastResurrectTime = Time; }
@ -342,7 +369,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(); }
@ -374,6 +400,10 @@ class BattleGround
virtual void FillInitialWorldStates(WorldPacket& /*data*/) {}
void SendPacketToTeam(uint32 TeamID, WorldPacket *packet, Player *sender = NULL, bool self = true);
void SendPacketToAll(WorldPacket *packet);
template<class Do>
void BroadcastWorker(Do& _do);
void PlaySoundToTeam(uint32 SoundID, uint32 TeamID);
void PlaySoundToAll(uint32 SoundID);
void CastSpellOnTeam(uint32 SpellID, uint32 TeamID);
@ -387,8 +417,11 @@ class BattleGround
void EndBattleGround(uint32 winner);
void BlockMovement(Player *plr);
void SendMessageToAll(char const* text);
void SendMessageToAll(int32 entry);
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]; }
@ -409,9 +442,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
@ -420,10 +454,11 @@ class BattleGround
virtual void HandleKillPlayer(Player *player, Player *killer);
/* Battleground events */
/* these functions will return true event is possible, but false if player is bugger */
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);
@ -452,20 +487,20 @@ class BattleGround
void DoorOpen(uint32 type);
void DoorClose(uint32 type);
const char *GetMangosString(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
@ -479,9 +514,12 @@ class BattleGround
std::map<uint64, std::vector<uint64> > m_ReviveQueue;
/*
this is important variable used for invitation messages
these are important variables used for starting messages
*/
uint8 m_Events;
BattleGroundStartTimeIntervals m_StartDelayTimes[BG_STARTING_EVENT_COUNT];
//this must be filled in constructors!
uint32 m_StartMessageIds[BG_STARTING_EVENT_COUNT];
bool m_BuffChange;
@ -490,6 +528,7 @@ class BattleGround
BattleGroundTypeId m_TypeID;
uint32 m_InstanceID; //BattleGround Instance's GUID!
BattleGroundStatus m_Status;
uint32 m_ClientInstanceID; //the instance-id which is sent to the client and without any other internal use
uint32 m_StartTime;
uint32 m_EndTime;
uint32 m_LastResurrectTime;
@ -507,7 +546,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 */

View file

@ -19,10 +19,20 @@
#include "Player.h"
#include "BattleGround.h"
#include "BattleGroundAA.h"
#include "Language.h"
BattleGroundAA::BattleGroundAA()
{
m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattleGroundAA::~BattleGroundAA()
@ -35,6 +45,14 @@ void BattleGroundAA::Update(uint32 diff)
BattleGround::Update(diff);
}
void BattleGroundAA::StartingEventCloseDoors()
{
}
void BattleGroundAA::StartingEventOpenDoors()
{
}
void BattleGroundAA::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);

View file

@ -39,6 +39,9 @@ class BattleGroundAA : public BattleGround
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
void RemovePlayer(Player *plr, uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);
bool SetupBattleGround();

View file

@ -21,9 +21,7 @@
#include "BattleGround.h"
#include "BattleGroundAB.h"
#include "Creature.h"
#include "Chat.h"
#include "ObjectMgr.h"
#include "MapManager.h"
#include "Language.h"
#include "Util.h"
#include "WorldPacket.h"
@ -33,6 +31,11 @@ BattleGroundAB::BattleGroundAB()
m_BuffChange = true;
m_BgObjects.resize(BG_AB_OBJECT_MAX);
m_BgCreatures.resize(BG_AB_ALL_NODES_COUNT);
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_AB_START_TWO_MINUTES;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_AB_START_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_AB_START_HALF_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_AB_HAS_BEGUN;
}
BattleGroundAB::~BattleGroundAB()
@ -43,81 +46,7 @@ void BattleGroundAB::Update(uint32 diff)
{
BattleGround::Update(diff);
if( GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize() )
{
ModifyStartDelayTime(diff);
if( !(m_Events & 0x01) )
{
m_Events |= 0x01;
// setup here, only when at least one player has ported to the map
if(!SetupBattleGround())
{
EndNow();
return;
}
sLog.outDebug("Arathi Basin: entering state STATUS_WAIT_JOIN ...");
// despawn banners, auras and buffs
for (int obj = BG_AB_OBJECT_BANNER_NEUTRAL; obj < BG_AB_DYNAMIC_NODES_COUNT * 8; ++obj)
SpawnBGObject(obj, RESPAWN_ONE_DAY);
for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT * 3; ++i)
SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + i, RESPAWN_ONE_DAY);
// Starting doors
SpawnBGObject(BG_AB_OBJECT_GATE_A, RESPAWN_IMMEDIATELY);
SpawnBGObject(BG_AB_OBJECT_GATE_H, RESPAWN_IMMEDIATELY);
DoorClose(BG_AB_OBJECT_GATE_A);
DoorClose(BG_AB_OBJECT_GATE_H);
// Starting base spirit guides
_NodeOccupied(BG_AB_SPIRIT_ALIANCE,ALLIANCE);
_NodeOccupied(BG_AB_SPIRIT_HORDE,HORDE);
SetStartDelayTime(START_DELAY0);
}
// After 1 minute, warning is signalled
else if( GetStartDelayTime() <= START_DELAY1 && !(m_Events & 0x04) )
{
m_Events |= 0x04;
SendMessageToAll(GetMangosString(LANG_BG_AB_ONEMINTOSTART));
}
// After 1,5 minute, warning is signalled
else if( GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x08) )
{
m_Events |= 0x08;
SendMessageToAll(GetMangosString(LANG_BG_AB_HALFMINTOSTART));
}
// After 2 minutes, gates OPEN ! x)
else if( GetStartDelayTime() < 0 && !(m_Events & 0x10) )
{
m_Events |= 0x10;
SendMessageToAll(GetMangosString(LANG_BG_AB_STARTED));
// spawn neutral banners
for (int banner = BG_AB_OBJECT_BANNER_NEUTRAL, i = 0; i < 5; banner += 8, ++i)
SpawnBGObject(banner, RESPAWN_IMMEDIATELY);
for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
{
//randomly select buff to spawn
uint8 buff = urand(0, 2);
SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + buff + i * 3, RESPAWN_IMMEDIATELY);
}
DoorOpen(BG_AB_OBJECT_GATE_A);
DoorOpen(BG_AB_OBJECT_GATE_H);
PlaySoundToAll(SOUND_BG_START);
SetStatus(STATUS_IN_PROGRESS);
for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
if(Player* plr = objmgr.GetPlayer(itr->first))
plr->RemoveAurasDueToSpell(SPELL_PREPARATION);
}
}
else if( GetStatus() == STATUS_IN_PROGRESS )
if( GetStatus() == STATUS_IN_PROGRESS )
{
int team_points[2] = { 0, 0 };
@ -154,13 +83,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, GetMangosString(LANG_BG_AB_NODE_TAKEN), (teamIndex == 0) ? GetMangosString(LANG_BG_AB_ALLY) : GetMangosString(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);
}
}
}
@ -182,22 +117,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] >= 200 )
if( m_ReputationScoreTics[team] >= m_ReputationTics )
{
(team == BG_TEAM_ALLIANCE) ? RewardReputationToTeam(509, 10, ALLIANCE) : RewardReputationToTeam(510, 10, HORDE);
m_ReputationScoreTics[team] -= 200;
m_ReputationScoreTics[team] -= m_ReputationTics;
}
if( m_HonorScoreTics[team] >= BG_HONOR_SCORE_TICKS )
if( m_HonorScoreTics[team] >= m_HonorTics )
{
(team == BG_TEAM_ALLIANCE) ? RewardHonorToTeam(20, ALLIANCE) : RewardHonorToTeam(20, HORDE);
m_HonorScoreTics[team] -= BG_HONOR_SCORE_TICKS;
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));
SendMessageToAll(LANG_BG_AB_A_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL);
else
SendMessageToAll(GetMangosString(LANG_BG_AB_H_NEAR_VICTORY));
SendMessageToAll(LANG_BG_AB_H_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(SOUND_NEAR_VICTORY);
m_IsInformedNearVictory = true;
}
@ -219,6 +154,40 @@ void BattleGroundAB::Update(uint32 diff)
}
}
void BattleGroundAB::StartingEventCloseDoors()
{
// despawn banners, auras and buffs
for (int obj = BG_AB_OBJECT_BANNER_NEUTRAL; obj < BG_AB_DYNAMIC_NODES_COUNT * 8; ++obj)
SpawnBGObject(obj, RESPAWN_ONE_DAY);
for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT * 3; ++i)
SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + i, RESPAWN_ONE_DAY);
// Starting doors
DoorClose(BG_AB_OBJECT_GATE_A);
DoorClose(BG_AB_OBJECT_GATE_H);
SpawnBGObject(BG_AB_OBJECT_GATE_A, RESPAWN_IMMEDIATELY);
SpawnBGObject(BG_AB_OBJECT_GATE_H, RESPAWN_IMMEDIATELY);
// Starting base spirit guides
_NodeOccupied(BG_AB_SPIRIT_ALIANCE,ALLIANCE);
_NodeOccupied(BG_AB_SPIRIT_HORDE,HORDE);
}
void BattleGroundAB::StartingEventOpenDoors()
{
// spawn neutral banners
for (int banner = BG_AB_OBJECT_BANNER_NEUTRAL, i = 0; i < 5; banner += 8, ++i)
SpawnBGObject(banner, RESPAWN_IMMEDIATELY);
for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
{
//randomly select buff to spawn
uint8 buff = urand(0, 2);
SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + buff + i * 3, RESPAWN_IMMEDIATELY);
}
DoorOpen(BG_AB_OBJECT_GATE_A);
DoorOpen(BG_AB_OBJECT_GATE_H);
}
void BattleGroundAB::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);
@ -303,24 +272,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 GetMangosString(LANG_BG_AB_NODE_STABLES);
case BG_AB_NODE_BLACKSMITH:
return GetMangosString(LANG_BG_AB_NODE_BLACKSMITH);
case BG_AB_NODE_FARM:
return GetMangosString(LANG_BG_AB_NODE_FARM);
case BG_AB_NODE_LUMBER_MILL:
return GetMangosString(LANG_BG_AB_NODE_LUMBER_MILL);
case BG_AB_NODE_GOLD_MINE:
return GetMangosString(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)
@ -451,10 +415,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;
@ -473,7 +433,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, GetMangosString(LANG_BG_AB_NODE_CLAIMED), _GetNodeName(node), (teamIndex == 0) ? GetMangosString(LANG_BG_AB_ALLY) : GetMangosString(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
@ -491,7 +457,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, GetMangosString(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
@ -506,7 +477,12 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
_SendNodeUpdate(node);
m_NodeTimers[node] = 0;
_NodeOccupied(node,(teamIndex == 0) ? ALLIANCE:HORDE);
sprintf(buf, GetMangosString(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;
}
@ -523,18 +499,24 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
_SendNodeUpdate(node);
_NodeDeOccupied(node);
m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME;
sprintf(buf, GetMangosString(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, GetMangosString(LANG_BG_AB_NODE_TAKEN), (teamIndex == 0) ? GetMangosString(LANG_BG_AB_ALLY) : GetMangosString(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);
}
@ -591,6 +573,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;
@ -604,6 +590,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());

View file

@ -170,6 +170,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
@ -238,10 +243,13 @@ class BattleGroundAB : public BattleGround
void Update(uint32 diff);
void AddPlayer(Player *plr);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
void RemovePlayer(Player *plr,uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);
virtual bool SetupBattleGround();
virtual void Reset();
void EndBattleGround(uint32 winner);
virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player);
/* Scorekeeping */
@ -263,7 +271,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
@ -271,14 +279,18 @@ 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

View file

@ -20,13 +20,16 @@
#include "Player.h"
#include "BattleGround.h"
#include "BattleGroundAV.h"
#include "Creature.h"
#include "MapManager.h"
#include "Language.h"
BattleGroundAV::BattleGroundAV()
{
//TODO FIX ME!
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_EY_START_TWO_MINUTES;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_EY_START_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_EY_START_HALF_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_EY_HAS_BEGUN;
}
BattleGroundAV::~BattleGroundAV()
@ -39,6 +42,14 @@ void BattleGroundAV::Update(uint32 diff)
BattleGround::Update(diff);
}
void BattleGroundAV::StartingEventCloseDoors()
{
}
void BattleGroundAV::StartingEventOpenDoors()
{
}
void BattleGroundAV::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);

View file

@ -46,6 +46,8 @@ class BattleGroundAV : public BattleGround
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
void RemovePlayer(Player *plr,uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);

View file

@ -20,15 +20,23 @@
#include "Player.h"
#include "BattleGround.h"
#include "BattleGroundBE.h"
#include "Creature.h"
#include "ObjectMgr.h"
#include "MapManager.h"
#include "WorldPacket.h"
#include "Language.h"
BattleGroundBE::BattleGroundBE()
{
m_BgObjects.resize(BG_BE_OBJECT_MAX);
m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattleGroundBE::~BattleGroundBE()
@ -40,73 +48,30 @@ void BattleGroundBE::Update(uint32 diff)
{
BattleGround::Update(diff);
// after bg start we get there
if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize())
{
ModifyStartDelayTime(diff);
if (!(m_Events & 0x01))
{
m_Events |= 0x01;
// setup here, only when at least one player has ported to the map
if(!SetupBattleGround())
{
EndNow();
return;
}
for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_4; i++)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
for(uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; i++)
SpawnBGObject(i, RESPAWN_ONE_DAY);
SetStartDelayTime(START_DELAY1);
SendMessageToAll(LANG_ARENA_ONE_MINUTE);
}
// After 30 seconds, warning is signalled
else if (GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x04))
{
m_Events |= 0x04;
SendMessageToAll(LANG_ARENA_THIRTY_SECONDS);
}
// After 15 seconds, warning is signalled
else if (GetStartDelayTime() <= START_DELAY3 && !(m_Events & 0x08))
{
m_Events |= 0x08;
SendMessageToAll(LANG_ARENA_FIFTEEN_SECONDS);
}
// delay expired (1 minute)
else if (GetStartDelayTime() <= 0 && !(m_Events & 0x10))
{
m_Events |= 0x10;
for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_2; i++)
DoorOpen(i);
for(uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; i++)
SpawnBGObject(i, 60);
SendMessageToAll(LANG_ARENA_BEGUN);
SetStatus(STATUS_IN_PROGRESS);
SetStartDelayTime(0);
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);
}
}
/*if(GetStatus() == STATUS_IN_PROGRESS)
{
// update something
}*/
}
void BattleGroundBE::StartingEventCloseDoors()
{
for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_4; i++)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
for(uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; i++)
SpawnBGObject(i, RESPAWN_ONE_DAY);
}
void BattleGroundBE::StartingEventOpenDoors()
{
for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_2; i++)
DoorOpen(i);
for(uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; i++)
SpawnBGObject(i, 60);
}
void BattleGroundBE::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);
@ -127,10 +92,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)
@ -149,16 +111,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)

View file

@ -59,6 +59,8 @@ class BattleGroundBE : public BattleGround
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
void RemovePlayer(Player *plr, uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);

View file

@ -19,10 +19,20 @@
#include "Player.h"
#include "BattleGround.h"
#include "BattleGroundDS.h"
#include "Language.h"
BattleGroundDS::BattleGroundDS()
{
m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattleGroundDS::~BattleGroundDS()
@ -35,6 +45,14 @@ void BattleGroundDS::Update(uint32 diff)
BattleGround::Update(diff);
}
void BattleGroundDS::StartingEventCloseDoors()
{
}
void BattleGroundDS::StartingEventOpenDoors()
{
}
void BattleGroundDS::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);

View file

@ -39,6 +39,9 @@ class BattleGroundDS : public BattleGround
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
void RemovePlayer(Player *plr, uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);
bool SetupBattleGround();

View file

@ -21,9 +21,7 @@
#include "BattleGround.h"
#include "BattleGroundEY.h"
#include "Creature.h"
#include "Chat.h"
#include "ObjectMgr.h"
#include "MapManager.h"
#include "Language.h"
#include "WorldPacket.h"
#include "Util.h"
@ -37,6 +35,11 @@ BattleGroundEY::BattleGroundEY()
m_Points_Trigger[BLOOD_ELF] = TR_BLOOD_ELF_BUFF;
m_Points_Trigger[DRAENEI_RUINS] = TR_DRAENEI_RUINS_BUFF;
m_Points_Trigger[MAGE_TOWER] = TR_MAGE_TOWER_BUFF;
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_EY_START_TWO_MINUTES;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_EY_START_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_EY_START_HALF_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_EY_HAS_BEGUN;
}
BattleGroundEY::~BattleGroundEY()
@ -46,71 +49,8 @@ BattleGroundEY::~BattleGroundEY()
void BattleGroundEY::Update(uint32 diff)
{
BattleGround::Update(diff);
// after bg start we get there (once)
if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize())
{
ModifyStartDelayTime(diff);
if(!(m_Events & 0x01))
{
m_Events |= 0x01;
// setup here, only when at least one player has ported to the map
if(!SetupBattleGround())
{
EndNow();
return;
}
SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_IMMEDIATELY);
SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_IMMEDIATELY);
// SpawnBGCreature(EY_SPIRIT_MAIN_ALLIANCE, RESPAWN_IMMEDIATELY);
// SpawnBGCreature(EY_SPIRIT_MAIN_HORDE, RESPAWN_IMMEDIATELY);
for(uint32 i = BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER; i < BG_EY_OBJECT_MAX; ++i)
SpawnBGObject(i, RESPAWN_ONE_DAY);
SetStartDelayTime(START_DELAY0);
}
// After 1 minute, warning is signalled
else if(GetStartDelayTime() <= START_DELAY1 && !(m_Events & 0x04))
{
m_Events |= 0x04;
SendMessageToAll(GetMangosString(LANG_BG_EY_ONE_MINUTE));
}
// After 1,5 minute, warning is signalled
else if(GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x08))
{
m_Events |= 0x08;
SendMessageToAll(GetMangosString(LANG_BG_EY_HALF_MINUTE));
}
// After 2 minutes, gates OPEN ! x)
else if(GetStartDelayTime() < 0 && !(m_Events & 0x10))
{
m_Events |= 0x10;
SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_ONE_DAY);
SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_ONE_DAY);
for(uint32 i = BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER; i <= BG_EY_OBJECT_FLAG_NETHERSTORM; ++i)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
for(uint32 i = 0; i < EY_POINTS_MAX; ++i)
{
//randomly spawn buff
uint8 buff = urand(0, 2);
SpawnBGObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + buff + i * 3, RESPAWN_IMMEDIATELY);
}
SendMessageToAll(GetMangosString(LANG_BG_EY_BEGIN));
PlaySoundToAll(SOUND_BG_START);
SetStatus(STATUS_IN_PROGRESS);
for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
if(Player *plr = objmgr.GetPlayer(itr->first))
plr->RemoveAurasDueToSpell(SPELL_PREPARATION);
}
}
else if(GetStatus() == STATUS_IN_PROGRESS)
if( GetStatus() == STATUS_IN_PROGRESS )
{
m_PointAddingTimer -= diff;
if(m_PointAddingTimer <= 0)
@ -152,15 +92,39 @@ void BattleGroundEY::Update(uint32 diff)
}
}
void BattleGroundEY::StartingEventCloseDoors()
{
SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_IMMEDIATELY);
SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_IMMEDIATELY);
for(uint32 i = BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER; i < BG_EY_OBJECT_MAX; ++i)
SpawnBGObject(i, RESPAWN_ONE_DAY);
}
void BattleGroundEY::StartingEventOpenDoors()
{
SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_ONE_DAY);
SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_ONE_DAY);
for(uint32 i = BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER; i <= BG_EY_OBJECT_FLAG_NETHERSTORM; ++i)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
for(uint32 i = 0; i < EY_POINTS_MAX; ++i)
{
//randomly spawn buff
uint8 buff = urand(0, 2);
SpawnBGObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + buff + i * 3, RESPAWN_IMMEDIATELY);
}
}
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_HONOR_SCORE_TICKS)
if (m_HonorScoreTics[team_index] >= m_HonorTics )
{
RewardHonorToTeam(20, Team);
m_HonorScoreTics[team_index] -= BG_HONOR_SCORE_TICKS;
RewardHonorToTeam(GetBonusHonorFromKill(1), Team);
m_HonorScoreTics[team_index] -= m_HonorTics;
}
UpdateTeamScore(Team);
}
@ -183,7 +147,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
@ -226,7 +190,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]);
@ -306,6 +270,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)
@ -530,6 +508,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)
{
@ -554,7 +534,7 @@ void BattleGroundEY::RespawnFlag(bool send_message)
if(send_message)
{
SendMessageToAll(GetMangosString(LANG_BG_EY_RESETED_FLAG));
SendMessageToAll(LANG_BG_EY_RESETED_FLAG, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(BG_EY_SOUND_FLAG_RESET); // flags respawned sound...
}
@ -603,32 +583,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 = GetMangosString(LANG_BG_EY_DROPPED_FLAG);
type = CHAT_MSG_BG_SYSTEM_ALLIANCE;
}
else
{
message = GetMangosString(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)
@ -636,20 +604,14 @@ void BattleGroundEY::EventPlayerClickedOnFlag(Player *Source, GameObject* target
if(GetStatus() != STATUS_IN_PROGRESS || IsFlagPickedup() || !Source->IsWithinDistInMap(target_obj, 10))
return;
const char *message;
uint8 type = 0;
message = GetMangosString(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);
}
@ -663,9 +625,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)
@ -674,8 +637,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)
@ -684,8 +645,6 @@ void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point)
if (Team == ALLIANCE)
{
m_TeamPointsCount[BG_TEAM_ALLIANCE]--;
message_type = CHAT_MSG_BG_SYSTEM_ALLIANCE;
message = GetMangosString(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);
@ -693,8 +652,6 @@ void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point)
else
{
m_TeamPointsCount[BG_TEAM_HORDE]--;
message_type = CHAT_MSG_BG_SYSTEM_HORDE;
message = GetMangosString(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);
@ -709,9 +666,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);
@ -722,8 +680,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);
@ -733,8 +689,6 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point)
if (Team == ALLIANCE)
{
m_TeamPointsCount[BG_TEAM_ALLIANCE]++;
type = CHAT_MSG_BG_SYSTEM_ALLIANCE;
message = GetMangosString(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);
@ -742,8 +696,6 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point)
else
{
m_TeamPointsCount[BG_TEAM_HORDE]++;
type = CHAT_MSG_BG_SYSTEM_HORDE;
message = GetMangosString(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);
@ -754,9 +706,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);
@ -778,38 +731,33 @@ void BattleGroundEY::EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType
if(GetStatus() != STATUS_IN_PROGRESS || 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 = GetMangosString(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 = GetMangosString(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]);

View file

@ -210,6 +210,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,
@ -302,6 +305,8 @@ class BattleGroundEY : public BattleGround
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
/* BG Flags */
uint64 GetFlagPickerGUID() const { return m_FlagKeeper; }
@ -319,6 +324,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;}
@ -368,5 +374,6 @@ class BattleGroundEY : public BattleGround
uint8 m_CurrentPointPlayersCount[2*EY_POINTS_MAX];
int32 m_PointAddingTimer;
uint32 m_HonorTics;
};
#endif

View file

@ -23,7 +23,6 @@
#include "Player.h"
#include "ObjectMgr.h"
#include "WorldSession.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "Object.h"
#include "Chat.h"
@ -111,9 +110,9 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
return;
// get bg instance or bg template if instance not found
BattleGround * bg = 0;
BattleGround * bg = NULL;
if(instanceId)
BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId, bgTypeId);
BattleGround *bg = sBattleGroundMgr.GetBattleGroundThroughClientInstance(instanceId, bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
if(!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId)))
{
@ -157,10 +156,11 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
// if we're here, then the conditions to join a bg are met. We can proceed in joining.
// _player->GetGroup() was already checked, grp is already initialized
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, isPremade, 0);
uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
if(joinAsGroup /* && _player->GetGroup()*/)
{
sLog.outDebug("Battleground: the following players are joining as group:");
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, isPremade, 0);
for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
{
Player *member = itr->getSource();
@ -173,7 +173,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, avgTime, 0);
member->GetSession()->SendPacket(&data);
sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId);
member->GetSession()->SendPacket(&data);
@ -181,9 +181,6 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName());
}
sLog.outDebug("Battleground: group end");
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
if(!ginfo->IsInvitedToBGInstanceGUID)
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true);
}
else
{
@ -194,16 +191,15 @@ 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, avgTime, 0);
SendPacket(&data);
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, false, 0);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
if(!ginfo->IsInvitedToBGInstanceGUID)
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true);
sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName());
}
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
if(!ginfo->IsInvitedToBGInstanceGUID)
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true);
}
void WorldSession::HandleBattleGroundPlayerPositionsOpcode( WorldPacket & /*recv_data*/ )
@ -323,22 +319,16 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId);
BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID());
// if the player is not in queue, continue
if(itrPlayerStatus == qpMap.end())
continue;
// no group information, this should never happen
if(!itrPlayerStatus->second.GroupInfo)
// if the player is not in queue, continue or no group information - this should never happen
if(itrPlayerStatus == qpMap.end() || !itrPlayerStatus->second.GroupInfo)
continue;
BattleGround * bg = NULL;
// get possibly needed data from groupinfo
uint8 arenatype = itrPlayerStatus->second.GroupInfo->ArenaType;
uint8 israted = itrPlayerStatus->second.GroupInfo->IsRated;
uint8 status = 0;
if(!itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID)
{
// not invited to bg, get template
@ -362,7 +352,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);
}
}
@ -429,6 +419,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)
{
@ -449,7 +445,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);
@ -484,7 +480,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);
@ -528,84 +524,41 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ )
sLog.outDebug( "WORLD: Battleground status" );
WorldPacket data;
uint32 queueSlot = PLAYER_MAX_BATTLEGROUND_QUEUES;
// TODO: we must put player back to battleground in case disconnect (< 5 minutes offline time) or teleport player on login(!) from battleground map to entry point
if(_player->InBattleGround())
{
BattleGround *bg = _player->GetBattleGround();
if(bg)
if(!bg)
return;
BattleGroundQueueTypeId bgQueueTypeId_tmp = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId_tmp);
if((bg->GetStatus() <= STATUS_IN_PROGRESS))
{
BattleGroundQueueTypeId bgQueueTypeId_tmp = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
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());
SendPacket(&data);
}
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
{
BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i);
if (i == queueSlot || !bgQueueTypeId)
continue;
BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId);
uint8 arenatype = BattleGroundMgr::BGArenaType(bgQueueTypeId);
uint8 isRated = 0;
BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID());
if(itrPlayerStatus == qpMap.end())
continue;
if(itrPlayerStatus->second.GroupInfo)
{
arenatype = itrPlayerStatus->second.GroupInfo->ArenaType;
isRated = itrPlayerStatus->second.GroupInfo->IsRated;
}
BattleGround *bg2 = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
if(bg2)
{
//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);
SendPacket(&data);
}
}
}
}
else
{
// we should update all queues? .. i'm not sure if this code is correct
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
{
BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i);
if(!bgQueueTypeId)
continue;
BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId);
uint8 arenatype = BattleGroundMgr::BGArenaType(bgQueueTypeId);
uint8 isRated = 0;
BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID());
if(itrPlayerStatus == qpMap.end())
continue;
if(itrPlayerStatus->second.GroupInfo)
{
arenatype = itrPlayerStatus->second.GroupInfo->ArenaType;
isRated = itrPlayerStatus->second.GroupInfo->IsRated;
}
if(bg)
{
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated);
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);
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime());
SendPacket(&data);
}
}*/
}
// we should update all queues? .. i'm not sure if this code is correct
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
{
BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i);
if(!bgQueueTypeId || i == queueSlot) //queueslot check in case we already send it in the above code
continue;
BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId);
uint8 arenatype = BattleGroundMgr::BGArenaType(bgQueueTypeId);
BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
if(!bg)
continue;
BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID());
if(itrPlayerStatus == qpMap.end() || !itrPlayerStatus->second.GroupInfo)
continue;
arenatype = itrPlayerStatus->second.GroupInfo->ArenaType;
uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(itrPlayerStatus->second.GroupInfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, avgTime, getMSTime()-itrPlayerStatus->second.GroupInfo->JoinTime, arenatype);
SendPacket(&data);
}
}
void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket & recv_data )
@ -768,9 +721,10 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
arenaRating = avg_pers_rating;
}
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating, ateamId);
uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
if(asGroup)
{
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating, ateamId);
sLog.outDebug("Battleground: arena join as group start");
if(isRated)
sLog.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player->GetArenaTeamId(arenaslot),_player->GetName(),arenaRating,arenatype);
@ -786,7 +740,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, avgTime, 0, arenatype);
member->GetSession()->SendPacket(&data);
sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId);
member->GetSession()->SendPacket(&data);
@ -794,7 +748,6 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
sLog.outDebug("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName());
}
sLog.outDebug("Battleground: arena join as group end");
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId), arenatype, isRated, arenaRating);
if(isRated)
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true);
}
@ -807,13 +760,12 @@ 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, avgTime, 0, arenatype);
SendPacket(&data);
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId), arenatype, isRated, arenaRating);
sLog.outDebug("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName());
}
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId), arenatype, isRated, arenaRating);
}
void WorldSession::HandleBattleGroundReportAFK( WorldPacket & recv_data )

View file

@ -52,6 +52,16 @@ INSTANTIATE_SINGLETON_1( BattleGroundMgr );
BattleGroundQueue::BattleGroundQueue()
{
for(uint32 i = 0; i < BG_TEAMS_COUNT; i++)
{
for(uint32 j = 0; j < MAX_BATTLEGROUND_QUEUES; j++)
{
m_SumOfWaitTimes[i][j] = 0;
m_WaitTimeLastPlayer[i][j] = 0;
for(uint32 k = 0; k < COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME; k++)
m_WaitTimes[i][j][k] = 0;
}
}
}
BattleGroundQueue::~BattleGroundQueue()
@ -81,7 +91,7 @@ void BattleGroundQueue::SelectionPool::Init()
// remove group info from selection pool
// returns true when we need to try to add new group to selection pool
// or false when pool is ok
// returns false when selection pool is ok or when we kicked smaller group than we need to kick
// sometimes it can be called on empty selection pool
bool BattleGroundQueue::SelectionPool::KickGroup(uint32 size)
{
@ -105,7 +115,8 @@ bool BattleGroundQueue::SelectionPool::KickGroup(uint32 size)
GroupQueueInfo* ginfo = (*groupToKick);
SelectedGroups.erase(groupToKick);
PlayerCount -= ginfo->Players.size();
if (abs((int32)(ginfo->Players.size() - size)) <= 1)
//return false if we kicked smaller group or there are enough players in selection pool
if (ginfo->Players.size() <= size + 1)
return false;
}
return true;
@ -113,8 +124,8 @@ bool BattleGroundQueue::SelectionPool::KickGroup(uint32 size)
// add group to selection pool
// used when building selection pools
// returns true if we can invite more players
// returns false when selection pool is set
// returns true if we can invite more players, or when we added group to selection pool
// returns false when selection pool is full
bool BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo *ginfo, uint32 desiredCount)
{
//if group is larger than desired count - don't allow to add it to pool
@ -123,6 +134,7 @@ bool BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo *ginfo, uint32 de
SelectedGroups.push_back(ginfo);
// increase selected players count
PlayerCount += ginfo->Players.size();
return true;
}
if( PlayerCount < desiredCount )
return true;
@ -147,7 +159,7 @@ GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, BattleGroundTypeId
ginfo->ArenaTeamId = arenateamid;
ginfo->IsRated = isRated;
ginfo->IsInvitedToBGInstanceGUID = 0;
ginfo->JoinTime = getMSTime();
ginfo->JoinTime = sWorld.GetGameTime() * IN_MILISECONDS;
ginfo->Team = leader->GetTeam();
ginfo->ArenaTeamRating = arenaRating;
ginfo->OpponentsTeamRating = 0;
@ -173,8 +185,6 @@ void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo)
{
//if player isn't in queue, he is added, if already is, then values are overwritten, no memory leak
PlayerQueueInfo& info = m_QueuedPlayers[plr->GetGUID()];
info.InviteTime = 0;
info.LastInviteTime = 0;
info.LastOnlineTime = getMSTime();
info.GroupInfo = ginfo;
@ -182,6 +192,55 @@ void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo)
ginfo->Players[plr->GetGUID()] = &info;
}
void BattleGroundQueue::PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id)
{
uint32 timeInQueue = (sWorld.GetGameTime() * IN_MILISECONDS) - ginfo->JoinTime;
uint8 team_index = BG_TEAM_ALLIANCE; //default set to BG_TEAM_ALLIANCE - or non rated arenas!
if( !ginfo->ArenaType )
{
if( ginfo->Team == HORDE )
team_index = BG_TEAM_HORDE;
}
else
{
if( ginfo->IsRated )
team_index = BG_TEAM_HORDE; //for rated arenas use BG_TEAM_HORDE
}
//store pointer to arrayindex of player that was added first
uint32* lastPlayerAddedPointer = &(m_WaitTimeLastPlayer[team_index][queue_id]);
//remove his time from sum
m_SumOfWaitTimes[team_index][queue_id] -= m_WaitTimes[team_index][queue_id][(*lastPlayerAddedPointer)];
//set average time to new
m_WaitTimes[team_index][queue_id][(*lastPlayerAddedPointer)] = timeInQueue;
//add new time to sum
m_SumOfWaitTimes[team_index][queue_id] += timeInQueue;
//set index of last player added to next one
(*lastPlayerAddedPointer)++;
(*lastPlayerAddedPointer) %= COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME;
}
uint32 BattleGroundQueue::GetAverageQueueWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id)
{
uint8 team_index = BG_TEAM_ALLIANCE; //default set to BG_TEAM_ALLIANCE - or non rated arenas!
if( !ginfo->ArenaType )
{
if( ginfo->Team == HORDE )
team_index = BG_TEAM_HORDE;
}
else
{
if( ginfo->IsRated )
team_index = BG_TEAM_HORDE; //for rated arenas use BG_TEAM_HORDE
}
//check if there is enought values(we always add values > 0)
if(m_WaitTimes[team_index][queue_id][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME - 1] )
return (m_SumOfWaitTimes[team_index][queue_id] / COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME);
else
//if there aren't enough values return 0 - not available
return 0;
}
//remove player from queue and from group info, if group info is empty then remove it too
void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCount)
{
@ -232,7 +291,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
@ -257,6 +316,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() )
{
@ -278,7 +353,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!
@ -355,13 +430,10 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b
// set invitation
ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID();
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
BGQueueIdBasedOnLevel queue_id = bg->GetQueueId();
// loop through the players
for(std::map<uint64,PlayerQueueInfo*>::iterator itr = ginfo->Players.begin(); itr != ginfo->Players.end(); ++itr)
{
// set status
itr->second->InviteTime = getMSTime();
itr->second->LastInviteTime = getMSTime();
// get the player
Player* plr = objmgr.GetPlayer(itr->first);
// if offline, skip him, this should not happen - player is removed from queue when he logs out
@ -369,6 +441,7 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b
continue;
// invite the player
PlayerInvitedToBGUpdateAverageWaitTime(ginfo, queue_id);
sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID(), bg->GetTypeID(), ginfo->Team);
WorldPacket data;
@ -378,7 +451,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;
@ -410,7 +483,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
@ -436,7 +508,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);
}
}
@ -499,7 +571,7 @@ void BattleGroundQueue::FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel
//if ali selection is already empty, then kick horde group, but if there are less horde than ali in bg - break;
if( !m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() )
{
if( aliFree <= diffHorde - 1 )
if( aliFree <= diffHorde + 1 )
break;
m_SelectionPools[BG_TEAM_HORDE].KickGroup(diffHorde - diffAli);
}
@ -514,7 +586,7 @@ void BattleGroundQueue::FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel
}
if( !m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() )
{
if( hordeFree <= diffAli - 1 )
if( hordeFree <= diffAli + 1 )
break;
m_SelectionPools[BG_TEAM_ALLIANCE].KickGroup(diffAli - diffHorde);
}
@ -622,7 +694,7 @@ bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BGQueueIdBas
return false;
}
//allow 1v0 if debug bg
if( sBattleGroundMgr.isTesting() && (m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() || m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount()) )
if( sBattleGroundMgr.isTesting() && bg_template->isBattleGround() && (m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() || m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount()) )
return true;
//return true if there are enough players in selection pools - enable to work .debug bg command correctly
return m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() >= minPlayers && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() >= minPlayers;
@ -995,7 +1067,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);
}
}
@ -1030,21 +1102,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);
}
}
@ -1075,10 +1137,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++)
{
@ -1086,6 +1148,8 @@ void BattleGroundMgr::DeleteAlllBattleGrounds()
{
BattleGround * bg = itr->second;
m_BattleGrounds[i].erase(itr++);
if(!m_ClientBattleGroundIds[i][bg->GetQueueId()].empty())
m_ClientBattleGroundIds[i][bg->GetQueueId()].erase(bg->GetClientInstanceID());
delete bg;
}
}
@ -1120,6 +1184,8 @@ void BattleGroundMgr::Update(uint32 diff)
{
BattleGround * bg = itr->second;
m_BattleGrounds[i].erase(itr);
if(!m_ClientBattleGroundIds[i][bg->GetQueueId()].empty())
m_ClientBattleGroundIds[i][bg->GetQueueId()].erase(bg->GetClientInstanceID());
delete bg;
}
}
@ -1160,7 +1226,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)
@ -1175,9 +1241,10 @@ void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGro
*data << uint32(QueueSlot); // queue id (0...2) - player can be in 3 queues in time
// uint64 in client
*data << uint64( uint64(arenatype ? arenatype : bg->GetArenaType()) | (uint64(0x0D) << 8) | (uint64(bg->GetTypeID()) << 16) | (uint64(0x1F90) << 48) );
*data << uint32(0); // unknown
*data << uint32(bg->GetClientInstanceID());
// 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
{
@ -1227,10 +1294,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)
@ -1386,10 +1450,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)
@ -1435,6 +1499,25 @@ void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID, BattleGro
plr->m_Events.AddEvent(removeEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME));
}
BattleGround * BattleGroundMgr::GetBattleGroundThroughClientInstance(uint32 instanceId, BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id)
{
//cause at HandleBattleGroundJoinOpcode the clients sends the instanceid he gets from
//SMSG_BATTLEFIELD_LIST we need to find the battleground with this clientinstance-id
BattleGround* bg = GetBattleGroundTemplate(bgTypeId);
if( !bg )
return NULL;
if(bg->isArena())
return GetBattleGround(instanceId, bgTypeId);
for(BattleGroundSet::iterator itr = m_BattleGrounds[bgTypeId].begin(); itr != m_BattleGrounds[bgTypeId].end(); ++itr)
{
if(itr->second->GetClientInstanceID() == instanceId)
return itr->second;
}
return NULL;
}
BattleGround * BattleGroundMgr::GetBattleGround(uint32 InstanceID, BattleGroundTypeId bgTypeId)
{
//search if needed
@ -1459,6 +1542,28 @@ BattleGround * BattleGroundMgr::GetBattleGroundTemplate(BattleGroundTypeId bgTyp
return m_BattleGrounds[bgTypeId].empty() ? NULL : m_BattleGrounds[bgTypeId].begin()->second;
}
uint32 BattleGroundMgr::CreateClientVisibleInstanceId(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id)
{
if( IsArenaType(bgTypeId) )
return 0; //arenas don't have client-instanceids
// we create here an instanceid, which is just for
// displaying this to the client and without any other use..
// the client-instanceIds are unique for each battleground-type
// the instance-id just needs to be as low as possible, beginning with 1
// the following works, because std::set is default ordered with "<"
// the optimalization would be to use as bitmask std::vector<uint32> - but that would only make code unreadable
uint32 lastId = 0;
for(std::set<uint32>::iterator itr = m_ClientBattleGroundIds[bgTypeId][queue_id].begin(); itr != m_ClientBattleGroundIds[bgTypeId][queue_id].end();)
{
if( (++lastId) != *itr) //if there is a gap between the ids, we will break..
break;
lastId = *itr;
}
m_ClientBattleGroundIds[bgTypeId][queue_id].insert(lastId + 1);
return lastId + 1;
}
// create a new battleground that will really be used to play
BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated)
{
@ -1528,6 +1633,7 @@ BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeI
// generate a new instance id
bg->SetInstanceID(MapManager::Instance().GenerateInstanceId()); // set instance id
bg->SetClientInstanceID(CreateClientVisibleInstanceId(bgTypeId, queue_id));
// reset the new bg (set status to status_wait_queue from status_none)
bg->Reset();
@ -1752,7 +1858,7 @@ void BattleGroundMgr::DistributeArenaPoints()
for (std::map<uint32, uint32>::iterator plr_itr = PlayerPoints.begin(); plr_itr != PlayerPoints.end(); ++plr_itr)
{
//update to database
CharacterDatabase.PExecute("UPDATE characters SET arena_pending_points = '%u' WHERE `guid` = '%u'", plr_itr->second, plr_itr->first);
CharacterDatabase.PExecute("UPDATE characters SET arena_pending_points = '%u' WHERE guid = '%u'", plr_itr->second, plr_itr->first);
//add points if player is online
Player* pl = objmgr.GetPlayer(plr_itr->first);
if (pl)
@ -1803,16 +1909,11 @@ void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, const uint6
uint32 count = 0;
*data << uint32(0x00); // number of bg instances
for(BattleGroundSet::iterator itr = m_BattleGrounds[bgTypeId].begin(); itr != m_BattleGrounds[bgTypeId].end(); ++itr)
uint32 queue_id = plr->GetBattleGroundQueueIdFromLevel(bgTypeId);
for(std::set<uint32>::iterator itr = m_ClientBattleGroundIds[bgTypeId][queue_id].begin(); itr != m_ClientBattleGroundIds[bgTypeId][queue_id].end();++itr)
{
// skip sending battleground template
if( itr == m_BattleGrounds[bgTypeId].begin() )
continue;
if( PlayerLevel >= itr->second->GetMinLevel() && PlayerLevel <= itr->second->GetMaxLevel() )
{
*data << uint32(itr->second->GetInstanceID());
++count;
}
*data << uint32(*itr);
++count;
}
data->put<uint32>( count_pos , count);
}

View file

@ -30,12 +30,11 @@ typedef std::list<BattleGround*> BGFreeSlotQueueType;
typedef UNORDERED_MAP<uint32, BattleGroundTypeId> BattleMastersMap;
#define BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY 86400 // seconds in a day
#define COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME 10
struct GroupQueueInfo; // type predefinition
struct PlayerQueueInfo // stores information for players in queue
{
uint32 InviteTime; // first invite time
uint32 LastInviteTime; // last invite time
uint32 LastOnlineTime; // for tracking and removing offline players from queue after 5 minutes
GroupQueueInfo * GroupInfo; // pointer to the associated groupqueueinfo
};
@ -79,6 +78,9 @@ class BattleGroundQueue
GroupQueueInfo * AddGroup(Player * leader, BattleGroundTypeId bgTypeId, uint8 ArenaType, bool isRated, bool isPremade, uint32 ArenaRating, uint32 ArenaTeamId = 0);
void AddPlayer(Player *plr, GroupQueueInfo *ginfo);
void RemovePlayer(const uint64& guid, bool decreaseInvitedCount);
void PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id);
uint32 GetAverageQueueWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id);
void DecreaseGroupLength(uint32 queueId, uint32 AsGroup);
void BGEndedRemoveInvites(BattleGround * bg);
void AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue);
@ -120,6 +122,9 @@ class BattleGroundQueue
private:
bool InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side);
uint32 m_WaitTimes[BG_TEAMS_COUNT][MAX_BATTLEGROUND_QUEUES][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME];
uint32 m_WaitTimeLastPlayer[BG_TEAMS_COUNT][MAX_BATTLEGROUND_QUEUES];
uint32 m_SumOfWaitTimes[BG_TEAMS_COUNT][MAX_BATTLEGROUND_QUEUES];
};
/*
@ -174,12 +179,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);
@ -188,18 +193,20 @@ class BattleGroundMgr
void InvitePlayer(Player* plr, uint32 bgInstanceGUID, BattleGroundTypeId bgTypeId, uint32 team);
/* Battlegrounds */
BattleGround* GetBattleGroundThroughClientInstance(uint32 instanceId, BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id);
BattleGround* GetBattleGround(uint32 InstanceID, BattleGroundTypeId bgTypeId); //there must be uint32 because MAX_BATTLEGROUND_TYPE_ID means unknown
BattleGround * GetBattleGroundTemplate(BattleGroundTypeId bgTypeId);
BattleGround * CreateNewBattleGround(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated);
BattleGround* GetBattleGroundTemplate(BattleGroundTypeId bgTypeId);
BattleGround* CreateNewBattleGround(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated);
uint32 CreateBattleGround(BattleGroundTypeId bgTypeId, bool IsArena, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam, uint32 LevelMin, uint32 LevelMax, char* BattleGroundName, uint32 MapID, float Team1StartLocX, float Team1StartLocY, float Team1StartLocZ, float Team1StartLocO, float Team2StartLocX, float Team2StartLocY, float Team2StartLocZ, float Team2StartLocO);
void AddBattleGround(uint32 InstanceID, BattleGroundTypeId bgTypeId, BattleGround* BG) { m_BattleGrounds[bgTypeId][InstanceID] = BG; };
void RemoveBattleGround(uint32 instanceID, BattleGroundTypeId bgTypeId) { m_BattleGrounds[bgTypeId].erase(instanceID); }
uint32 CreateClientVisibleInstanceId(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id);
void CreateInitialBattleGrounds();
void DeleteAlllBattleGrounds();
void DeleteAllBattleGrounds();
void SendToBattleGround(Player *pl, uint32 InstanceID, BattleGroundTypeId bgTypeId);
@ -240,6 +247,7 @@ class BattleGroundMgr
/* Battlegrounds */
BattleGroundSet m_BattleGrounds[MAX_BATTLEGROUND_TYPE_ID];
std::set<uint32> m_ClientBattleGroundIds[MAX_BATTLEGROUND_TYPE_ID][MAX_BATTLEGROUND_QUEUES]; //the instanceids just visible for the client
uint32 m_NextRatingDiscardUpdate;
uint64 m_NextAutoDistributionTime;
uint32 m_AutoDistributionTimeChecker;

View file

@ -20,15 +20,23 @@
#include "Player.h"
#include "BattleGround.h"
#include "BattleGroundNA.h"
#include "Creature.h"
#include "ObjectMgr.h"
#include "MapManager.h"
#include "WorldPacket.h"
#include "Language.h"
BattleGroundNA::BattleGroundNA()
{
m_BgObjects.resize(BG_NA_OBJECT_MAX);
m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattleGroundNA::~BattleGroundNA()
@ -40,70 +48,27 @@ void BattleGroundNA::Update(uint32 diff)
{
BattleGround::Update(diff);
// after bg start we get there
if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize())
{
ModifyStartDelayTime(diff);
if (!(m_Events & 0x01))
{
m_Events |= 0x01;
// setup here, only when at least one player has ported to the map
if(!SetupBattleGround())
{
EndNow();
return;
}
for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_4; i++)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
SetStartDelayTime(START_DELAY1);
SendMessageToAll(LANG_ARENA_ONE_MINUTE);
}
// After 30 seconds, warning is signalled
else if (GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x04))
{
m_Events |= 0x04;
SendMessageToAll(LANG_ARENA_THIRTY_SECONDS);
}
// After 15 seconds, warning is signalled
else if (GetStartDelayTime() <= START_DELAY3 && !(m_Events & 0x08))
{
m_Events |= 0x08;
SendMessageToAll(LANG_ARENA_FIFTEEN_SECONDS);
}
// delay expired (1 minute)
else if (GetStartDelayTime() <= 0 && !(m_Events & 0x10))
{
m_Events |= 0x10;
for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_2; i++)
DoorOpen(i);
for(uint32 i = BG_NA_OBJECT_BUFF_1; i <= BG_NA_OBJECT_BUFF_2; i++)
SpawnBGObject(i, 60);
SendMessageToAll(LANG_ARENA_BEGUN);
SetStatus(STATUS_IN_PROGRESS);
SetStartDelayTime(0);
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);
}
}
/*if(GetStatus() == STATUS_IN_PROGRESS)
{
// update something
}*/
}
void BattleGroundNA::StartingEventCloseDoors()
{
for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_4; i++)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
}
void BattleGroundNA::StartingEventOpenDoors()
{
for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_2; i++)
DoorOpen(i);
for(uint32 i = BG_NA_OBJECT_BUFF_1; i <= BG_NA_OBJECT_BUFF_2; i++)
SpawnBGObject(i, 60);
}
void BattleGroundNA::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);
@ -124,10 +89,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)
@ -146,16 +108,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)

View file

@ -60,6 +60,8 @@ class BattleGroundNA : public BattleGround
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
void RemovePlayer(Player *plr, uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);

View file

@ -20,15 +20,23 @@
#include "Player.h"
#include "BattleGround.h"
#include "BattleGroundRL.h"
#include "Creature.h"
#include "ObjectMgr.h"
#include "MapManager.h"
#include "Language.h"
#include "WorldPacket.h"
BattleGroundRL::BattleGroundRL()
{
m_BgObjects.resize(BG_RL_OBJECT_MAX);
m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattleGroundRL::~BattleGroundRL()
@ -40,71 +48,27 @@ void BattleGroundRL::Update(uint32 diff)
{
BattleGround::Update(diff);
if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize())
{
ModifyStartDelayTime(diff);
if (!(m_Events & 0x01))
{
m_Events |= 0x01;
// setup here, only when at least one player has ported to the map
if(!SetupBattleGround())
{
EndNow();
return;
}
for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
SetStartDelayTime(START_DELAY1);
SendMessageToAll(LANG_ARENA_ONE_MINUTE);
}
// After 30 seconds, warning is signalled
else if (GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x04))
{
m_Events |= 0x04;
SendMessageToAll(LANG_ARENA_THIRTY_SECONDS);
}
// After 15 seconds, warning is signalled
else if (GetStartDelayTime() <= START_DELAY3 && !(m_Events & 0x08))
{
m_Events |= 0x08;
SendMessageToAll(LANG_ARENA_FIFTEEN_SECONDS);
}
// delay expired (1 minute)
else if (GetStartDelayTime() <= 0 && !(m_Events & 0x10))
{
m_Events |= 0x10;
for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++)
DoorOpen(i);
for(uint32 i = BG_RL_OBJECT_BUFF_1; i <= BG_RL_OBJECT_BUFF_2; i++)
SpawnBGObject(i, 60);
SendMessageToAll(LANG_ARENA_BEGUN);
SetStatus(STATUS_IN_PROGRESS);
SetStartDelayTime(0);
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);
}
}
/*if(GetStatus() == STATUS_IN_PROGRESS)
{
// update something
}*/
}
void BattleGroundRL::StartingEventCloseDoors()
{
for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
}
void BattleGroundRL::StartingEventOpenDoors()
{
for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++)
DoorOpen(i);
for(uint32 i = BG_RL_OBJECT_BUFF_1; i <= BG_RL_OBJECT_BUFF_2; i++)
SpawnBGObject(i, 60);
}
void BattleGroundRL::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);
@ -125,10 +89,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)
@ -147,16 +108,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)

View file

@ -58,6 +58,8 @@ class BattleGroundRL : public BattleGround
virtual void AddPlayer(Player *plr);
virtual void Reset();
virtual void FillInitialWorldStates(WorldPacket &d);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
void RemovePlayer(Player *plr, uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);

View file

@ -19,10 +19,20 @@
#include "Player.h"
#include "BattleGround.h"
#include "BattleGroundRV.h"
#include "Language.h"
BattleGroundRV::BattleGroundRV()
{
m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattleGroundRV::~BattleGroundRV()
@ -35,6 +45,14 @@ void BattleGroundRV::Update(uint32 diff)
BattleGround::Update(diff);
}
void BattleGroundRV::StartingEventCloseDoors()
{
}
void BattleGroundRV::StartingEventOpenDoors()
{
}
void BattleGroundRV::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);

View file

@ -39,6 +39,9 @@ class BattleGroundRV : public BattleGround
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
void RemovePlayer(Player *plr, uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);
bool SetupBattleGround();

View file

@ -16,13 +16,18 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Player.h"
#include "BattleGround.h"
#include "BattleGroundSA.h"
#include "Player.h"
#include "Language.h"
BattleGroundSA::BattleGroundSA()
{
//TODO FIX ME!
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN;
}
BattleGroundSA::~BattleGroundSA()
@ -35,6 +40,14 @@ void BattleGroundSA::Update(uint32 diff)
BattleGround::Update(diff);
}
void BattleGroundSA::StartingEventCloseDoors()
{
}
void BattleGroundSA::StartingEventOpenDoors()
{
}
void BattleGroundSA::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);

View file

@ -39,6 +39,8 @@ class BattleGroundSA : public BattleGround
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
void RemovePlayer(Player *plr,uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);

View file

@ -22,8 +22,6 @@
#include "BattleGroundWS.h"
#include "Creature.h"
#include "GameObject.h"
#include "Chat.h"
#include "MapManager.h"
#include "ObjectMgr.h"
#include "WorldPacket.h"
#include "Language.h"
@ -32,6 +30,11 @@ BattleGroundWS::BattleGroundWS()
{
m_BgObjects.resize(BG_WS_OBJECT_MAX);
m_BgCreatures.resize(BG_CREATURES_MAX_WS);
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN;
}
BattleGroundWS::~BattleGroundWS()
@ -42,75 +45,7 @@ void BattleGroundWS::Update(uint32 diff)
{
BattleGround::Update(diff);
// after bg start we get there (once)
if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize())
{
ModifyStartDelayTime(diff);
if(!(m_Events & 0x01))
{
m_Events |= 0x01;
// setup here, only when at least one player has ported to the map
if(!SetupBattleGround())
{
EndNow();
return;
}
// for(uint32 i = WS_SPIRIT_MAIN_ALLIANCE; i <= WS_SPIRIT_MAIN_HORDE; i++)
// SpawnBGCreature(i, RESPAWN_IMMEDIATELY);
for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_H_4; i++)
{
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
DoorClose(i);
}
for(uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; i++)
SpawnBGObject(i, RESPAWN_ONE_DAY);
SetStartDelayTime(START_DELAY0);
}
// After 1 minute, warning is signalled
else if(GetStartDelayTime() <= START_DELAY1 && !(m_Events & 0x04))
{
m_Events |= 0x04;
SendMessageToAll(GetMangosString(LANG_BG_WS_ONE_MINUTE));
}
// After 1,5 minute, warning is signalled
else if(GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x08))
{
m_Events |= 0x08;
SendMessageToAll(GetMangosString(LANG_BG_WS_HALF_MINUTE));
}
// After 2 minutes, gates OPEN ! x)
else if(GetStartDelayTime() < 0 && !(m_Events & 0x10))
{
m_Events |= 0x10;
for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_A_4; i++)
DoorOpen(i);
for(uint32 i = BG_WS_OBJECT_DOOR_H_1; i <= BG_WS_OBJECT_DOOR_H_2; i++)
DoorOpen(i);
SpawnBGObject(BG_WS_OBJECT_DOOR_A_5, RESPAWN_ONE_DAY);
SpawnBGObject(BG_WS_OBJECT_DOOR_A_6, RESPAWN_ONE_DAY);
SpawnBGObject(BG_WS_OBJECT_DOOR_H_3, RESPAWN_ONE_DAY);
SpawnBGObject(BG_WS_OBJECT_DOOR_H_4, RESPAWN_ONE_DAY);
for(uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; i++)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
SendMessageToAll(GetMangosString(LANG_BG_WS_BEGIN));
PlaySoundToAll(SOUND_BG_START);
SetStatus(STATUS_IN_PROGRESS);
for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
if(Player* plr = objmgr.GetPlayer(itr->first))
plr->RemoveAurasDueToSpell(SPELL_PREPARATION);
}
}
else if(GetStatus() == STATUS_IN_PROGRESS)
if(GetStatus() == STATUS_IN_PROGRESS)
{
if(m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_WAIT_RESPAWN)
{
@ -155,6 +90,33 @@ void BattleGroundWS::Update(uint32 diff)
}
}
void BattleGroundWS::StartingEventCloseDoors()
{
for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_H_4; i++)
{
DoorClose(i);
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
}
for(uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; i++)
SpawnBGObject(i, RESPAWN_ONE_DAY);
}
void BattleGroundWS::StartingEventOpenDoors()
{
for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_A_4; i++)
DoorOpen(i);
for(uint32 i = BG_WS_OBJECT_DOOR_H_1; i <= BG_WS_OBJECT_DOOR_H_2; i++)
DoorOpen(i);
SpawnBGObject(BG_WS_OBJECT_DOOR_A_5, RESPAWN_ONE_DAY);
SpawnBGObject(BG_WS_OBJECT_DOOR_A_6, RESPAWN_ONE_DAY);
SpawnBGObject(BG_WS_OBJECT_DOOR_H_3, RESPAWN_ONE_DAY);
SpawnBGObject(BG_WS_OBJECT_DOOR_H_4, RESPAWN_ONE_DAY);
for(uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; i++)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
}
void BattleGroundWS::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);
@ -182,7 +144,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));
SendMessageToAll(LANG_BG_WS_F_PLACED, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED); // flag respawned sound...
}
}
@ -196,12 +158,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));
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));
SendMessageToAll(LANG_BG_WS_HORDE_FLAG_RESPAWNED, CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED);
@ -220,11 +182,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)
@ -236,13 +194,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 = GetMangosString(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, 35, ALLIANCE); // +35 reputation
RewardHonorToTeam(40, ALLIANCE); // +40 bonushonor
RewardReputationToTeam(890, m_ReputationCapture, ALLIANCE);
}
else
{
@ -253,26 +208,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 = GetMangosString(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, 35, HORDE); // +35 reputation
RewardHonorToTeam(40, 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;
@ -324,8 +279,6 @@ void BattleGroundWS::EventPlayerDroppedFlag(Player *Source)
return;
}
const char *message = "";
uint8 type = 0;
bool set = false;
if(Source->GetTeam() == ALLIANCE)
@ -337,8 +290,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 = GetMangosString(LANG_BG_WS_DROPPED_HF);
type = CHAT_MSG_BG_SYSTEM_HORDE;
Source->CastSpell(Source, BG_WS_SPELL_WARSONG_FLAG_DROPPED, true);
set = true;
}
@ -352,8 +303,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 = GetMangosString(LANG_BG_WS_DROPPED_AF);
type = CHAT_MSG_BG_SYSTEM_ALLIANCE;
Source->CastSpell(Source, BG_WS_SPELL_SILVERWING_FLAG_DROPPED, true);
set = true;
}
@ -364,14 +313,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;
}
@ -382,14 +333,14 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target
if(GetStatus() != STATUS_IN_PROGRESS)
return;
const char *message = NULL;
uint8 type = 0;
int32 message_id = 0;
ChatMsg type;
//alliance flag picked up from base
if(Source->GetTeam() == HORDE && GetFlagState(ALLIANCE) == BG_WS_FLAG_STATE_ON_BASE
&& m_BgObjects[BG_WS_OBJECT_A_FLAG] == target_obj->GetGUID())
{
message = GetMangosString(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);
@ -405,7 +356,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target
if (Source->GetTeam() == ALLIANCE && GetFlagState(HORDE) == BG_WS_FLAG_STATE_ON_BASE
&& m_BgObjects[BG_WS_OBJECT_H_FLAG] == target_obj->GetGUID())
{
message = GetMangosString(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);
@ -422,7 +373,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target
{
if(Source->GetTeam() == ALLIANCE)
{
message = GetMangosString(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);
@ -432,7 +383,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target
}
else
{
message = GetMangosString(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);
@ -451,7 +402,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target
{
if(Source->GetTeam() == HORDE)
{
message = GetMangosString(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);
@ -461,7 +412,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target
}
else
{
message = GetMangosString(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);
@ -475,12 +426,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);
}
@ -642,16 +591,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)
@ -684,6 +650,29 @@ void BattleGroundWS::UpdatePlayerScore(Player *Source, uint32 type, uint32 value
}
}
WorldSafeLocsEntry const* BattleGroundWS::GetClosestGraveYard(Player* player)
{
//if status in progress, it returns main graveyards with spiritguides
//else it will return the graveyard in the flagroom - this is especially good
//if a player dies in preparation phase - then the player can't cheat
//and teleport to the graveyard outside the flagroom
//and start running around, while the doors are still closed
if(player->GetTeam() == ALLIANCE)
{
if(GetStatus() == STATUS_IN_PROGRESS)
return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_ALLIANCE);
else
return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_FLAGROOM_ALLIANCE);
}
else
{
if(GetStatus() == STATUS_IN_PROGRESS)
return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_HORDE);
else
return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_FLAGROOM_HORDE);
}
}
void BattleGroundWS::FillInitialWorldStates(WorldPacket& data)
{
data << uint32(BG_WS_FLAG_CAPTURES_ALLIANCE) << uint32(GetTeamScore(ALLIANCE));

View file

@ -105,8 +105,10 @@ enum BG_WS_FlagState
enum BG_WS_Graveyards
{
WS_GRAVEYARD_MAIN_ALLIANCE = 771,
WS_GRAVEYARD_MAIN_HORDE = 772
WS_GRAVEYARD_FLAGROOM_ALLIANCE = 769,
WS_GRAVEYARD_FLAGROOM_HORDE = 770,
WS_GRAVEYARD_MAIN_ALLIANCE = 771,
WS_GRAVEYARD_MAIN_HORDE = 772
};
enum BG_WS_CreatureTypes
@ -138,6 +140,8 @@ class BattleGroundWS : public BattleGround
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
/* BG Flags */
uint64 GetAllianceFlagPickerGUID() const { return m_FlagKeepers[BG_TEAM_ALLIANCE]; }
@ -160,6 +164,8 @@ 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);
void UpdateTeamScore(uint32 team);
@ -181,5 +187,9 @@ class BattleGroundWS : public BattleGround
uint32 m_TeamScores[2];
int32 m_FlagsTimer[2];
int32 m_FlagsDropTimer[2];
uint32 m_ReputationCapture;
uint32 m_HonorWinKills;
uint32 m_HonorEndKills;
};
#endif

View file

@ -21,7 +21,6 @@
#include "Common.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "Opcodes.h"
#include "Player.h"

View file

@ -29,7 +29,6 @@
#include "Guild.h"
#include "UpdateMask.h"
#include "Auth/md5.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "Group.h"
#include "Database/DatabaseImpl.h"

View file

@ -28,7 +28,6 @@
#include "Player.h"
#include "UpdateMask.h"
#include "Chat.h"
#include "MapManager.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
#include "AccountMgr.h"
@ -418,26 +417,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 },
{ "factionid", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFactionIdCommand, "", NULL },
{ "flag", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFlagCommand, "", 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 },
{ "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 },
{ "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 },
{ "info", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcInfoCommand, "", NULL },
{ "playemote", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcPlayEmoteCommand, "", NULL },
{ "follow", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFollowCommand, "", NULL },
{ "setphase", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetPhaseCommand, "", 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 },
@ -445,9 +443,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 }

View file

@ -176,10 +176,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);
@ -187,6 +191,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);
@ -197,7 +202,12 @@ class ChatHandler
bool HandleNpcUnFollowCommand(const char* args);
bool HandleNpcWhisperCommand(const char* args);
bool HandleNpcYellCommand(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);
@ -300,13 +310,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);
@ -341,7 +346,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);

View file

@ -28,7 +28,6 @@
#include "ChannelMgr.h"
#include "Group.h"
#include "Guild.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "ScriptCalls.h"
#include "Player.h"
@ -522,44 +521,42 @@ void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data )
}
EmotesTextEntry const *em = sEmotesTextStore.LookupEntry(text_emote);
if (em)
if (!em)
return;
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit);
uint32 emote_anim = em->textid;
WorldPacket data;
switch(emote_anim)
{
uint32 emote_anim = em->textid;
WorldPacket data;
switch(emote_anim)
{
case EMOTE_STATE_SLEEP:
case EMOTE_STATE_SIT:
case EMOTE_STATE_KNEEL:
case EMOTE_ONESHOT_NONE:
break;
default:
GetPlayer()->HandleEmoteCommand(emote_anim);
break;
}
data.Initialize(SMSG_TEXT_EMOTE, (20+namlen));
data << GetPlayer()->GetGUID();
data << (uint32)text_emote;
data << emoteNum;
data << (uint32)namlen;
if( namlen > 1 )
{
data.append(nam, namlen);
}
else
{
data << (uint8)0x00;
}
GetPlayer()->SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true);
//Send scripted event call
if (pCreature && Script)
Script->ReceiveEmote(GetPlayer(),pCreature,text_emote);
case EMOTE_STATE_SLEEP:
case EMOTE_STATE_SIT:
case EMOTE_STATE_KNEEL:
case EMOTE_ONESHOT_NONE:
break;
default:
GetPlayer()->HandleEmoteCommand(emote_anim);
break;
}
data.Initialize(SMSG_TEXT_EMOTE, (20+namlen));
data << GetPlayer()->GetGUID();
data << (uint32)text_emote;
data << emoteNum;
data << (uint32)namlen;
if( namlen > 1 )
data.append(nam, namlen);
else
data << (uint8)0x00;
GetPlayer()->SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true);
//Send scripted event call
if (pCreature && Script)
Script->ReceiveEmote(GetPlayer(),pCreature,text_emote);
}
void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data )

View file

@ -20,7 +20,6 @@
#include "Log.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "World.h"
#include "ObjectAccessor.h"
#include "CreatureAI.h"
#include "ObjectDefines.h"

View file

@ -20,12 +20,9 @@
#include "Corpse.h"
#include "Player.h"
#include "UpdateMask.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "Database/DatabaseEnv.h"
#include "Opcodes.h"
#include "WorldSession.h"
#include "WorldPacket.h"
#include "GossipDef.h"
#include "World.h"

View file

@ -19,7 +19,6 @@
#include "Common.h"
#include "Database/DatabaseEnv.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "World.h"
#include "ObjectMgr.h"
#include "SpellMgr.h"
@ -35,7 +34,6 @@
#include "CreatureAI.h"
#include "CreatureAISelector.h"
#include "Formulas.h"
#include "SpellAuras.h"
#include "WaypointMovementGenerator.h"
#include "InstanceData.h"
#include "BattleGroundMgr.h"
@ -1564,7 +1562,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;
}
@ -1614,7 +1612,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;
}
@ -2117,4 +2115,4 @@ void Creature::SetActiveObjectState( bool on )
if(world)
map->Add(this);
}
}

View file

@ -16,7 +16,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "CreatureAIRegistry.h"
#include "NullCreatureAI.h"
#include "ReactorAI.h"
#include "AggressorAI.h"
@ -26,7 +25,6 @@
#include "RandomMovementGenerator.h"
#include "CreatureAIImpl.h"
#include "MovementGeneratorImpl.h"
#include "MapManager.h"
#include "CreatureAIRegistry.h"
#include "WaypointMovementGenerator.h"

View file

@ -19,7 +19,6 @@
#ifndef MANGOS_DESTINATIONHOLDERIMP_H
#define MANGOS_DESTINATIONHOLDERIMP_H
#include "Creature.h"
#include "MapManager.h"
#include "DestinationHolder.h"

View file

@ -19,11 +19,9 @@
#include "Common.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "World.h"
#include "Log.h"
#include "Opcodes.h"
#include "UpdateData.h"
#include "MapManager.h"
#include "Player.h"
void WorldSession::HandleDuelAcceptedOpcode(WorldPacket& recvPacket)

View file

@ -17,16 +17,11 @@
*/
#include "Common.h"
#include "GameObject.h"
#include "UpdateMask.h"
#include "Opcodes.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "World.h"
#include "ObjectAccessor.h"
#include "Database/DatabaseEnv.h"
#include "SpellAuras.h"
#include "MapManager.h"
#include "GridNotifiers.h"
#include "CellImpl.h"
#include "GridNotifiersImpl.h"

View file

@ -22,7 +22,6 @@
#include "MovementGenerator.h"
#include "DestinationHolder.h"
#include "Traveller.h"
#include "MapManager.h"
template<class T>
class MANGOS_DLL_SPEC FleeingMovementGenerator

View file

@ -119,7 +119,7 @@ void WorldSession::HandleGMTicketCreateOpcode( WorldPacket & recv_data )
data.Initialize( SMSG_GMTICKET_CREATE, 4 );
data << uint32(2);
SendPacket( &data );
DEBUG_LOG("update the ticket\n");
DEBUG_LOG("update the ticket");
//TODO: Guard player map
HashMapHolder<Player>::MapType &m = ObjectAccessor::Instance().GetPlayers();

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "GameEvent.h"
#include "GameEventMgr.h"
#include "World.h"
#include "ObjectMgr.h"
#include "PoolHandler.h"
@ -26,9 +26,9 @@
#include "MapManager.h"
#include "Policies/SingletonImp.h"
INSTANTIATE_SINGLETON_1(GameEvent);
INSTANTIATE_SINGLETON_1(GameEventMgr);
bool GameEvent::CheckOneGameEvent(uint16 entry) const
bool GameEventMgr::CheckOneGameEvent(uint16 entry) const
{
// Get the event information
time_t currenttime = time(NULL);
@ -39,7 +39,7 @@ bool GameEvent::CheckOneGameEvent(uint16 entry) const
return false;
}
uint32 GameEvent::NextCheck(uint16 entry) const
uint32 GameEventMgr::NextCheck(uint16 entry) const
{
time_t currenttime = time(NULL);
@ -65,7 +65,7 @@ uint32 GameEvent::NextCheck(uint16 entry) const
return delay;
}
void GameEvent::StartEvent( uint16 event_id, bool overwrite )
void GameEventMgr::StartEvent( uint16 event_id, bool overwrite )
{
AddActiveEvent(event_id);
ApplyNewEvent(event_id);
@ -77,7 +77,7 @@ void GameEvent::StartEvent( uint16 event_id, bool overwrite )
}
}
void GameEvent::StopEvent( uint16 event_id, bool overwrite )
void GameEventMgr::StopEvent( uint16 event_id, bool overwrite )
{
RemoveActiveEvent(event_id);
UnApplyEvent(event_id);
@ -89,7 +89,7 @@ void GameEvent::StopEvent( uint16 event_id, bool overwrite )
}
}
void GameEvent::LoadFromDB()
void GameEventMgr::LoadFromDB()
{
{
QueryResult *result = WorldDatabase.Query("SELECT MAX(entry) FROM game_event");
@ -108,7 +108,7 @@ void GameEvent::LoadFromDB()
mGameEvent.resize(max_event_id+1);
}
QueryResult *result = WorldDatabase.Query("SELECT entry,UNIX_TIMESTAMP(start_time),UNIX_TIMESTAMP(end_time),occurence,length,description FROM game_event");
QueryResult *result = WorldDatabase.Query("SELECT entry,UNIX_TIMESTAMP(start_time),UNIX_TIMESTAMP(end_time),occurence,length,holiday,description FROM game_event");
if( !result )
{
mGameEvent.clear();
@ -142,6 +142,8 @@ void GameEvent::LoadFromDB()
pGameEvent.end = time_t(endtime);
pGameEvent.occurence = fields[3].GetUInt32();
pGameEvent.length = fields[4].GetUInt32();
pGameEvent.holiday_id = fields[5].GetUInt32();
if(pGameEvent.length==0) // length>0 is validity check
{
@ -149,7 +151,16 @@ void GameEvent::LoadFromDB()
continue;
}
pGameEvent.description = fields[5].GetCppString();
if(pGameEvent.holiday_id)
{
if(!sHolidaysStore.LookupEntry(pGameEvent.holiday_id))
{
sLog.outErrorDb("`game_event` game event id (%i) have not existed holiday id %u.",event_id,pGameEvent.holiday_id);
pGameEvent.holiday_id = 0;
}
}
pGameEvent.description = fields[6].GetCppString();
} while( result->NextRow() );
delete result;
@ -405,7 +416,7 @@ void GameEvent::LoadFromDB()
}
}
uint32 GameEvent::Initialize() // return the next event delay in ms
uint32 GameEventMgr::Initialize() // return the next event delay in ms
{
m_ActiveEvents.clear();
uint32 delay = Update();
@ -414,7 +425,7 @@ uint32 GameEvent::Initialize() // return the next e
return delay;
}
uint32 GameEvent::Update() // return the next event delay in ms
uint32 GameEventMgr::Update() // return the next event delay in ms
{
uint32 nextEventDelay = max_ge_check_delay; // 1 day
uint32 calcDelay;
@ -450,7 +461,7 @@ uint32 GameEvent::Update() // return the next e
return (nextEventDelay + 1) * IN_MILISECONDS; // Add 1 second to be sure event has started/stopped at next call
}
void GameEvent::UnApplyEvent(uint16 event_id)
void GameEventMgr::UnApplyEvent(uint16 event_id)
{
sLog.outString("GameEvent %u \"%s\" removed.", event_id, mGameEvent[event_id].description.c_str());
// un-spawn positive event tagged objects
@ -464,7 +475,7 @@ void GameEvent::UnApplyEvent(uint16 event_id)
UpdateEventQuests(event_id, false);
}
void GameEvent::ApplyNewEvent(uint16 event_id)
void GameEventMgr::ApplyNewEvent(uint16 event_id)
{
switch(sWorld.getConfig(CONFIG_EVENT_ANNOUNCE))
{
@ -487,13 +498,13 @@ void GameEvent::ApplyNewEvent(uint16 event_id)
UpdateEventQuests(event_id, true);
}
void GameEvent::GameEventSpawn(int16 event_id)
void GameEventMgr::GameEventSpawn(int16 event_id)
{
int32 internal_event_id = mGameEvent.size() + event_id - 1;
if(internal_event_id < 0 || internal_event_id >= mGameEventCreatureGuids.size())
{
sLog.outError("GameEvent::GameEventSpawn attempt access to out of range mGameEventCreatureGuids element %i (size: %u)",internal_event_id,mGameEventCreatureGuids.size());
sLog.outError("GameEventMgr::GameEventSpawn attempt access to out of range mGameEventCreatureGuids element %i (size: %u)",internal_event_id,mGameEventCreatureGuids.size());
return;
}
@ -526,7 +537,7 @@ void GameEvent::GameEventSpawn(int16 event_id)
if(internal_event_id < 0 || internal_event_id >= mGameEventGameobjectGuids.size())
{
sLog.outError("GameEvent::GameEventSpawn attempt access to out of range mGameEventGameobjectGuids element %i (size: %u)",internal_event_id,mGameEventGameobjectGuids.size());
sLog.outError("GameEventMgr::GameEventSpawn attempt access to out of range mGameEventGameobjectGuids element %i (size: %u)",internal_event_id,mGameEventGameobjectGuids.size());
return;
}
@ -560,7 +571,7 @@ void GameEvent::GameEventSpawn(int16 event_id)
if(internal_event_id < 0 || internal_event_id >= mGameEventPoolIds.size())
{
sLog.outError("GameEvent::GameEventSpawn attempt access to out of range mGameEventPoolIds element %i (size: %u)",internal_event_id,mGameEventPoolIds.size());
sLog.outError("GameEventMgr::GameEventSpawn attempt access to out of range mGameEventPoolIds element %i (size: %u)",internal_event_id,mGameEventPoolIds.size());
return;
}
@ -570,13 +581,13 @@ void GameEvent::GameEventSpawn(int16 event_id)
}
}
void GameEvent::GameEventUnspawn(int16 event_id)
void GameEventMgr::GameEventUnspawn(int16 event_id)
{
int32 internal_event_id = mGameEvent.size() + event_id - 1;
if(internal_event_id < 0 || internal_event_id >= mGameEventCreatureGuids.size())
{
sLog.outError("GameEvent::GameEventUnspawn attempt access to out of range mGameEventCreatureGuids element %i (size: %u)",internal_event_id,mGameEventCreatureGuids.size());
sLog.outError("GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventCreatureGuids element %i (size: %u)",internal_event_id,mGameEventCreatureGuids.size());
return;
}
@ -597,7 +608,7 @@ void GameEvent::GameEventUnspawn(int16 event_id)
if(internal_event_id < 0 || internal_event_id >= mGameEventGameobjectGuids.size())
{
sLog.outError("GameEvent::GameEventUnspawn attempt access to out of range mGameEventGameobjectGuids element %i (size: %u)",internal_event_id,mGameEventGameobjectGuids.size());
sLog.outError("GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventGameobjectGuids element %i (size: %u)",internal_event_id,mGameEventGameobjectGuids.size());
return;
}
@ -614,7 +625,7 @@ void GameEvent::GameEventUnspawn(int16 event_id)
}
if(internal_event_id < 0 || internal_event_id >= mGameEventPoolIds.size())
{
sLog.outError("GameEvent::GameEventUnspawn attempt access to out of range mGameEventPoolIds element %i (size: %u)",internal_event_id,mGameEventPoolIds.size());
sLog.outError("GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventPoolIds element %i (size: %u)",internal_event_id,mGameEventPoolIds.size());
return;
}
@ -624,7 +635,7 @@ void GameEvent::GameEventUnspawn(int16 event_id)
}
}
void GameEvent::ChangeEquipOrModel(int16 event_id, bool activate)
void GameEventMgr::ChangeEquipOrModel(int16 event_id, bool activate)
{
for(ModelEquipList::iterator itr = mGameEventModelEquip[event_id].begin();itr != mGameEventModelEquip[event_id].end();++itr)
{
@ -703,7 +714,7 @@ void GameEvent::ChangeEquipOrModel(int16 event_id, bool activate)
}
}
void GameEvent::UpdateEventQuests(uint16 event_id, bool Activate)
void GameEventMgr::UpdateEventQuests(uint16 event_id, bool Activate)
{
QuestRelList::iterator itr;
for (itr = mGameEventQuests[event_id].begin();itr != mGameEventQuests[event_id].end();++itr)
@ -729,7 +740,19 @@ void GameEvent::UpdateEventQuests(uint16 event_id, bool Activate)
}
}
GameEvent::GameEvent()
GameEventMgr::GameEventMgr()
{
isSystemInit = false;
}
MANGOS_DLL_SPEC bool IsHolidayActive( HolidayIds id )
{
GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap();
GameEventMgr::ActiveEvents const& ae = gameeventmgr.GetActiveEventList();
for(GameEventMgr::ActiveEvents::const_iterator itr = ae.begin(); itr != ae.end(); ++itr)
if(events[id].holiday_id==id)
return true;
return false;
}

View file

@ -16,15 +16,18 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef MANGOS_GAMEEVENT_H
#define MANGOS_GAMEEVENT_H
#ifndef MANGOS_GAMEEVENT_MGR_H
#define MANGOS_GAMEEVENT_MGR_H
#include "Common.h"
#include "SharedDefines.h"
#include "Platform/Define.h"
#include "Creature.h"
#include "GameObject.h"
#define max_ge_check_delay 86400 // 1 day in seconds
class Creature;
class GameObject;
struct GameEventData
{
GameEventData() : start(1),end(0),occurence(0),length(0) {}
@ -32,6 +35,7 @@ struct GameEventData
time_t end;
uint32 occurence;
uint32 length;
uint32 holiday_id;
std::string description;
bool isValid() const { return length > 0; }
@ -45,11 +49,11 @@ struct ModelEquip
uint32 equipement_id_prev;
};
class GameEvent
class GameEventMgr
{
public:
GameEvent();
~GameEvent() {};
GameEventMgr();
~GameEventMgr() {};
typedef std::set<uint16> ActiveEvents;
typedef std::vector<GameEventData> GameEventDataMap;
ActiveEvents const& GetActiveEventList() const { return m_ActiveEvents; }
@ -92,5 +96,8 @@ class GameEvent
bool isSystemInit;
};
#define gameeventmgr MaNGOS::Singleton<GameEvent>::Instance()
#define gameeventmgr MaNGOS::Singleton<GameEventMgr>::Instance()
MANGOS_DLL_SPEC bool IsHolidayActive(HolidayIds id);
#endif

View file

@ -26,10 +26,8 @@
#include "UpdateMask.h"
#include "Opcodes.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "World.h"
#include "Database/DatabaseEnv.h"
#include "MapManager.h"
#include "LootMgr.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
@ -472,14 +470,15 @@ void GameObject::getFishLoot(Loot *fishloot, Player* loot_owner)
{
fishloot->clear();
uint32 subzone = GetAreaId();
uint32 zone, subzone;
GetZoneAndAreaId(zone,subzone);
// if subzone loot exist use it
if(LootTemplates_Fishing.HaveLootFor(subzone))
fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner,true);
// else use zone loot
else
fishloot->FillLoot(GetZoneId(), LootTemplates_Fishing, loot_owner,true);
fishloot->FillLoot(zone, LootTemplates_Fishing, loot_owner,true);
}
void GameObject::SaveToDB()
@ -1000,11 +999,12 @@ void GameObject::Use(Unit* user)
// 2) if skill == base_zone_skill => 5% chance
// 3) chance is linear dependence from (base_zone_skill-skill)
uint32 subzone = GetAreaId();
uint32 zone, subzone;
GetZoneAndAreaId(zone,subzone);
int32 zone_skill = objmgr.GetFishingBaseSkillLevel( subzone );
if(!zone_skill)
zone_skill = objmgr.GetFishingBaseSkillLevel( GetZoneId() );
zone_skill = objmgr.GetFishingBaseSkillLevel( zone );
//provide error, no fishable zone or area should be 0
if(!zone_skill)
@ -1174,7 +1174,7 @@ void GameObject::Use(Unit* user)
Player* player = (Player*)user;
if( player->isAllowUseBattleGroundObject() )
if( player->CanUseBattleGroundObject() )
{
// in battleground check
BattleGround *bg = player->GetBattleGround();
@ -1199,7 +1199,7 @@ void GameObject::Use(Unit* user)
Player* player = (Player*)user;
if( player->isAllowUseBattleGroundObject() )
if( player->CanUseBattleGroundObject() )
{
// in battleground check
BattleGround *bg = player->GetBattleGround();

View file

@ -22,7 +22,6 @@
#include "UpdateData.h"
#include "Item.h"
#include "Map.h"
#include "MapManager.h"
#include "Transports.h"
#include "ObjectAccessor.h"

View file

@ -862,6 +862,27 @@ namespace MaNGOS
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<> void PlayerRelocationNotifier::Visit<Creature>(CreatureMapType &);

View file

@ -562,4 +562,28 @@ void MaNGOS::LocalizedPacketDo<Builder>::operator()( Player* p )
p->SendDirectMessage(data);
}
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

View file

@ -18,7 +18,6 @@
#include "GridStates.h"
#include "GridNotifiers.h"
#include "ObjectAccessor.h"
#include "GameSystem/Grid.h"
#include "Log.h"

View file

@ -26,8 +26,6 @@
#include "ObjectMgr.h"
#include "Player.h"
#include "Group.h"
#include "ObjectAccessor.h"
#include "MapManager.h"
#include "SocialMgr.h"
#include "Util.h"
@ -215,26 +213,16 @@ void WorldSession::HandleGroupDeclineOpcode( WorldPacket & /*recv_data*/ )
Group *group = GetPlayer()->GetGroupInvite();
if (!group) return;
// remember leader if online
Player *leader = objmgr.GetPlayer(group->GetLeaderGUID());
/** error handling **/
// uninvite, group can be deleted
GetPlayer()->UninviteFromGroup();
if(!leader || !leader->GetSession())
return;
/********************/
// everything's fine, do it
if(!group->IsCreated())
{
// note: this means that if you invite more than one person
// and one of them declines before the first one accepts
// all invites will be cleared
// fixme: is that ok ?
group->RemoveAllInvites();
delete group;
}
GetPlayer()->SetGroupInvite(NULL);
// report
WorldPacket data( SMSG_GROUP_DECLINE, 10 ); // guess size
data << GetPlayer()->GetName();
leader->GetSession()->SendPacket( &data );

View file

@ -19,7 +19,6 @@
#include "Database/DatabaseEnv.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "MapManager.h"
#include "Player.h"
#include "Opcodes.h"
#include "ObjectMgr.h"
@ -27,6 +26,7 @@
#include "Chat.h"
#include "SocialMgr.h"
#include "Util.h"
#include "Language.h"
Guild::Guild()
{
@ -50,27 +50,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);
@ -88,18 +86,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);
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(lGuid, (uint32)GR_GUILDMASTER);
return AddMember(leaderGuid, (uint32)GR_GUILDMASTER);
}
bool Guild::AddMember(uint64 plGuid, uint32 plRank)

View file

@ -267,7 +267,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;

View file

@ -24,7 +24,6 @@
#include "Log.h"
#include "Opcodes.h"
#include "Guild.h"
#include "MapManager.h"
#include "GossipDef.h"
#include "SocialMgr.h"
@ -63,7 +62,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;

View file

@ -20,8 +20,6 @@
#include "Creature.h"
#include "CreatureAI.h"
#include "Traveller.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "DestinationHolderImp.h"
#include "ObjectMgr.h"
#include "WorldPacket.h"

View file

@ -17,7 +17,7 @@
*/
#include "IdleMovementGenerator.h"
#include "Creature.h"
#include "Unit.h"
IdleMovementGenerator si_idleMovement;

View file

@ -16,13 +16,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "InstanceSaveMgr.h"
#include "Common.h"
#include "Database/SQLStorage.h"
#include "Player.h"
#include "GridNotifiers.h"
#include "WorldSession.h"
#include "Log.h"
#include "GridStates.h"
#include "CellImpl.h"
@ -34,7 +32,6 @@
#include "GridNotifiersImpl.h"
#include "Config/ConfigEnv.h"
#include "Transports.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "World.h"
#include "Group.h"

View file

@ -19,7 +19,6 @@
#include "Common.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "World.h"
#include "Opcodes.h"
#include "Log.h"
#include "ObjectMgr.h"

View file

@ -170,7 +170,8 @@ enum MangosStrings
LANG_CONSOLE_COMMAND = 172,
LANG_YOU_CHANGE_RUNIC_POWER = 173,
LANG_YOURS_RUNIC_POWER_CHANGED = 174,
// Room for more level 1 175-199 not used
LANG_LIQUID_STATUS = 175,
// Room for more level 1 176-199 not used
// level 2 chat
LANG_NO_SELECTION = 200,
@ -569,9 +570,11 @@ enum MangosStrings
// Battleground
LANG_BG_A_WINS = 600,
LANG_BG_H_WINS = 601,
LANG_BG_WS_ONE_MINUTE = 602,
LANG_BG_WS_HALF_MINUTE = 603,
LANG_BG_WS_BEGIN = 604,
LANG_BG_WS_START_TWO_MINUTES = 753,
LANG_BG_WS_START_ONE_MINUTE = 602,
LANG_BG_WS_START_HALF_MINUTE = 603,
LANG_BG_WS_HAS_BEGUN = 604,
LANG_BG_WS_CAPTURED_HF = 605,
LANG_BG_WS_CAPTURED_AF = 606,
@ -585,9 +588,10 @@ enum MangosStrings
LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED = 614,
LANG_BG_WS_HORDE_FLAG_RESPAWNED = 615,
LANG_BG_EY_ONE_MINUTE = 636,
LANG_BG_EY_HALF_MINUTE = 637,
LANG_BG_EY_BEGIN = 638,
LANG_BG_EY_START_TWO_MINUTES = 755,
LANG_BG_EY_START_ONE_MINUTE = 636,
LANG_BG_EY_START_HALF_MINUTE = 637,
LANG_BG_EY_HAS_BEGUN = 638,
LANG_BG_AB_ALLY = 650,
LANG_BG_AB_HORDE = 651,
@ -600,9 +604,11 @@ enum MangosStrings
LANG_BG_AB_NODE_DEFENDED = 658,
LANG_BG_AB_NODE_ASSAULTED = 659,
LANG_BG_AB_NODE_CLAIMED = 660,
LANG_BG_AB_ONEMINTOSTART = 661,
LANG_BG_AB_HALFMINTOSTART = 662,
LANG_BG_AB_STARTED = 663,
LANG_BG_AB_START_TWO_MINUTES = 754,
LANG_BG_AB_START_ONE_MINUTE = 661,
LANG_BG_AB_START_HALF_MINUTE = 662,
LANG_BG_AB_HAS_BEGUN = 663,
LANG_BG_AB_A_NEAR_VICTORY = 664,
LANG_BG_AB_H_NEAR_VICTORY = 665,
LANG_BG_MARK_BY_MAIL = 666,
@ -633,7 +639,7 @@ enum MangosStrings
LANG_ARENA_ONE_MINUTE = 701,
LANG_ARENA_THIRTY_SECONDS = 702,
LANG_ARENA_FIFTEEN_SECONDS = 703,
LANG_ARENA_BEGUN = 704,
LANG_ARENA_HAS_BEGUN = 704,
LANG_WAIT_BEFORE_SPEAKING = 705,
LANG_NOT_EQUIPPED_ITEM = 706,
@ -658,7 +664,7 @@ enum MangosStrings
LANG_ARENA_NOT_ENOUGH_PLAYERS = 723, // "Your group does not have enough players to join this match."
LANG_ARENA_GOLD_WINS = 724, // "The Gold Team wins!"
LANG_ARENA_GREEN_WINS = 725, // "The Green Team wins!"
LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 726, // The battleground will end soon, because there aren't enough players. Get more ppl or win already!
// = 726, not used
LANG_BG_GROUP_OFFLINE_MEMBER = 727, // "Your group has an offline member. Please remove him before joining."
LANG_BG_GROUP_MIXED_FACTION = 728, // "Your group has players from the opposing faction. You can't join the battleground as a group."
LANG_BG_GROUP_MIXED_LEVELS = 729, // "Your group has players from different battleground brakets. You can't join as group."
@ -680,7 +686,16 @@ enum MangosStrings
LANG_DIST_ARENA_POINTS_TEAM_START = 744,
LANG_DIST_ARENA_POINTS_TEAM_END = 745,
LANG_DIST_ARENA_POINTS_END = 746,
// Room for batleground/arena strings 747-799 not used
// = 747, not used
// = 748, not used
// = 749, not used
LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 750, // "Not enough players. This game will close in %u mins."
LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS = 751, // "Not enough players. This game will close in %u seconds."
// = 752, not used
// LANG_BG_WS_START_TWO_MINUTES = 753,
// LANG_BG_AB_START_TWO_MINUTES = 754,
// LANG_BG_EY_START_TWO_MINUTES = 755,
// Room for batleground/arena strings 756-799 not used
// in game strings
// = 800, not used
@ -694,7 +709,12 @@ enum MangosStrings
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,

View file

@ -18,13 +18,10 @@
#include "Common.h"
#include "Database/DatabaseEnv.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "World.h"
#include "Player.h"
#include "Opcodes.h"
#include "Chat.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "Language.h"
#include "AccountMgr.h"

View file

@ -36,6 +36,7 @@
#include "VMapFactory.h"
#endif
//-----------------------Npc Commands-----------------------
bool ChatHandler::HandleNpcSayCommand(const char* args)
{
if(!*args)
@ -119,6 +120,7 @@ bool ChatHandler::HandleNpcWhisperCommand(const char* args)
return true;
}
//----------------------------------------------------------
// global announce
bool ChatHandler::HandleAnnounceCommand(const char* args)
@ -282,8 +284,8 @@ bool ChatHandler::HandleGPSCommand(const char* args)
CellPair cell_val = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY());
Cell cell(cell_val);
uint32 zone_id = obj->GetZoneId();
uint32 area_id = obj->GetAreaId();
uint32 zone_id, area_id;
obj->GetZoneAndAreaId(zone_id,area_id);
MapEntry const* mapEntry = sMapStore.LookupEntry(obj->GetMapId());
AreaTableEntry const* zoneEntry = GetAreaEntryByAreaID(zone_id);
@ -329,6 +331,12 @@ bool ChatHandler::HandleGPSCommand(const char* args)
cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), obj->GetInstanceId(),
zone_x, zone_y, ground_z, floor_z, have_map, have_vmap );
LiquidData liquid_status;
ZLiquidStatus res = map->getLiquidStatus(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), MAP_ALL_LIQUIDS, &liquid_status);
if (res)
{
PSendSysMessage(LANG_LIQUID_STATUS, liquid_status.level, liquid_status.depth_level, liquid_status.type, res);
}
return true;
}

File diff suppressed because it is too large Load diff

View file

@ -33,7 +33,6 @@
#include "Guild.h"
#include "ObjectAccessor.h"
#include "MapManager.h"
#include "SpellAuras.h"
#include "ScriptCalls.h"
#include "Language.h"
#include "GridNotifiersImpl.h"
@ -3066,7 +3065,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);
@ -3261,77 +3260,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();
@ -3592,7 +3520,7 @@ bool ChatHandler::HandleLinkGraveCommand(const char* args)
return false;
}
if(objmgr.AddGraveYardLink(g_id,player->GetZoneId(),g_team))
if(objmgr.AddGraveYardLink(g_id,zoneId,g_team))
PSendSysMessage(LANG_COMMAND_GRAVEYARDLINKED, g_id,zoneId);
else
PSendSysMessage(LANG_COMMAND_GRAVEYARDALRLINKED, g_id,zoneId);
@ -3616,6 +3544,7 @@ bool ChatHandler::HandleNearGraveCommand(const char* args)
return false;
Player* player = m_session->GetPlayer();
uint32 zone_id = player->GetZoneId();
WorldSafeLocsEntry const* graveyard = objmgr.GetClosestGraveYard(
player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(),player->GetMapId(),g_team);
@ -3624,7 +3553,7 @@ bool ChatHandler::HandleNearGraveCommand(const char* args)
{
uint32 g_id = graveyard->ID;
GraveYardData const* data = objmgr.FindGraveYardData(g_id,player->GetZoneId());
GraveYardData const* data = objmgr.FindGraveYardData(g_id,zone_id);
if (!data)
{
PSendSysMessage(LANG_COMMAND_GRAVEYARDERROR,g_id);
@ -3643,7 +3572,7 @@ bool ChatHandler::HandleNearGraveCommand(const char* args)
else if(g_team == ALLIANCE)
team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_ALLIANCE);
PSendSysMessage(LANG_COMMAND_GRAVEYARDNEAREST, g_id,team_name.c_str(),player->GetZoneId());
PSendSysMessage(LANG_COMMAND_GRAVEYARDNEAREST, g_id,team_name.c_str(),zone_id);
}
else
{
@ -3657,29 +3586,36 @@ bool ChatHandler::HandleNearGraveCommand(const char* args)
team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_ALLIANCE);
if(g_team == ~uint32(0))
PSendSysMessage(LANG_COMMAND_ZONENOGRAVEYARDS, player->GetZoneId());
PSendSysMessage(LANG_COMMAND_ZONENOGRAVEYARDS, zone_id);
else
PSendSysMessage(LANG_COMMAND_ZONENOGRAFACTION, player->GetZoneId(),team_name.c_str());
PSendSysMessage(LANG_COMMAND_ZONENOGRAFACTION, zone_id,team_name.c_str());
}
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;
}
@ -3728,6 +3664,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)
@ -5686,30 +5711,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)

View file

@ -114,11 +114,18 @@ void LootStore::LoadLootTable()
float chanceOrQuestChance = fields[2].GetFloat();
uint8 group = fields[3].GetUInt8();
int32 mincountOrRef = fields[4].GetInt32();
uint8 maxcount = fields[5].GetUInt8();
uint32 maxcount = fields[5].GetUInt32();
ConditionType condition = (ConditionType)fields[6].GetUInt8();
uint32 cond_value1 = fields[7].GetUInt32();
uint32 cond_value2 = fields[8].GetUInt32();
if(maxcount > std::numeric_limits<uint8>::max())
{
sLog.outErrorDb("Table '%s' entry %d item %d: maxcount value (%u) to large. must be less %u - skipped", GetName(), entry, item, maxcount,std::numeric_limits<uint8>::max());
continue; // error already printed to log/console.
}
if(!PlayerCondition::IsValid(condition,cond_value1, cond_value2))
{
sLog.outErrorDb("... in table '%s' entry %u item %u", GetName(), entry, item);
@ -248,6 +255,12 @@ bool LootStoreItem::Roll(bool rate) const
// Checks correctness of values
bool LootStoreItem::IsValid(LootStore const& store, uint32 entry) const
{
if(group >= 1 << 7) // it stored in 7 bit field
{
sLog.outErrorDb("Table '%s' entry %d item %d: group (%u) must be less %u - skipped", store.GetName(), entry, itemid, group, 1 << 7);
return false;
}
if (mincountOrRef == 0)
{
sLog.outErrorDb("Table '%s' entry %d item %d: wrong mincountOrRef (%d) - skipped", store.GetName(), entry, itemid, mincountOrRef);

View file

@ -63,17 +63,17 @@ struct LootStoreItem
uint32 itemid; // id of the item
float chance; // always positive, chance to drop for both quest and non-quest items, chance to be used for refs
int32 mincountOrRef; // mincount for drop items (positive) or minus referenced TemplateleId (negative)
uint8 group :8;
uint8 group :7;
bool needs_quest :1; // quest drop (negative ChanceOrQuestChance in DB)
uint8 maxcount :8; // max drop count for the item (mincountOrRef positive) or Ref multiplicator (mincountOrRef negative)
uint16 conditionId :16; // additional loot condition Id
bool needs_quest :1; // quest drop (negative ChanceOrQuestChance in DB)
// Constructor, converting ChanceOrQuestChance -> (chance, needs_quest)
// displayid is filled in IsValid() which must be called after
LootStoreItem(uint32 _itemid, float _chanceOrQuestChance, int8 _group, uint8 _conditionId, int32 _mincountOrRef, uint8 _maxcount)
: itemid(_itemid), chance(fabs(_chanceOrQuestChance)), mincountOrRef(_mincountOrRef),
group(_group), maxcount(_maxcount), conditionId(_conditionId),
needs_quest(_chanceOrQuestChance < 0) {}
group(_group), needs_quest(_chanceOrQuestChance < 0), maxcount(_maxcount), conditionId(_conditionId)
{}
bool Roll(bool rate) const; // Checks if the entry takes it's chance (at loot generation)
bool IsValid(LootStore const& store, uint32 entry) const;

View file

@ -109,8 +109,8 @@ libmangosgame_a_SOURCES = \
FleeingMovementGenerator.cpp \
FleeingMovementGenerator.h \
Formulas.h \
GameEvent.cpp \
GameEvent.h \
GameEventMgr.cpp \
GameEventMgr.h \
GameObject.cpp \
GameObject.h \
GlobalEvents.cpp \

View file

@ -19,7 +19,6 @@
#include "MapManager.h"
#include "Player.h"
#include "GridNotifiers.h"
#include "WorldSession.h"
#include "Log.h"
#include "GridStates.h"
#include "CellImpl.h"
@ -42,9 +41,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()
@ -67,9 +63,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;
@ -79,7 +75,6 @@ bool Map::ExistMap(uint32 mapid,int x,int y)
delete [] tmp;
fclose(pf);
return true;
}
@ -158,29 +153,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)
@ -1032,7 +1011,11 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool pForce)
{
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);
}
@ -1057,94 +1040,527 @@ void Map::UnloadAll(bool pForce)
}
}
float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const
//*****************************
// Grid function
//*****************************
GridMap::GridMap()
{
GridPair p = MaNGOS::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;
}
GridMap::~GridMap()
{
unloadData();
}
bool GridMap::loadData(char *filename)
{
// Unload old data if exist
unloadData();
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;
}
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))
{
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
{
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;
}
}
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
float lx=MAP_RESOLUTION*(32 -x/SIZE_OF_GRIDS - gx);
float ly=MAP_RESOLUTION*(32 -y/SIZE_OF_GRIDS - gy);
// ensure GridMap is loaded
const_cast<Map*>(this)->EnsureGridCreated(GridPair(63-gx,63-gy));
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 = GridMaps[gx][gy])
if(GridMap *gmap = const_cast<Map*>(this)->GetGrid(x, y))
{
int lx_int = (int)lx;
int ly_int = (int)ly;
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)
{
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;
}
}
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;
}
}
// Calculate height
float _mapheight = a * lx + b * ly + c;
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)
@ -1203,25 +1619,9 @@ float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const
uint16 Map::GetAreaFlag(float x, float y, float z) const
{
//local x,y coords
float lx,ly;
int gx,gy;
GridPair p = MaNGOS::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);
@ -1240,6 +1640,11 @@ uint16 Map::GetAreaFlag(float x, float y, float z) const
case 856: // The Noxious Glade (Eastern Plaguelands)
case 2456: // Death's Breach (Eastern Plaguelands)
if(z > 350.0f) areaflag = 1950; break;
// Dalaran
case 1593:
case 2484:
case 2492:
if( (x < 6116 && x > 5568) && (y < 982 && y > 282) && z > 563.0f) areaflag = 2153; break;
}
return areaflag;
@ -1247,49 +1652,29 @@ 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;
}
ZLiquidStatus Map::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data) const
{
if(GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
return gmap->getLiquidStatus(x, y, z, ReqLiquidType, data);
else
return LIQUID_MAP_NO_WATER;
}
float Map::GetWaterLevel(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=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(GridMaps[gx][gy])
return GridMaps[gx][gy]->liquid_level[(int)(lx)][(int)(ly)];
if(GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
return gmap->getLiquidLevel(x, y);
else
return 0;
}
uint32 Map::GetAreaId(uint16 areaflag,uint32 map_id)
uint32 Map::GetAreaIdByAreaFlag(uint16 areaflag,uint32 map_id)
{
AreaTableEntry const *entry = GetAreaEntryByAreaFlagAndMap(areaflag,map_id);
@ -1299,7 +1684,7 @@ uint32 Map::GetAreaId(uint16 areaflag,uint32 map_id)
return 0;
}
uint32 Map::GetZoneId(uint16 areaflag,uint32 map_id)
uint32 Map::GetZoneIdByAreaFlag(uint16 areaflag,uint32 map_id)
{
AreaTableEntry const *entry = GetAreaEntryByAreaFlagAndMap(areaflag,map_id);
@ -1309,26 +1694,37 @@ uint32 Map::GetZoneId(uint16 areaflag,uint32 map_id)
return 0;
}
void Map::GetZoneAndAreaIdByAreaFlag(uint32& zoneid, uint32& areaid, uint16 areaflag,uint32 map_id)
{
AreaTableEntry const *entry = GetAreaEntryByAreaFlagAndMap(areaflag,map_id);
areaid = entry ? entry->ID : 0;
zoneid = entry ? (( entry->zone != 0 ) ? entry->zone : entry->ID) : 0;
}
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
@ -1817,7 +2213,6 @@ bool InstanceMap::Add(Player *player)
// first player enters (no players yet)
SetResetSchedule(false);
player->SendInitWorldStates();
sLog.outDetail("MAP: Player '%s' entered the instance '%u' of map '%s'", player->GetName(), GetInstanceId(), GetMapName());
// initialize unload state
m_unloadTimer = 0;
@ -1933,7 +2328,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;
}

View file

@ -68,14 +68,135 @@ typedef RGuard<GridRWLock, ZThread::Lockable> GridReadGuard;
typedef WGuard<GridRWLock, ZThread::Lockable> GridWriteGuard;
typedef MaNGOS::SingleThreaded<GridRWLock>::Lock NullGuard;
typedef struct
//******************************************
// Map file format defines
//******************************************
#define MAP_MAGIC 'SPAM'
#define MAP_VERSION_MAGIC '0.1w'
#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
{
@ -190,22 +311,30 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
float GetHeight(float x, float y, float z, bool pCheckVMap=true) 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;
bool IsUnderWater(float x, float y, float z) const;
static uint32 GetAreaId(uint16 areaflag,uint32 map_id);
static uint32 GetZoneId(uint16 areaflag,uint32 map_id);
static uint32 GetAreaIdByAreaFlag(uint16 areaflag,uint32 map_id);
static uint32 GetZoneIdByAreaFlag(uint16 areaflag,uint32 map_id);
static void GetZoneAndAreaIdByAreaFlag(uint32& zoneid, uint32& areaid, uint16 areaflag,uint32 map_id);
uint32 GetAreaId(float x, float y, float z) const
{
return GetAreaId(GetAreaFlag(x,y,z),i_id);
return GetAreaIdByAreaFlag(GetAreaFlag(x,y,z),i_id);
}
uint32 GetZoneId(float x, float y, float z) const
{
return GetZoneId(GetAreaFlag(x,y,z),i_id);
return GetZoneIdByAreaFlag(GetAreaFlag(x,y,z),i_id);
}
void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const
{
GetZoneAndAreaIdByAreaFlag(zoneid,areaid,GetAreaFlag(x,y,z),i_id);
}
virtual void MoveAllCreaturesInMoveList();
@ -277,6 +406,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
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;

View file

@ -50,8 +50,18 @@ class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton<MapManager, MaNGOS::
Map const* m = GetBaseMap(mapid);
return m->GetAreaFlag(x, y, z);
}
uint32 GetAreaId(uint32 mapid, float x, float y, float z) const { return Map::GetAreaId(GetAreaFlag(mapid, x, y, z),mapid); }
uint32 GetZoneId(uint32 mapid, float x, float y, float z) const { return Map::GetZoneId(GetAreaFlag(mapid, x, y, z),mapid); }
uint32 GetAreaId(uint32 mapid, float x, float y, float z) const
{
return Map::GetAreaIdByAreaFlag(GetAreaFlag(mapid, x, y, z),mapid);
}
uint32 GetZoneId(uint32 mapid, float x, float y, float z) const
{
return Map::GetZoneIdByAreaFlag(GetAreaFlag(mapid, x, y, z),mapid);
}
void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, uint32 mapid, float x, float y, float z)
{
Map::GetZoneAndAreaIdByAreaFlag(zoneid,areaid,GetAreaFlag(mapid, x, y, z),mapid);
}
void Initialize(void);
void Update(uint32);

View file

@ -34,11 +34,9 @@
#include "Chat.h"
#include "ScriptCalls.h"
#include <zlib/zlib.h>
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "Object.h"
#include "BattleGround.h"
#include "SpellAuras.h"
#include "Pet.h"
#include "SocialMgr.h"
@ -386,10 +384,10 @@ void WorldSession::HandleZoneUpdateOpcode( WorldPacket & recv_data )
sLog.outDetail("WORLD: Recvd ZONE_UPDATE: %u", newZone);
if(newZone != _player->GetZoneId())
GetPlayer()->SendInitWorldStates(); // only if really enters to new zone, not just area change, works strange...
GetPlayer()->UpdateZone(newZone);
// use server size data
uint32 newzone, newarea;
GetPlayer()->GetZoneAndAreaId(newzone,newarea);
GetPlayer()->UpdateZone(newzone,newarea);
}
void WorldSession::HandleSetTargetOpcode( WorldPacket & recv_data )
@ -859,8 +857,16 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data)
}
uint32 missingQuest = 0;
if(at->requiredQuest && !GetPlayer()->GetQuestRewardStatus(at->requiredQuest))
missingQuest = at->requiredQuest;
if(GetPlayer()->GetDifficulty() == DIFFICULTY_HEROIC)
{
if (at->requiredQuestHeroic && !GetPlayer()->GetQuestRewardStatus(at->requiredQuestHeroic))
missingQuest = at->requiredQuestHeroic;
}
else
{
if(at->requiredQuest && !GetPlayer()->GetQuestRewardStatus(at->requiredQuest))
missingQuest = at->requiredQuest;
}
if(missingLevel || missingItem || missingKey || missingQuest)
{

View file

@ -21,9 +21,9 @@
#include "WorldSession.h"
#include "Opcodes.h"
#include "Log.h"
#include "World.h"
#include "Corpse.h"
#include "Player.h"
#include "Vehicle.h"
#include "MapManager.h"
#include "Transports.h"
#include "BattleGround.h"

View file

@ -23,17 +23,14 @@
#include "WorldSession.h"
#include "Opcodes.h"
#include "Log.h"
#include "World.h"
#include "ObjectMgr.h"
#include "SpellMgr.h"
#include "Player.h"
#include "GossipDef.h"
#include "SpellAuras.h"
#include "UpdateMask.h"
#include "ScriptCalls.h"
#include "ObjectAccessor.h"
#include "Creature.h"
#include "MapManager.h"
#include "Pet.h"
#include "BattleGroundMgr.h"
#include "BattleGround.h"
@ -436,11 +433,12 @@ void WorldSession::HandleBinderActivateOpcode( WorldPacket & recv_data )
void WorldSession::SendBindPoint(Creature *npc)
{
uint32 bindspell = 3286;
uint32 zone_id = _player->GetZoneId();
// update sql homebind
CharacterDatabase.PExecute("UPDATE character_homebind SET map = '%u', zone = '%u', position_x = '%f', position_y = '%f', position_z = '%f' WHERE guid = '%u'", _player->GetMapId(), _player->GetZoneId(), _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetGUIDLow());
CharacterDatabase.PExecute("UPDATE character_homebind SET map = '%u', zone = '%u', position_x = '%f', position_y = '%f', position_z = '%f' WHERE guid = '%u'", _player->GetMapId(), zone_id, _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetGUIDLow());
_player->m_homebindMapId = _player->GetMapId();
_player->m_homebindZoneId = _player->GetZoneId();
_player->m_homebindZoneId = zone_id;
_player->m_homebindX = _player->GetPositionX();
_player->m_homebindY = _player->GetPositionY();
_player->m_homebindZ = _player->GetPositionZ();
@ -459,19 +457,19 @@ void WorldSession::SendBindPoint(Creature *npc)
data << float(_player->GetPositionY());
data << float(_player->GetPositionZ());
data << uint32(_player->GetMapId());
data << uint32(_player->GetZoneId());
data << uint32(zone_id);
SendPacket( &data );
DEBUG_LOG("New Home Position X is %f",_player->GetPositionX());
DEBUG_LOG("New Home Position Y is %f",_player->GetPositionY());
DEBUG_LOG("New Home Position Z is %f",_player->GetPositionZ());
DEBUG_LOG("New Home MapId is %u",_player->GetMapId());
DEBUG_LOG("New Home ZoneId is %u",_player->GetZoneId());
DEBUG_LOG("New Home ZoneId is %u",zone_id);
// zone update
data.Initialize( SMSG_PLAYERBOUND, 8+4 );
data << uint64(_player->GetGUID());
data << uint32(_player->GetZoneId());
data << uint32(zone_id);
SendPacket( &data );
_player->PlayerTalkClass->CloseGossip();

View file

@ -25,8 +25,8 @@
#include "Object.h"
#include "Creature.h"
#include "Player.h"
#include "Vehicle.h"
#include "ObjectMgr.h"
#include "WorldSession.h"
#include "UpdateData.h"
#include "UpdateMask.h"
#include "Util.h"
@ -1096,6 +1096,11 @@ uint32 WorldObject::GetAreaId() const
return MapManager::Instance().GetBaseMap(m_mapId)->GetAreaId(m_positionX,m_positionY,m_positionZ);
}
void WorldObject::GetZoneAndAreaId(uint32& zoneid, uint32& areaid) const
{
MapManager::Instance().GetBaseMap(m_mapId)->GetZoneAndAreaId(zoneid,areaid,m_positionX,m_positionY,m_positionZ);
}
InstanceData* WorldObject::GetInstanceData()
{
Map *map = GetMap();

View file

@ -414,6 +414,7 @@ class MANGOS_DLL_SPEC WorldObject : public Object
uint32 GetZoneId() const;
uint32 GetAreaId() const;
void GetZoneAndAreaId(uint32& zoneid, uint32& areaid) const;
InstanceData* GetInstanceData();

View file

@ -23,8 +23,7 @@
#include "Creature.h"
#include "GameObject.h"
#include "DynamicObject.h"
#include "Corpse.h"
#include "WorldSession.h"
#include "Vehicle.h"
#include "WorldPacket.h"
#include "Item.h"
#include "Corpse.h"
@ -409,7 +408,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);

View file

@ -31,7 +31,6 @@
#include "GridDefines.h"
#include "Object.h"
#include "Player.h"
#include "Vehicle.h"
#include <set>
@ -40,6 +39,7 @@ class Corpse;
class Unit;
class GameObject;
class DynamicObject;
class Vehicle;
class WorldObject;
class Map;

View file

@ -19,7 +19,6 @@
#include "ObjectGridLoader.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "MapManager.h"
#include "Creature.h"
#include "GameObject.h"
#include "DynamicObject.h"

View file

@ -28,14 +28,13 @@
#include "SpellMgr.h"
#include "UpdateMask.h"
#include "World.h"
#include "WorldSession.h"
#include "Group.h"
#include "Guild.h"
#include "ArenaTeam.h"
#include "Transports.h"
#include "ProgressBar.h"
#include "Language.h"
#include "GameEvent.h"
#include "GameEventMgr.h"
#include "Spell.h"
#include "Chat.h"
#include "AccountMgr.h"
@ -43,7 +42,6 @@
#include "SpellAuras.h"
#include "Util.h"
#include "WaypointManager.h"
#include "BattleGround.h"
INSTANTIATE_SINGLETON_1(ObjectMgr);
@ -1767,7 +1765,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 mangosd.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)
@ -2146,7 +2147,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 mangosd.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;
}
@ -2241,7 +2245,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 mangosd.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;
}
@ -2349,7 +2356,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
@ -3273,14 +3283,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
@ -3298,14 +3309,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);
}
}
@ -4850,8 +4862,8 @@ void ObjectMgr::LoadAreaTriggerTeleports()
uint32 count = 0;
// 0 1 2 3 4 5 6 7 8 9 10 11 12
QueryResult *result = WorldDatabase.Query("SELECT id, required_level, required_item, required_item2, heroic_key, heroic_key2, required_quest_done, required_failed_text, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM areatrigger_teleport");
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13
QueryResult *result = WorldDatabase.Query("SELECT id, required_level, required_item, required_item2, heroic_key, heroic_key2, required_quest_done, required_quest_done_heroic, required_failed_text, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM areatrigger_teleport");
if( !result )
{
@ -4878,18 +4890,19 @@ void ObjectMgr::LoadAreaTriggerTeleports()
AreaTrigger at;
at.requiredLevel = fields[1].GetUInt8();
at.requiredItem = fields[2].GetUInt32();
at.requiredItem2 = fields[3].GetUInt32();
at.heroicKey = fields[4].GetUInt32();
at.heroicKey2 = fields[5].GetUInt32();
at.requiredQuest = fields[6].GetUInt32();
at.requiredFailedText = fields[7].GetCppString();
at.target_mapId = fields[8].GetUInt32();
at.target_X = fields[9].GetFloat();
at.target_Y = fields[10].GetFloat();
at.target_Z = fields[11].GetFloat();
at.target_Orientation = fields[12].GetFloat();
at.requiredLevel = fields[1].GetUInt8();
at.requiredItem = fields[2].GetUInt32();
at.requiredItem2 = fields[3].GetUInt32();
at.heroicKey = fields[4].GetUInt32();
at.heroicKey2 = fields[5].GetUInt32();
at.requiredQuest = fields[6].GetUInt32();
at.requiredQuestHeroic = fields[7].GetUInt32();
at.requiredFailedText = fields[8].GetCppString();
at.target_mapId = fields[9].GetUInt32();
at.target_X = fields[10].GetFloat();
at.target_Y = fields[11].GetFloat();
at.target_Z = fields[12].GetFloat();
at.target_Orientation = fields[13].GetFloat();
AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID);
if(!atEntry)
@ -4939,13 +4952,24 @@ void ObjectMgr::LoadAreaTriggerTeleports()
if(at.requiredQuest)
{
if(!mQuestTemplates[at.requiredQuest])
QuestMap::iterator qReqItr = mQuestTemplates.find(at.requiredQuest);
if(qReqItr == mQuestTemplates.end())
{
sLog.outErrorDb("Required Quest %u not exist for trigger %u, remove quest done requirement.",at.requiredQuest,Trigger_ID);
at.requiredQuest = 0;
}
}
if(at.requiredQuestHeroic)
{
QuestMap::iterator qReqItr = mQuestTemplates.find(at.requiredQuestHeroic);
if(qReqItr == mQuestTemplates.end())
{
sLog.outErrorDb("Required Quest %u not exist for trigger %u, remove quest done requirement.",at.requiredQuestHeroic,Trigger_ID);
at.requiredQuestHeroic = 0;
}
}
MapEntry const* mapEntry = sMapStore.LookupEntry(at.target_mapId);
if(!mapEntry)
{
@ -6692,7 +6716,7 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
}
case CONDITION_ACTIVE_EVENT:
{
GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap();
if(value1 >=events.size() || !events[value1].isValid())
{
sLog.outErrorDb("Active event condition requires existed event id (%u), skipped", value1);

View file

@ -103,6 +103,7 @@ struct AreaTrigger
uint32 heroicKey;
uint32 heroicKey2;
uint32 requiredQuest;
uint32 requiredQuestHeroic;
std::string requiredFailedText;
uint32 target_mapId;
float target_X;

View file

@ -19,12 +19,10 @@
#include "Common.h"
#include "Database/DatabaseEnv.h"
#include "Log.h"
#include "WorldSession.h"
#include "WorldPacket.h"
#include "ObjectMgr.h"
#include "SpellMgr.h"
#include "Pet.h"
#include "MapManager.h"
#include "Formulas.h"
#include "SpellAuras.h"
#include "CreatureAI.h"

View file

@ -19,18 +19,15 @@
#include "Common.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "World.h"
#include "ObjectMgr.h"
#include "SpellMgr.h"
#include "Log.h"
#include "Opcodes.h"
#include "Spell.h"
#include "ObjectAccessor.h"
#include "MapManager.h"
#include "CreatureAI.h"
#include "Util.h"
#include "Pet.h"
#include "Language.h"
void WorldSession::HandlePetAction( WorldPacket & recv_data )
{
@ -47,16 +44,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;
}
@ -146,7 +143,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
@ -174,7 +171,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;
}
@ -264,7 +261,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);
}
}
@ -272,7 +269,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;
@ -312,7 +309,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;
@ -331,7 +328,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;
}
@ -349,7 +346,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)))
@ -381,7 +378,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;
@ -499,7 +496,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;
}
@ -534,7 +531,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;
}
@ -586,7 +583,7 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
if(!pet || (pet != _player->GetPet() && pet!= _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;
}
@ -596,7 +593,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;
}

View file

@ -26,7 +26,6 @@
#include "Opcodes.h"
#include "Guild.h"
#include "ArenaTeam.h"
#include "MapManager.h"
#include "GossipDef.h"
#include "SocialMgr.h"
@ -825,7 +824,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;

View file

@ -21,13 +21,13 @@
#include "Database/DatabaseEnv.h"
#include "Log.h"
#include "Opcodes.h"
#include "ObjectMgr.h"
#include "SpellMgr.h"
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "UpdateMask.h"
#include "Player.h"
#include "Vehicle.h"
#include "SkillDiscovery.h"
#include "QuestDef.h"
#include "GossipDef.h"
@ -47,7 +47,6 @@
#include "Group.h"
#include "Guild.h"
#include "Pet.h"
#include "SpellAuras.h"
#include "Util.h"
#include "Transports.h"
#include "Weather.h"
@ -348,8 +347,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;
@ -794,25 +796,14 @@ bool Player::StoreNewItemInBestSlots(uint32 titem_id, uint32 titem_amount)
return false;
}
void Player::StartMirrorTimer(MirrorTimerType Type, uint32 MaxValue)
void Player::SendMirrorTimer(MirrorTimerType Type, uint32 MaxValue, uint32 CurrentValue, int32 Regen)
{
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)
{
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;
@ -825,9 +816,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 );
@ -838,12 +827,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);
@ -863,96 +862,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;
}
uint32 UnderWaterTime = 3*MINUTE*IN_MILISECONDS; // default duration
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);
if ((m_isunderwater & UNDERWATER_INWATER) && !(m_isunderwater & UNDERWATER_INLAVA) && isAlive())
{
//single trigger timer
if (!(m_isunderwater & UNDERWATER_WATER_TRIGGER))
case FATIGUE_TIMER:
return MINUTE*IN_MILISECONDS;
case BREATH_TIMER:
{
m_isunderwater|= UNDERWATER_WATER_TRIGGER;
m_breathTimer = UnderWaterTime + 1*IN_MILISECONDS;
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;
}
//single trigger "show Breathbar"
if ( m_breathTimer <= UnderWaterTime && !(m_isunderwater & UNDERWATER_WATER_BREATHB))
case FIRE_TIMER:
{
m_isunderwater|= UNDERWATER_WATER_BREATHB;
StartMirrorTimer(BREATH_TIMER, UnderWaterTime);
}
//continuous trigger drowning "Damage"
if ((m_breathTimer == 0) && (m_isunderwater & UNDERWATER_INWATER))
{
//TODO: Check this formula
uint64 guid = GetGUID();
uint32 damage = GetMaxHealth() / 5 + urand(0, getLevel()-1);
EnvironmentalDamage(guid, DAMAGE_DROWNING,damage);
m_breathTimer = 2000;
if (!isAlive())
return DISABLED_MIRROR_TIMER;
return 1*IN_MILISECONDS;
}
default:
return 0;
}
//single trigger retract bar
else if (!(m_isunderwater & UNDERWATER_INWATER) && (m_isunderwater & UNDERWATER_WATER_TRIGGER) && (m_breathTimer > 0) && isAlive())
{
uint32 BreathRegen = 10;
// m_breathTimer will be reduced in ModifyMirrorTimer
ModifyMirrorTimer(BREATH_TIMER, UnderWaterTime, m_breathTimer,BreathRegen);
m_isunderwater = UNDERWATER_WATER_BREATHB_RETRACTING;
}
//remove bar
else if ((m_breathTimer < 50) && !(m_isunderwater & UNDERWATER_INWATER) && (m_isunderwater == UNDERWATER_WATER_BREATHB_RETRACTING))
{
StopMirrorTimer(BREATH_TIMER);
m_isunderwater = UNDERWATER_NONE;
}
return 0;
}
void Player::HandleLava()
void Player::UpdateMirrorTimers()
{
if ((m_isunderwater & UNDERWATER_INLAVA) && isAlive())
// Desync flags for update on next HandleDrowning
if (m_MirrorTimerFlags)
m_MirrorTimerFlagsLast = ~m_MirrorTimerFlags;
}
void Player::HandleDrowning(uint32 time_diff)
{
if (!m_MirrorTimerFlags)
return;
// In water
if (m_MirrorTimerFlags & UNDERWATER_INWATER)
{
/*
* arrai: how is this supposed to work? UNDERWATER_INLAVA is always set in this scope!
// Single trigger Set BreathTimer
if (!(m_isunderwater & UNDERWATER_INLAVA))
// Breath timer not activated - activate it
if (m_MirrorTimer[BREATH_TIMER] == DISABLED_MIRROR_TIMER)
{
m_isunderwater|= UNDERWATER_WATER_BREATHB;
m_breathTimer = 1*IN_MILISECONDS;
m_MirrorTimer[BREATH_TIMER] = getMaxTimer(BREATH_TIMER);
SendMirrorTimer(BREATH_TIMER, m_MirrorTimer[BREATH_TIMER], m_MirrorTimer[BREATH_TIMER], -1);
}
*/
// Reset BreathTimer and still in the lava
if (!m_breathTimer)
else // If activated - do tick
{
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[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);
}
}
else if (!isAlive()) // Disable breath timer and reset underwater flags
else if (m_MirrorTimer[BREATH_TIMER] != DISABLED_MIRROR_TIMER) // Regen timer
{
m_breathTimer = 0;
m_isunderwater = UNDERWATER_NONE;
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);
}
// In dark water
if (m_MirrorTimerFlags & UNDERWARER_INDARKWATER)
{
// Fatigue timer not activated - activate it
if (m_MirrorTimer[FATIGUE_TIMER] == DISABLED_MIRROR_TIMER)
{
m_MirrorTimer[FATIGUE_TIMER] = getMaxTimer(FATIGUE_TIMER);
SendMirrorTimer(FATIGUE_TIMER, m_MirrorTimer[FATIGUE_TIMER], m_MirrorTimer[FATIGUE_TIMER], -1);
}
else
{
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 (m_MirrorTimer[FATIGUE_TIMER] != DISABLED_MIRROR_TIMER) // Regen timer
{
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
@ -1182,14 +1238,15 @@ void Player::Update( uint32 p_time )
{
if(p_time >= m_zoneUpdateTimer)
{
uint32 newzone = GetZoneId();
uint32 newzone, newarea;
GetZoneAndAreaId(newzone,newarea);
if( m_zoneUpdateId != newzone )
UpdateZone(newzone); // also update area
UpdateZone(newzone,newarea); // also update area
else
{
// use area updates as well
// needed for free far all arenas for example
uint32 newarea = GetAreaId();
if( m_areaUpdateId != newarea )
UpdateArea(newarea);
@ -1224,21 +1281,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)
@ -1606,16 +1650,19 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
}
}
uint32 newzone, newarea;
GetZoneAndAreaId(newzone,newarea);
if(!GetSession()->PlayerLogout())
{
// don't reset teleport semaphore while logging out, otherwise m_teleport_dest won't be used in Player::SaveToDB
SetSemaphoreTeleport(false);
UpdateZone(GetZoneId());
UpdateZone(newzone,newarea);
}
// new zone
if(old_zone != GetZoneId())
if(old_zone != newzone)
{
// honorless target
if(pvpInfo.inHostileArea)
@ -2070,7 +2117,7 @@ void Player::UninviteFromGroup()
group->RemoveInvite(this);
if(group->GetMembersCount() <= 1) // group has just 1 member => disband
if(group->GetMembersCount() <= 1) // group has just 1 member => disband
{
if(group->IsCreated())
{
@ -3883,7 +3930,9 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness)
}
// trigger update zone for alive state zone updates
UpdateZone(GetZoneId());
uint32 newzone, newarea;
GetZoneAndAreaId(newzone,newarea);
UpdateZone(newzone,newarea);
// update visibility
ObjectAccessor::UpdateVisibilityForPlayer(this);
@ -6318,13 +6367,16 @@ void Player::UpdateArea(uint32 newArea)
UpdateAreaDependentAuras(newArea);
}
void Player::UpdateZone(uint32 newZone)
void Player::UpdateZone(uint32 newZone, uint32 newArea)
{
if(m_zoneUpdateId != newZone)
SendInitWorldStates(newZone, newArea); // only if really enters to new zone, not just area change, works strange...
m_zoneUpdateId = newZone;
m_zoneUpdateTimer = ZONE_UPDATE_INTERVAL;
// zone changed, so area changed as well, update it
UpdateArea(GetAreaId());
UpdateArea(newArea);
AreaTableEntry const* zone = GetAreaEntryByAreaID(newZone);
if(!zone)
@ -7682,15 +7734,15 @@ void Player::SendUpdateWorldState(uint32 Field, uint32 Value)
GetSession()->SendPacket(&data);
}
void Player::SendInitWorldStates()
void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
{
// data depends on zoneid/mapid...
BattleGround* bg = GetBattleGround();
uint16 NumberOfFields = 0;
uint32 mapid = GetMapId();
uint32 zoneid = GetZoneId();
uint32 areaid = GetAreaId();
sLog.outDebug("Sending SMSG_INIT_WORLD_STATES to Map:%u, Zone: %u", mapid, zoneid);
// may be exist better way to do this...
switch(zoneid)
{
@ -12658,8 +12710,8 @@ void Player::AddQuest( Quest const *pQuest, Object *questGiver )
SpellAreaForQuestMapBounds saBounds = spellmgr.GetSpellAreaForQuestMapBounds(quest_id,true);
if(saBounds.first != saBounds.second)
{
uint32 zone = GetZoneId();
uint32 area = GetAreaId();
uint32 zone, area;
GetZoneAndAreaId(zone,area);
for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
if(itr->second->autocast && itr->second->IsFitToRequirements(this,zone,area))
@ -12873,8 +12925,7 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
SpellAreaForQuestMapBounds saEndBounds = spellmgr.GetSpellAreaForQuestEndMapBounds(quest_id);
if(saEndBounds.first != saEndBounds.second)
{
uint32 zone = GetZoneId();
uint32 area = GetAreaId();
GetZoneAndAreaId(zone,area);
for(SpellAreaForAreaMap::const_iterator itr = saEndBounds.first; itr != saEndBounds.second; ++itr)
if(!itr->second->IsFitToRequirements(this,zone,area))
@ -12885,8 +12936,8 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
SpellAreaForQuestMapBounds saBounds = spellmgr.GetSpellAreaForQuestMapBounds(quest_id,false);
if(saBounds.first != saBounds.second)
{
if(!zone) zone = GetZoneId();
if(!area) area = GetAreaId();
if(!zone || !area)
GetZoneAndAreaId(zone,area);
for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
if(itr->second->autocast && itr->second->IsFitToRequirements(this,zone,area))
@ -14297,7 +14348,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());
@ -15635,7 +15686,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;
@ -18249,7 +18300,10 @@ void Player::SendInitialPacketsBeforeAddToMap()
SendInitialReputations();
SendInitWorldStates();
m_achievementMgr.SendAllAchievementData();
UpdateZone(GetZoneId());
uint32 newzone, newarea;
GetZoneAndAreaId(newzone,newarea);
UpdateZone(newzone,newarea); // also call SendInitWorldStates();
SendEquipmentSetList();
@ -19297,21 +19351,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 )
@ -19341,13 +19422,22 @@ bool ItemPosCount::isContainedIn(ItemPosCountVec const& vec) const
return false;
}
bool Player::isAllowUseBattleGroundObject()
bool Player::CanUseBattleGroundObject()
{
return ( //InBattleGround() && // in battleground - not need, check in other cases
!IsMounted() && // not mounted
//!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
);
}
@ -19814,6 +19904,11 @@ 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);
}
void Player::BuildPlayerTalentsInfoData(WorldPacket *data)
{
*data << uint32(GetFreeTalentPoints()); // unspentTalentPoints
@ -20356,6 +20451,4 @@ void Player::DeleteEquipmentSet(uint64 setGuid)
{
itr->second.state = EQUIPMENT_SET_DELETED;
break;
}
}
}

View file

@ -69,10 +69,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
@ -502,6 +503,8 @@ enum MirrorTimerType
BREATH_TIMER = 1,
FIRE_TIMER = 2
};
#define MAX_TIMERS 3
#define DISABLED_MIRROR_TIMER -1
// 2^n values
enum PlayerExtraFlags
@ -1551,7 +1554,7 @@ class MANGOS_DLL_SPEC Player : public Unit
PvPInfo pvpInfo;
void UpdatePvP(bool state, bool ovrride=false);
void UpdateZone(uint32 newZone);
void UpdateZone(uint32 newZone,uint32 newArea);
void UpdateArea(uint32 newArea);
void UpdateZoneDependentAuras( uint32 zone_id ); // zones
@ -1727,6 +1730,7 @@ class MANGOS_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);
@ -1874,7 +1878,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void SetEquipmentSet(uint32 index, EquipmentSet eqset);
void DeleteEquipmentSet(uint64 setGuid);
void SendInitWorldStates();
void SendInitWorldStates(uint32 zone, uint32 area);
void SendUpdateWorldState(uint32 Field, uint32 Value);
void SendDirectMessage(WorldPacket *data);
@ -1995,7 +1999,8 @@ class MANGOS_DLL_SPEC Player : public Unit
void ClearAfkReports() { m_bgAfkReporter.clear(); }
bool GetBGAccessByLevel(BattleGroundTypeId bgTypeId) const;
bool isAllowUseBattleGroundObject();
bool CanUseBattleGroundObject();
bool CanCaptureTowerPoint();
/*********************************************************/
/*** REST SYSTEM ***/
@ -2041,8 +2046,6 @@ class MANGOS_DLL_SPEC Player : public Unit
bool IsFlying() const { return HasUnitMovementFlag(MOVEMENTFLAG_FLYING); }
bool IsAllowUseFlyMountsHere() const;
void HandleDrowning();
void SetClientControl(Unit* target, uint8 allowMove);
void EnterVehicle(Vehicle *vehicle);
@ -2171,6 +2174,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void AddRunePower(uint8 index);
void InitRunes();
AchievementMgr& GetAchievementMgr() { return m_achievementMgr; }
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=0, Unit *unit=NULL, uint32 time=0);
bool HasTitle(uint32 bitIndex);
bool HasTitle(CharTitlesEntry const* title) { return HasTitle(title->bit_index); }
void SetTitle(CharTitlesEntry const* title);
@ -2256,12 +2260,14 @@ class MANGOS_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;
/*********************************************************/
@ -2342,7 +2348,6 @@ class MANGOS_DLL_SPEC Player : public Unit
bool m_DailyQuestChanged;
time_t m_lastDailyQuestTime;
uint32 m_breathTimer;
uint32 m_drunkTimer;
uint16 m_drunk;
uint32 m_weaponChangeTimer;

View file

@ -20,7 +20,6 @@
#include "Errors.h"
#include "Creature.h"
#include "CreatureAI.h"
#include "MapManager.h"
#include "DestinationHolderImp.h"
//----- Point Movement Generator

View file

@ -17,10 +17,8 @@
*/
#include "PoolHandler.h"
#include "World.h"
#include "ObjectMgr.h"
#include "ProgressBar.h"
#include "Language.h"
#include "Log.h"
#include "MapManager.h"
#include "Policies/SingletonImp.h"

View file

@ -29,7 +29,6 @@
#include "Player.h"
#include "UpdateMask.h"
#include "NPCHandler.h"
#include "ObjectAccessor.h"
#include "Pet.h"
#include "MapManager.h"

View file

@ -1594,6 +1594,31 @@ enum CreatureEliteType
CREATURE_UNKNOWN = 5 // found in 2.2.3 for 2 mobs
};
// values based at Holidays.dbc
enum HolidayIds
{
HOLIDAY_FIREWORKS_SPECTACULAR = 62,
HOLIDAY_FEAST_OF_WINTER_VEIL = 141,
HOLIDAY_NOBLEGARDEN = 181,
HOLIDAY_CHILDRENS_WEEK = 201,
HOLIDAY_CALL_TO_ARMS_AV = 283,
HOLIDAY_CALL_TO_ARMS_WG = 284,
HOLIDAY_CALL_TO_ARMS_AB = 285,
HOLIDAY_FISHING_EXTRAVAGANZA = 301,
HOLIDAY_HARVEST_FESTIVAL = 321,
HOLIDAY_HALLOWS_END = 324,
HOLIDAY_LUNAR_FESTIVAL = 327,
HOLIDAY_LOVE_IS_IN_THE_AIR = 335,
HOLIDAY_FIRE_FESTIVAL = 341,
HOLIDAY_CALL_TO_ARMS_ES = 353,
HOLIDAY_BREWFEST = 372,
HOLIDAY_DARKMOON_FAIRE_ELWYNN = 374,
HOLIDAY_DARKMOON_FAIRE_THUNDER = 375,
HOLIDAY_DARKMOON_FAIRE_SHATTRATH = 376,
HOLIDAY_CALL_TO_ARMS_SA = 400,
HOLIDAY_WOTLK_LAUNCH = 406
};
// values based at QuestInfo.dbc
enum QuestTypes
{

View file

@ -20,7 +20,6 @@
#include "Log.h"
#include "ProgressBar.h"
#include "Policies/SingletonImp.h"
#include "ObjectAccessor.h"
#include "World.h"
#include "Util.h"
#include "SkillDiscovery.h"

View file

@ -21,12 +21,10 @@
#include "Opcodes.h"
#include "Log.h"
#include "Player.h"
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "ObjectAccessor.h"
#include "UpdateMask.h"
#include "SpellAuras.h"
void WorldSession::HandleLearnTalentOpcode( WorldPacket & recv_data )
{

View file

@ -21,7 +21,6 @@
#include "Database/DatabaseEnv.h"
#include "Opcodes.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "Player.h"
#include "ObjectMgr.h"
#include "World.h"

View file

@ -33,7 +33,6 @@
#include "Unit.h"
#include "Spell.h"
#include "DynamicObject.h"
#include "SpellAuras.h"
#include "Group.h"
#include "UpdateData.h"
#include "MapManager.h"
@ -2045,7 +2044,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
}
}
else
sLog.outError( "SPELL: unknown target coordinates for spell ID %u\n", m_spellInfo->Id );
sLog.outError( "SPELL: unknown target coordinates for spell ID %u", m_spellInfo->Id );
}break;
case TARGET_BEHIND_VICTIM:
{
@ -3354,7 +3353,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)
{
@ -3373,7 +3372,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;
@ -3530,7 +3529,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);
}
}
@ -3756,7 +3755,10 @@ uint8 Spell::CanCast(bool strict)
return SPELL_FAILED_NOT_IN_ARENA;
// zone check
if (uint8 res= spellmgr.GetSpellAllowedInLocationError(m_spellInfo,m_caster->GetMapId(),m_caster->GetZoneId(),m_caster->GetAreaId(),
uint32 zone, area;
m_caster->GetZoneAndAreaId(zone,area);
if (uint8 res= spellmgr.GetSpellAllowedInLocationError(m_spellInfo,m_caster->GetMapId(),zone,area,
m_caster->GetTypeId()==TYPEID_PLAYER ? ((Player*)m_caster) : NULL))
return res;
@ -4108,7 +4110,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

View file

@ -29,11 +29,9 @@
#include "Player.h"
#include "Unit.h"
#include "Spell.h"
#include "SpellAuras.h"
#include "DynamicObject.h"
#include "Group.h"
#include "UpdateData.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "Policies/SingletonImp.h"
#include "Totem.h"
@ -2396,8 +2394,8 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAuraMapBounds(GetId());
if(saBounds.first != saBounds.second)
{
uint32 zone = m_target->GetZoneId();
uint32 area = m_target->GetAreaId();
uint32 zone, area;
m_target->GetZoneAndAreaId(zone,area);
for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
{
@ -2497,15 +2495,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)
@ -3115,7 +3107,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);
@ -4188,7 +4180,7 @@ void Aura::HandleAuraPeriodicDummy(bool apply, bool Real)
{
// Explosive Shot
if (apply && !loading && caster)
m_modifier.m_amount +=caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100;
m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100);
break;
}
}
@ -6691,8 +6683,8 @@ void Aura::HandlePhase(bool apply, bool Real)
SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAuraMapBounds(GetId());
if(saBounds.first != saBounds.second)
{
uint32 zone = m_target->GetZoneId();
uint32 area = m_target->GetAreaId();
uint32 zone, area;
m_target->GetZoneAndAreaId(zone,area);
for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
{

View file

@ -17,10 +17,8 @@
*/
#include "Common.h"
#include "SharedDefines.h"
#include "Database/DatabaseEnv.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "Opcodes.h"
#include "Log.h"
#include "UpdateMask.h"
@ -30,7 +28,6 @@
#include "Player.h"
#include "SkillExtraItems.h"
#include "Unit.h"
#include "CreatureAI.h"
#include "Spell.h"
#include "DynamicObject.h"
#include "SpellAuras.h"
@ -56,6 +53,7 @@
#include "TemporarySummon.h"
#include "ScriptCalls.h"
#include "SkillDiscovery.h"
#include "Formulas.h"
pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
{
@ -375,7 +373,7 @@ void Spell::EffectSchoolDMG(uint32 effect_idx)
damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100);
}
// Shield Slam
else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
else if(m_spellInfo->SpellFamilyFlags & 0x0000020000000000LL)
damage += int32(m_caster->GetShieldBlockValue());
// Victory Rush
else if(m_spellInfo->SpellFamilyFlags & 0x10000000000LL)
@ -595,6 +593,11 @@ void Spell::EffectSchoolDMG(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;
}
}
@ -808,7 +811,7 @@ void Spell::EffectDummy(uint32 i)
creatureTarget->RemoveCorpse();
creatureTarget->SetHealth(0); // just for nice GM-mode view
DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy\n");
DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy");
map->Add(pGameObj);
WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
@ -1261,7 +1264,7 @@ void Spell::EffectDummy(uint32 i)
if (m_spellInfo->SpellFamilyFlags & 0x0000000000040000LL)
{
// 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;
@ -1659,7 +1662,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;
}
@ -1758,7 +1761,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;
}
@ -2021,7 +2024,7 @@ void Spell::EffectTeleportUnits(uint32 i)
SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id);
if(!st)
{
sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u\n", m_spellInfo->Id );
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);
@ -2061,7 +2064,7 @@ void Spell::EffectTeleportUnits(uint32 i)
// 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\n", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id );
sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id );
return;
}
// Init dest coordinates
@ -2922,7 +2925,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())
{
@ -2934,7 +2937,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())
{
@ -3770,13 +3773,18 @@ void Spell::EffectAddHonor(uint32 /*i*/)
if(unitTarget->GetTypeId() != TYPEID_PLAYER)
return;
sLog.outDebug("SpellEffect::AddHonor called for spell_id %u , that rewards %d honor points to player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow());
uint32 honor_reward = MaNGOS::Honor::hk_honor_at_level(unitTarget->getLevel(), damage);
sLog.outDebug("SpellEffect::AddHonor called for spell_id %u, that rewards %u honor points to player: %u", m_spellInfo->Id, honor_reward, ((Player*)unitTarget)->GetGUIDLow());
// TODO: find formula for honor reward based on player's level!
// now fixed only for level 70 players:
if (((Player*)unitTarget)->getLevel() == 70)
// do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
if( damage <= 50 )
((Player*)unitTarget)->RewardHonor(NULL, 1, honor_reward);
else
{
//maybe we have correct honor_gain in damage already
((Player*)unitTarget)->RewardHonor(NULL, 1, damage);
sLog.outError("SpellEffect::AddHonor called for spell_id %u, that rewards %d * honor for one honorable kill and it is too much (%u of honor) for player: %u", m_spellInfo->Id, damage, honor_reward, ((Player*)unitTarget)->GetGUIDLow());
}
}
void Spell::EffectTradeSkill(uint32 /*i*/)
@ -4774,7 +4782,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:
@ -4782,7 +4790,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;
}
// Mirren's Drinking Hat
case 29830:
@ -6297,7 +6312,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);

View file

@ -20,15 +20,11 @@
#include "Database/DBCStores.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "World.h"
#include "ObjectMgr.h"
#include "SpellMgr.h"
#include "Log.h"
#include "Opcodes.h"
#include "Spell.h"
#include "SpellAuras.h"
#include "BattleGround.h"
#include "MapManager.h"
#include "ScriptCalls.h"
#include "Totem.h"

Some files were not shown because too many files have changed in this diff Show more