📄 ground.cpp.svn-base
字号:
for(map<uint32, uint32>::iterator itr = m_worldStates.begin(); itr != m_worldStates.end(); ++itr)
data << itr->first << itr->second;
plr->GetSession()->SendPacket(&data);
}
Cpvp::Cpvp(MapMgr * mgr, uint32 id, uint32 levelgroup, uint32 type) : m_mapMgr(mgr), m_id(id), m_type(type), m_levelGroup(levelgroup)
{
m_nextPvPUpdateTime = 0;
m_countdownStage = 0;
m_ended = false;
m_started = false;
m_winningteam = 0;
m_startTime = (uint32)UNIXTIME;
m_lastResurrect = (uint32)UNIXTIME;
sEventMgr.AddEvent(this, &Cpvp::EventResurrectPlayers, EVENT_pvp_QUEUE_UPDATE, 30000, 0,0);
/* create raid groups */
for(uint32 i = 0; i < 2; ++i)
{
m_groups[i] = new Group(true);
m_groups[i]->m_disbandOnNoMembers = false;
m_groups[i]->ExpandToRaid();
}
}
Cpvp::~Cpvp()
{
sEventMgr.RemoveEvents(this);
for(uint32 i = 0; i < 2; ++i)
{
PlayerInfo *inf;
for(uint32 j = 0; j < m_groups[i]->GetSubGroupCount(); ++j) {
for(GroupMembersSet::iterator itr = m_groups[i]->GetSubGroup(j)->GetGroupMembersBegin(); itr != m_groups[i]->GetSubGroup(j)->GetGroupMembersEnd();) {
inf = (*itr);
++itr;
m_groups[i]->RemovePlayer(inf);
}
}
delete m_groups[i];
}
}
void Cpvp::UpdatePvPData()
{
if(m_type >= pvp_fortress_ && m_type <= pvp_fortress_)
{
if(!m_ended)
{
return;
}
}
if(UNIXTIME >= m_nextPvPUpdateTime)
{
m_mainLock.Acquire();
WorldPacket data(10*(m_players[0].size()+m_players[1].size())+50);
BuildPvPUpdateDataPacket(&data);
DistributePacketToAll(&data);
m_mainLock.Release();
m_nextPvPUpdateTime = UNIXTIME + 2;
}
}
void Cpvp::BuildPvPUpdateDataPacket(WorldPacket * data)
{
data->Initialize(MSG_PVP_LOG_DATA);
data->reserve(10*(m_players[0].size()+m_players[1].size())+50);
BGScore * bs;
if(m_type >= pvp_fortress_ && m_type <= pvp_fortress_)
{
if(!m_ended)
{
return;
}
*data << uint8(1);
if(!Rated())
{
*data << uint32(0x61272A5C);
*data << uint8(0);
*data << uint32(m_players[0].size() + m_players[1].size());
*data << uint8(0);
}
else
{
/* Grab some fortress */
fortressTeam * [2] = {NULL,NULL};
for(uint32 i = 0; i < 2; ++i)
{
for(set<Player*>::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr)
{
[i] = (*itr)->m_fortress[ ((fortress*)this)->GetfortressTeamType() ];
if([i])
break;
}
}
if([0])
{
*data << uint32([0]->m_id);
*data << uint32(0);
*data << [0]->m_name;
}
else
{
*data << uint32(0x61272A5C);
*data << uint32(0);
*data << uint8(0);
}
if([1])
{
*data << uint32([1]->m_id);
*data << uint32(0);
*data << [1]->m_name;
}
else
{
*data << uint32(m_players[0].size() + m_players[1].size());
*data << uint32(0);
*data << uint8(0);
}
}
*data << uint8(1);
*data << uint8(m_winningteam);
*data << uint32(m_players[0].size() + m_players[1].size());
for(uint32 i = 0; i < 2; ++i)
{
for(set<Player*>::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr)
{
*data << (*itr)->GetGUID();
bs = &(*itr)->m_bgScore;
*data << bs->KillingBlows;
// would this be correct?
if( Rated() )
{
*data << uint8((*itr)->m_bgTeam);
}
else
{
*data << uint32(0); // w
*data << uint32(0); // t
*data << uint32(0); // f
}
*data << uint32(1); // count of values after this
*data << uint32(bs->Misc1); // rating change
}
}
}
else
{
*data << uint8(0);
if(m_ended)
{
*data << uint8(1);
*data << uint8(m_winningteam);
}
else
*data << uint8(0); // If the game has ended - this will be 1
*data << uint32(m_players[0].size() + m_players[1].size());
for(uint32 i = 0; i < 2; ++i)
{
for(set<Player*>::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr)
{
*data << (*itr)->GetGUID();
bs = &(*itr)->m_bgScore;
*data << bs->KillingBlows;
*data << bs->HonorableKills;
*data << bs->Deaths;
*data << bs->BonusHonor;
*data << bs->DamageDone;
*data << bs->HealingDone;
*data << uint32(0x2);
*data << bs->Misc1;
*data << bs->Misc2;
}
}
}
}
void Cpvp::AddPlayer(Player * plr, uint32 team)
{
m_mainLock.Acquire();
/* This is called when the player is added, not when they port. So, they're essentially still queued, but not inside the bg yet */
m_pendPlayers[team].insert(plr->GetLowGUID());
/* Send a packet telling them that they can enter */
pvpManager.SendpvpfieldStatus(plr, 2, m_type, m_id, 120000, m_mapMgr->GetMapId(),Rated()); // You will be removed from the queue in 2 minutes.
/* Add an event to remove them in 2 minutes time. */
sEventMgr.AddEvent(plr, &Player::RemoveFrompvpQueue, EVENT_pvp_QUEUE_UPDATE, 120000, 1,0);
plr->m_pendingpvp = this;
m_mainLock.Release();
}
void Cpvp::RemovePendingPlayer(Player * plr)
{
m_mainLock.Acquire();
m_pendPlayers[plr->m_bgTeam].erase(plr->GetLowGUID());
/* send a null bg update (so they don't join) */
pvpManager.SendpvpfieldStatus(plr, 0, 0, 0, 0, 0,0);
plr->m_pendingpvp =0;
plr->m_bgTeam=plr->GetTeam();
m_mainLock.Release();
}
void Cpvp::OnPlayerPushed(Player * plr)
{
if( plr->GetGroup() && !Rated() )
plr->GetGroup()->RemovePlayer(plr->m_playerInfo);
plr->ProcessPendingUpdates();
if( plr->GetGroup() == NULL )
{
if ( plr->m_isGmInvisible == false ) //do not join invisible gm's into bg groups.
m_groups[plr->m_bgTeam]->AddMember( plr->m_playerInfo );
}
}
void Cpvp::PortPlayer(Player * plr, bool skip_teleport /* = false*/)
{
m_mainLock.Acquire();
if(m_ended)
{
sChatHandler.SystemMessage(plr->GetSession(), "You cannot join this pvp as it has already ended.");
pvpManager.SendpvpfieldStatus(plr, 0, 0, 0, 0, 0,0);
plr->m_pendingpvp = 0;
m_mainLock.Release();
return;
}
m_pendPlayers[plr->m_bgTeam].erase(plr->GetLowGUID());
if(m_players[plr->m_bgTeam].find(plr) != m_players[plr->m_bgTeam].end())
{
m_mainLock.Release();
return;
}
plr->SetTeam(plr->m_bgTeam);
if ( plr->m_isGmInvisible == false )
{
//Do not let everyone know an invisible gm has joined.
WorldPacket data(SMSG_pvp_PLAYER_JOINED, 8);
data << plr->GetGUID();
DistributePacketToAll(&data);
}
m_players[plr->m_bgTeam].insert(plr);
/* remove from any auto queue remove events */
sEventMgr.RemoveEvents(plr, EVENT_pvp_QUEUE_UPDATE);
if( !skip_teleport )
{
if( plr->IsInWorld() )
plr->RemoveFromWorld();
}
plr->m_pendingpvp = 0;
plr->m_bg = this;
if(!plr->IsPvPFlagged())
plr->SetPvPFlag();
/* Reset the score */
memset(&plr->m_bgScore, 0, sizeof(BGScore));
/* send him the world states */
SendWorldStates(plr);
/* update pvp data */
UpdatePvPData();
/* add the player to the group */
if(plr->GetGroup() && !Rated())
{
// remove them from their group
plr->GetGroup()->RemovePlayer( plr->m_playerInfo );
}
if(!m_countdownStage)
{
m_countdownStage = 1;
sEventMgr.AddEvent(this, &Cpvp::EventCountdown, EVENT_pvp_COUNTDOWN, 30000, 0,0);
sEventMgr.ModifyEventTimeLeft(this, EVENT_pvp_COUNTDOWN, 10000);
}
sEventMgr.RemoveEvents(this, EVENT_pvp_CLOSE);
OnAddPlayer(plr);
if(!skip_teleport)
{
/* This is where we actually teleport the player to the pvp. */
plr->SafeTeleport(m_mapMgr,GetStartingCoords(plr->m_bgTeam));
pvpManager.SendpvpfieldStatus(plr, 3, m_type, m_id, (uint32)UNIXTIME - m_startTime, m_mapMgr->GetMapId(),Rated()); // Elapsed time is the last argument
}
m_mainLock.Release();
}
Cpvp * CpvpManager::Createevent system(uint32 Type, uint32 LevelGroup)
{
CreatepvpFunc cfunc = BGCFuncs[Type];
MapMgr * mgr = 0;
Cpvp * bg;
uint32 iid;
if(Type == pvp_fortress_ || Type == pvp_fortress_ || Type == pvp_fortress_)
{
/* fortresss follow a different procedure. */
static const uint32 fortress_map_ids[3] = { 559, 562, 572 };
uint32 mapid = fortress_map_ids[RandomUInt(2)];
mapid=562;
uint32 players_per_side;
mgr = sevent systemMgr.Createpvpevent system(mapid);
if(mgr == NULL)
{
Log.Error("pvpManager", "fortress Createevent system() call failed for map %u, type %u, level group %u", mapid, Type, LevelGroup);
return NULL; // Shouldn't happen
}
switch(Type)
{
case pvp_fortress_:
players_per_side = 2;
break;
case pvp_fortress_:
players_per_side = 3;
break;
case pvp_fortress_:
players_per_side = 5;
break;
default:
players_per_side = 0;
break;
}
iid = ++m_maxpvpId;
bg = new fortress(mgr, iid, LevelGroup, Type, players_per_side);
mgr->m_pvp = bg;
Log.Success("pvpManager", "Created fortress pvp type %u for level group %u on map %u.", Type, LevelGroup, mapid);
sEventMgr.AddEvent(bg, &Cpvp::EventCreate, EVENT_pvp_QUEUE_UPDATE, 1, 1,0);
m_event systemLock.Acquire();
m_event systems[Type].insert( make_pair(iid, bg) );
m_event systemLock.Release();
return bg;
}
if(cfunc == NULL)
{
Log.Error("pvpManager", "Could not find CreatepvpFunc pointer for type %u level group %u", Type, LevelGroup);
return NULL;
}
/* Create Map Manager */
mgr = sevent systemMgr.Createpvpevent system(BGMapIds[Type]);
if(mgr == NULL)
{
Log.Error("pvpManager", "Createevent system() call failed for map %u, type %u, level group %u", BGMapIds[Type], Type, LevelGroup);
return NULL; // Shouldn't happen
}
/* Call the create function */
iid = ++m_maxpvpId;
bg = cfunc(mgr, iid, LevelGroup, Type);
mgr->m_pvp = bg;
sEventMgr.AddEvent(bg, &Cpvp::EventCreate, EVENT_pvp_QUEUE_UPDATE, 1, 1,0);
Log.Success("pvpManager", "Created pvp type %u for level group %u.", Type, LevelGroup);
m_event systemLock.Acquire();
m_event systems[Type].insert( make_pair(iid, bg) );
m_event systemLock.Release();
return bg;
}
void CpvpManager::Deletepvp(Cpvp * bg)
{
uint32 i = bg->GetType();
uint32 j = bg->GetLevelGroup();
Player * plr;
m_event systemLock.Acquire();
m_queueLock.Acquire();
m_event systems[i].erase(bg->GetId());
/* erase any queued players */
list<uint32>::iterator itr = m_queuedPlayers[i][j].begin();
list<uint32>::iterator it2;
for(; itr != m_queuedPlayers[i][j].end();)
{
it2 = itr++;
plr = objmgr.GetPlayer(*it2);
if(!plr)
{
m_queuedPlayers[i][j].erase(it2);
continue;
}
if(plr && plr->m_bgQueueevent systemId == bg->GetId())
{
sChatHandler.SystemMessageToPlr(plr, "Your queue on pvp event system %u is no longer valid, the event system no longer exists.", bg->GetId());
SendpvpfieldStatus(plr, 0, 0, 0, 0, 0,0);
plr->m_bgIsQueued = false;
m_queuedPlayers[i][j].erase(it2);
}
}
m_queueLock.Release();
m_event systemLock.Release();
}
GameObject * Cpvp::SpawnGameObject(uint32 entry,uint32 MapId , float x, float y, float z, float o, uint32 flags, uint32 faction, float scale)
{
GameObject *go = m_mapMgr->CreateGameObject(entry);
go->CreateFromProto(entry, MapId, x, y, z, o);
go->SetUInt32Value(GAMEOBJECT_FACTION,faction);
go->SetFloatValue(OBJECT_FIELD_SCALE_X,scale);
go->SetUInt32Value(GAMEOBJECT_FLAGS, flags);
go->SetFloatValue(GAMEOBJECT_POS_X, x);
go->SetFloatValue(GAMEOBJECT_POS_Y, y);
go->SetFloatValue(GAMEOBJECT_POS_Z, z);
go->SetFloatValue(GAMEOBJECT_FACING, o);
go->Setevent systemID(m_mapMgr->Getevent systemID());
go->m_pvp = this;
return go;
}
void Cpvp::SendChatMessage(uint32 Type, uint64 Guid, const char * Format, ...)
{
char msg[500];
va_list ap;
va_start(ap, Format);
vsnprintf(msg, 500, Format, ap);
va_end(ap);
WorldPacket * data = sChatHandler.FillMessageData(Type, 0, msg, Guid, 0);
DistributePacketToAll(data);
delete data;
}
void Cpvp::DistributePacketToAll(WorldPacket * packet)
{
m_mainLock.Acquire();
for(int i = 0; i < 2; ++i)
{
for(set<Player*>::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr)
(*itr)->GetSession()->SendPacket(packet);
}
m_mainLock.Release();
}
void Cpvp::DistributePacketToTeam(WorldPacket * packet, uint32 Team)
{
m_mainLock.Acquire();
for(set<Player*>::iterator itr = m_players[Team].begin(); itr != m_players[Team].end(); ++itr)
(*itr)->GetSession()->SendPacket(packet);
m_mainLock.Release();
}
void Cpvp::PlaySoundToAll(uint32 Sound)
{
WorldPacket data(SMSG_PLAY_SOUND, 4);
data << Sound;
DistributePacketToAll(&data);
}
void Cpvp::PlaySoundToTeam(uint32 Team, uint32 Sound)
{
WorldPacket data(SMSG_PLAY_SOUND, 4);
data << Sound;
DistributePacketToTeam(&data, Team);
}
void CpvpManager::SendpvpfieldStatus(Player * plr, uint32 Status, uint32 Type, uint32 event systemID, uint32 Time, uint32 MapId, uint8 RatedMatch)
{
WorldPacket data(SMSG_pvpFIELD_STATUS, 30);
if(Status == 0)
data << uint64(0) << uint32(0);
else
{
if(Type >= pvp_fortress_ && Type <= pvp_fortress_)
{
data << uint32(plr->m_bgTeam);
switch(Type)
{
case pvp_fortress_:
data << uint8(2);
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -