server/game/src/war_map.cpp

1104 lines
22 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "stdafx.h"
#include "war_map.h"
#include "sectree_manager.h"
#include "char.h"
#include "char_manager.h"
#include "affect.h"
#include "item.h"
#include "config.h"
#include "desc.h"
#include "desc_manager.h"
#include "guild_manager.h"
#include "buffer_manager.h"
#include "db.h"
#include "packet.h"
#include "locale_service.h"
EVENTINFO(war_map_info)
{
int iStep;
CWarMap * pWarMap;
war_map_info()
: iStep( 0 )
, pWarMap( 0 )
{
}
};
EVENTFUNC(war_begin_event)
{
war_map_info* info = dynamic_cast<war_map_info*>( event->info );
if ( info == NULL )
{
sys_err( "war_begin_event> <Factor> Null pointer" );
return 0;
}
CWarMap * pMap = info->pWarMap;
pMap->CheckWarEnd();
return PASSES_PER_SEC(10);
}
EVENTFUNC(war_end_event)
{
war_map_info* info = dynamic_cast<war_map_info*>( event->info );
if ( info == NULL )
{
sys_err( "war_end_event> <Factor> Null pointer" );
return 0;
}
CWarMap * pMap = info->pWarMap;
if (info->iStep == 0)
{
++info->iStep;
pMap->ExitAll();
return PASSES_PER_SEC(5);
}
else
{
pMap->SetEndEvent(NULL);
CWarMapManager::instance().DestroyWarMap(pMap);
return 0;
}
}
EVENTFUNC(war_timeout_event)
{
war_map_info* info = dynamic_cast<war_map_info*>( event->info );
if ( info == NULL )
{
sys_err( "war_timeout_event> <Factor> Null pointer" );
return 0;
}
CWarMap * pMap = info->pWarMap;
pMap->Timeout();
return 0;
}
void CWarMap::STeamData::Initialize()
{
dwID = 0;
pkGuild = NULL;
iMemberCount = 0;
iUsePotionPrice = 0;
iScore = 0;
pkChrFlag = NULL;
pkChrFlagBase = NULL;
set_pidJoiner.clear();
}
CWarMap::CWarMap(int lMapIndex, const TGuildWarInfo & r_info, TWarMapInfo * pkWarMapInfo, DWORD dwGuildID1, DWORD dwGuildID2)
{
m_kMapInfo = *pkWarMapInfo;
m_kMapInfo.lMapIndex = lMapIndex;
memcpy(&m_WarInfo, &r_info, sizeof(TGuildWarInfo));
m_TeamData[0].Initialize();
m_TeamData[0].dwID = dwGuildID1;
m_TeamData[0].pkGuild = CGuildManager::instance().TouchGuild(dwGuildID1);
m_TeamData[1].Initialize();
m_TeamData[1].dwID = dwGuildID2;
m_TeamData[1].pkGuild = CGuildManager::instance().TouchGuild(dwGuildID2);
m_iObserverCount = 0;
war_map_info* info = AllocEventInfo<war_map_info>();
info->pWarMap = this;
SetBeginEvent(event_create(war_begin_event, info, PASSES_PER_SEC(60)));
m_pkEndEvent = NULL;
m_pkTimeoutEvent = NULL;
m_pkResetFlagEvent = NULL;
m_bTimeout = false;
m_dwStartTime = get_dword_time();
m_bEnded = false;
if (GetType() == WAR_MAP_TYPE_FLAG)
{
AddFlagBase(0);
AddFlagBase(1);
AddFlag(0);
AddFlag(1);
}
}
CWarMap::~CWarMap()
{
event_cancel(&m_pkBeginEvent);
event_cancel(&m_pkEndEvent);
event_cancel(&m_pkTimeoutEvent);
event_cancel(&m_pkResetFlagEvent);
sys_log(0, "WarMap::~WarMap : map index %d", GetMapIndex());
itertype(m_set_pkChr) it = m_set_pkChr.begin();
while (it != m_set_pkChr.end())
{
LPCHARACTER ch = *(it++);
if (ch->GetDesc())
{
sys_log(0, "WarMap::~WarMap : disconnecting %s", ch->GetName());
DESC_MANAGER::instance().DestroyDesc(ch->GetDesc());
}
}
m_set_pkChr.clear();
}
void CWarMap::SetBeginEvent(LPEVENT pkEv)
{
if (m_pkBeginEvent != NULL) {
event_cancel(&m_pkBeginEvent);
}
if (pkEv != NULL) {
m_pkBeginEvent = pkEv;
}
}
void CWarMap::SetEndEvent(LPEVENT pkEv)
{
if (m_pkEndEvent != NULL) {
event_cancel(&m_pkEndEvent);
}
if (pkEv != NULL) {
m_pkEndEvent = pkEv;
}
}
void CWarMap::SetTimeoutEvent(LPEVENT pkEv)
{
if (m_pkTimeoutEvent != NULL) {
event_cancel(&m_pkTimeoutEvent);
}
if (pkEv != NULL) {
m_pkTimeoutEvent = pkEv;
}
}
void CWarMap::SetResetFlagEvent(LPEVENT pkEv)
{
if (m_pkResetFlagEvent != NULL) {
event_cancel(&m_pkResetFlagEvent);
}
if (pkEv != NULL) {
m_pkResetFlagEvent = pkEv;
}
}
bool CWarMap::GetTeamIndex(DWORD dwGuildID, BYTE & bIdx)
{
if (m_TeamData[0].dwID == dwGuildID)
{
bIdx = 0;
return true;
}
else if (m_TeamData[1].dwID == dwGuildID)
{
bIdx = 1;
return true;
}
return false;
}
DWORD CWarMap::GetGuildID(BYTE bIdx)
{
assert(bIdx < 2);
return m_TeamData[bIdx].dwID;
}
CGuild * CWarMap::GetGuild(BYTE bIdx)
{
return m_TeamData[bIdx].pkGuild;
}
int CWarMap::GetMapIndex()
{
return m_kMapInfo.lMapIndex;
}
BYTE CWarMap::GetType()
{
return m_kMapInfo.bType;
}
DWORD CWarMap::GetGuildOpponent(LPCHARACTER ch)
{
if (ch->GetGuild())
{
DWORD gid = ch->GetGuild()->GetID();
BYTE idx;
if (GetTeamIndex(gid, idx))
return m_TeamData[!idx].dwID;
}
return 0;
}
DWORD CWarMap::GetWinnerGuild()
{
DWORD win_gid = 0;
if (m_TeamData[1].iScore > m_TeamData[0].iScore)
{
win_gid = m_TeamData[1].dwID;
}
else if (m_TeamData[0].iScore > m_TeamData[1].iScore)
{
win_gid = m_TeamData[0].dwID;
}
return (win_gid);
}
void CWarMap::UsePotion(LPCHARACTER ch, LPITEM item)
{
if (m_pkEndEvent)
return;
if (ch->IsObserverMode())
return;
if (!ch->GetGuild())
return;
if (!item->GetProto())
return;
int iPrice = item->GetProto()->dwGold;
DWORD gid = ch->GetGuild()->GetID();
if (gid == m_TeamData[0].dwID)
m_TeamData[0].iUsePotionPrice += iPrice;
else if (gid == m_TeamData[1].dwID)
m_TeamData[1].iUsePotionPrice += iPrice;
}
int CWarMap::STeamData::GetAccumulatedJoinerCount()
{
return set_pidJoiner.size();
}
int CWarMap::STeamData::GetCurJointerCount()
{
return iMemberCount;
}
void CWarMap::STeamData::AppendMember(LPCHARACTER ch)
{
set_pidJoiner.insert(ch->GetPlayerID());
++iMemberCount;
}
void CWarMap::STeamData::RemoveMember(LPCHARACTER ch)
{
// set_pidJoiner <20><> <20><><EFBFBD><EFBFBD> <20>ο<EFBFBD><CEBF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʴ´<CAB4>
--iMemberCount;
}
struct FSendUserCount
{
char buf1[30];
char buf2[128];
FSendUserCount(DWORD g1, int g1_count, DWORD g2, int g2_count, int observer)
{
snprintf(buf1, sizeof(buf1), "ObserverCount %d", observer);
snprintf(buf2, sizeof(buf2), "WarUC %u %d %u %d %d", g1, g1_count, g2, g2_count, observer);
}
void operator() (LPCHARACTER ch)
{
ch->ChatPacket(CHAT_TYPE_COMMAND, buf1);
ch->ChatPacket(CHAT_TYPE_COMMAND, buf2);
}
};
void CWarMap::UpdateUserCount()
{
FSendUserCount f(
m_TeamData[0].dwID,
m_TeamData[0].GetAccumulatedJoinerCount(),
m_TeamData[1].dwID,
m_TeamData[1].GetAccumulatedJoinerCount(),
m_iObserverCount);
std::for_each(m_set_pkChr.begin(), m_set_pkChr.end(), f);
}
void CWarMap::IncMember(LPCHARACTER ch)
{
if (!ch->IsPC())
return;
sys_log(0, "WarMap::IncMember");
DWORD gid = 0;
if (ch->GetGuild())
gid = ch->GetGuild()->GetID();
bool isWarMember = ch->GetQuestFlag("war.is_war_member") > 0 ? true : false;
if (isWarMember && gid != m_TeamData[0].dwID && gid != m_TeamData[1].dwID)
{
ch->SetQuestFlag("war.is_war_member", 0);
isWarMember = false;
}
if (isWarMember)
{
if (gid == m_TeamData[0].dwID)
{
m_TeamData[0].AppendMember(ch);
}
else if (gid == m_TeamData[1].dwID)
{
m_TeamData[1].AppendMember(ch);
}
event_cancel(&m_pkTimeoutEvent);
sys_log(0, "WarMap +m %u(cur:%d, acc:%d) vs %u(cur:%d, acc:%d)",
m_TeamData[0].dwID, m_TeamData[0].GetCurJointerCount(), m_TeamData[0].GetAccumulatedJoinerCount(),
m_TeamData[1].dwID, m_TeamData[1].GetCurJointerCount(), m_TeamData[1].GetAccumulatedJoinerCount());
}
else
{
++m_iObserverCount;
sys_log(0, "WarMap +o %d", m_iObserverCount);
ch->SetObserverMode(true);
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϼ̽<CFBC><CCBD>ϴ<EFBFBD>."));
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD>ڽ<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ͻø<CFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20>ִ<EFBFBD> <<3C><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>> <20><>ư<EFBFBD><C6B0> <20><><EFBFBD>ɴϴ<C9B4>."));
}
UpdateUserCount();
m_set_pkChr.insert(ch);
LPDESC d = ch->GetDesc();
SendWarPacket(d);
SendScorePacket(0, d);
SendScorePacket(1, d);
}
void CWarMap::DecMember(LPCHARACTER ch)
{
if (!ch->IsPC())
return;
sys_log(0, "WarMap::DecMember");
DWORD gid = 0;
if (ch->GetGuild())
gid = ch->GetGuild()->GetID();
if (!ch->IsObserverMode())
{
if (gid == m_TeamData[0].dwID)
m_TeamData[0].RemoveMember(ch);
else if (gid == m_TeamData[1].dwID)
m_TeamData[1].RemoveMember(ch);
if (m_kMapInfo.bType == WAR_MAP_TYPE_FLAG)
{
CAffect * pkAff = ch->FindAffect(AFFECT_WAR_FLAG);
if (pkAff)
{
BYTE idx;
if (GetTeamIndex(pkAff->lApplyValue, idx))
AddFlag(idx, ch->GetX(), ch->GetY());
ch->RemoveAffect(AFFECT_WAR_FLAG);
}
}
sys_log(0, "WarMap -m %u(cur:%d, acc:%d) vs %u(cur:%d, acc:%d)",
m_TeamData[0].dwID, m_TeamData[0].GetCurJointerCount(), m_TeamData[0].GetAccumulatedJoinerCount(),
m_TeamData[1].dwID, m_TeamData[1].GetCurJointerCount(), m_TeamData[1].GetAccumulatedJoinerCount());
CheckWarEnd();
ch->SetQuestFlag("war.is_war_member", 0);
}
else
{
--m_iObserverCount;
sys_log(0, "WarMap -o %d", m_iObserverCount);
ch->SetObserverMode(false);
}
UpdateUserCount();
m_set_pkChr.erase(ch);
}
struct FExitGuildWar
{
void operator() (LPCHARACTER ch)
{
if (ch->IsPC())
{
ch->ExitToSavedLocation();
}
}
};
void CWarMap::ExitAll()
{
FExitGuildWar f;
std::for_each(m_set_pkChr.begin(), m_set_pkChr.end(), f);
}
void CWarMap::CheckWarEnd()
{
if (m_bEnded)
return;
if (m_TeamData[0].iMemberCount == 0 || m_TeamData[1].iMemberCount == 0)
{
if (m_bTimeout)
return;
if (m_pkTimeoutEvent)
return;
Notice(LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ƹ<EFBFBD><C6B9><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
Notice(LC_TEXT("1<EFBFBD><EFBFBD> <20>̳<EFBFBD><CCB3><EFBFBD> <20>ƹ<EFBFBD><C6B9><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ڵ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>˴ϴ<CBB4>."));
sys_log(0, "CheckWarEnd: Timeout begin %u vs %u", m_TeamData[0].dwID, m_TeamData[1].dwID);
war_map_info* info = AllocEventInfo<war_map_info>();
info->pWarMap = this;
SetTimeoutEvent(event_create(war_timeout_event, info, PASSES_PER_SEC(60)));
}
else
CheckScore();
}
int CWarMap::GetRewardGold(BYTE bWinnerIdx)
{
int iRewardGold = m_WarInfo.iWarPrice;
iRewardGold += (m_TeamData[bWinnerIdx].iUsePotionPrice * m_WarInfo.iWinnerPotionRewardPctToWinner) / 100;
iRewardGold += (m_TeamData[bWinnerIdx ? 0 : 1].iUsePotionPrice * m_WarInfo.iLoserPotionRewardPctToWinner) / 100;
return iRewardGold;
}
void CWarMap::Draw()
{
CGuildManager::instance().RequestWarOver(m_TeamData[0].dwID, m_TeamData[1].dwID, 0, 0);
}
void CWarMap::Timeout()
{
SetTimeoutEvent(NULL);
if (m_bTimeout)
return;
if (m_bEnded)
return;
DWORD dwWinner = 0;
DWORD dwLoser = 0;
int iRewardGold = 0;
if (get_dword_time() - m_dwStartTime < 60000 * 5)
{
Notice(LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ǿ<EFBFBD> <20><><EFBFBD>ºη<C2BA> <20><><EFBFBD><EFBFBD> <20>Ǿ<EFBFBD><C7BE><EFBFBD><EFBFBD>ϴ<EFBFBD>. (5<><35><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>)"));
dwWinner = 0;
dwLoser = 0;
}
else
{
int iWinnerIdx = -1;
if (m_TeamData[0].iMemberCount == 0)
iWinnerIdx = 1;
else if (m_TeamData[1].iMemberCount == 0)
iWinnerIdx = 0;
if (iWinnerIdx == -1)
{
dwWinner = GetWinnerGuild();
if (dwWinner == m_TeamData[0].dwID)
{
iRewardGold = GetRewardGold(0);
dwLoser = m_TeamData[1].dwID;
}
else if (dwWinner == m_TeamData[1].dwID)
{
iRewardGold = GetRewardGold(1);
dwLoser = m_TeamData[0].dwID;
}
sys_err("WarMap: member count is not zero, guild1 %u %d guild2 %u %d, winner %u",
m_TeamData[0].dwID, m_TeamData[0].iMemberCount,
m_TeamData[1].dwID, m_TeamData[1].iMemberCount,
dwWinner);
}
else
{
dwWinner = m_TeamData[iWinnerIdx].dwID;
dwLoser = m_TeamData[iWinnerIdx == 0 ? 1 : 0].dwID;
iRewardGold = GetRewardGold(iWinnerIdx);
}
}
sys_log(0, "WarMap: Timeout %u %u winner %u loser %u reward %d map %d",
m_TeamData[0].dwID, m_TeamData[1].dwID, dwWinner, dwLoser, iRewardGold, m_kMapInfo.lMapIndex);
if (dwWinner)
CGuildManager::instance().RequestWarOver(dwWinner, dwLoser, dwWinner, iRewardGold);
else
CGuildManager::instance().RequestWarOver(m_TeamData[0].dwID, m_TeamData[1].dwID, dwWinner, iRewardGold);
m_bTimeout = true;
}
namespace
{
struct FPacket
{
FPacket(const void * p, int size) : m_pvData(p), m_iSize(size)
{
}
void operator () (LPCHARACTER ch)
{
ch->GetDesc()->Packet(m_pvData, m_iSize);
}
const void * m_pvData;
int m_iSize;
};
struct FNotice
{
FNotice(const char * psz) : m_psz(psz)
{
}
void operator() (LPCHARACTER ch)
{
ch->ChatPacket(CHAT_TYPE_NOTICE, "%s", m_psz);
}
const char * m_psz;
};
};
void CWarMap::Notice(const char * psz)
{
FNotice f(psz);
std::for_each(m_set_pkChr.begin(), m_set_pkChr.end(), f);
}
void CWarMap::Packet(const void * p, int size)
{
FPacket f(p, size);
std::for_each(m_set_pkChr.begin(), m_set_pkChr.end(), f);
}
void CWarMap::SendWarPacket(LPDESC d)
{
TPacketGCGuild pack;
TPacketGCGuildWar pack2;
pack.header = HEADER_GC_GUILD;
pack.subheader = GUILD_SUBHEADER_GC_WAR;
pack.size = sizeof(pack) + sizeof(pack2);
pack2.dwGuildSelf = m_TeamData[0].dwID;
pack2.dwGuildOpp = m_TeamData[1].dwID;
pack2.bType = CGuildManager::instance().TouchGuild(m_TeamData[0].dwID)->GetGuildWarType(m_TeamData[1].dwID);
pack2.bWarState = CGuildManager::instance().TouchGuild(m_TeamData[0].dwID)->GetGuildWarState(m_TeamData[1].dwID);
d->RawPacket(&pack, sizeof(pack));
d->Packet(&pack2, sizeof(pack2));
}
void CWarMap::SendScorePacket(BYTE bIdx, LPDESC d)
{
TPacketGCGuild p;
p.header = HEADER_GC_GUILD;
p.subheader = GUILD_SUBHEADER_GC_WAR_SCORE;
p.size = sizeof(p) + sizeof(DWORD) + sizeof(DWORD) + sizeof(int);
TEMP_BUFFER buf;
buf.write(&p, sizeof(p));
buf.write(&m_TeamData[bIdx].dwID, sizeof(DWORD));
buf.write(&m_TeamData[bIdx ? 0 : 1].dwID, sizeof(DWORD));
buf.write(&m_TeamData[bIdx].iScore, sizeof(int));
if (d)
d->Packet(buf.read_peek(), buf.size());
else
Packet(buf.read_peek(), buf.size());
}
void CWarMap::UpdateScore(DWORD g1, int score1, DWORD g2, int score2)
{
BYTE idx;
if (GetTeamIndex(g1, idx))
{
if (m_TeamData[idx].iScore != score1)
{
m_TeamData[idx].iScore = score1;
SendScorePacket(idx);
}
}
if (GetTeamIndex(g2, idx))
{
if (m_TeamData[idx].iScore != score2)
{
m_TeamData[idx].iScore = score2;
SendScorePacket(idx);
}
}
CheckScore();
}
bool CWarMap::CheckScore()
{
if (m_bEnded)
return true;
// 30<33><30> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Ȯ<><C8AE><EFBFBD>Ѵ<EFBFBD>.
if (get_dword_time() - m_dwStartTime < 30000)
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> üũ<C3BC><C5A9><EFBFBD><EFBFBD> <20>ʴ´<CAB4>.
if (m_TeamData[0].iScore == m_TeamData[1].iScore)
return false;
int iEndScore = m_WarInfo.iEndScore;
if (test_server) iEndScore /= 10;
DWORD dwWinner;
DWORD dwLoser;
if (m_TeamData[0].iScore >= iEndScore)
{
dwWinner = m_TeamData[0].dwID;
dwLoser = m_TeamData[1].dwID;
}
else if (m_TeamData[1].iScore >= iEndScore)
{
dwWinner = m_TeamData[1].dwID;
dwLoser = m_TeamData[0].dwID;
}
else
return false;
int iRewardGold = 0;
if (dwWinner == m_TeamData[0].dwID)
iRewardGold = GetRewardGold(0);
else if (dwWinner == m_TeamData[1].dwID)
iRewardGold = GetRewardGold(1);
sys_log(0, "WarMap::CheckScore end score %d guild1 %u score guild2 %d %u score %d winner %u reward %d",
iEndScore,
m_TeamData[0].dwID,
m_TeamData[0].iScore,
m_TeamData[1].dwID,
m_TeamData[1].iScore,
dwWinner,
iRewardGold);
CGuildManager::instance().RequestWarOver(dwWinner, dwLoser, dwWinner, iRewardGold);
return true;
}
bool CWarMap::SetEnded()
{
sys_log(0, "WarMap::SetEnded %d", m_kMapInfo.lMapIndex);
if (m_pkEndEvent)
return false;
if (m_TeamData[0].pkChrFlag)
{
M2_DESTROY_CHARACTER(m_TeamData[0].pkChrFlag);
m_TeamData[0].pkChrFlag = NULL;
}
if (m_TeamData[0].pkChrFlagBase)
{
M2_DESTROY_CHARACTER(m_TeamData[0].pkChrFlagBase);
m_TeamData[0].pkChrFlagBase = NULL;
}
if (m_TeamData[1].pkChrFlag)
{
M2_DESTROY_CHARACTER(m_TeamData[1].pkChrFlag);
m_TeamData[1].pkChrFlag = NULL;
}
if (m_TeamData[1].pkChrFlagBase)
{
M2_DESTROY_CHARACTER(m_TeamData[1].pkChrFlagBase);
m_TeamData[1].pkChrFlagBase = NULL;
}
event_cancel(&m_pkResetFlagEvent);
m_bEnded = true;
war_map_info* info = AllocEventInfo<war_map_info>();
info->pWarMap = this;
info->iStep = 0;
SetEndEvent(event_create(war_end_event, info, PASSES_PER_SEC(10)));
return true;
}
void CWarMap::OnKill(LPCHARACTER killer, LPCHARACTER ch)
{
if (m_bEnded)
return;
DWORD dwKillerGuild = 0;
DWORD dwDeadGuild = 0;
if (killer->GetGuild())
dwKillerGuild = killer->GetGuild()->GetID();
if (ch->GetGuild())
dwDeadGuild = ch->GetGuild()->GetID();
BYTE idx;
sys_log(0, "WarMap::OnKill %u %u", dwKillerGuild, dwDeadGuild);
if (!GetTeamIndex(dwKillerGuild, idx))
return;
if (!GetTeamIndex(dwDeadGuild, idx))
return;
switch (m_kMapInfo.bType)
{
case WAR_MAP_TYPE_NORMAL:
SendGuildWarScore(dwKillerGuild, dwDeadGuild, 1, ch->GetLevel());
break;
case WAR_MAP_TYPE_FLAG:
{
CAffect * pkAff = ch->FindAffect(AFFECT_WAR_FLAG);
if (pkAff)
{
if (GetTeamIndex(pkAff->lApplyValue, idx))
AddFlag(idx, ch->GetX(), ch->GetY());
ch->RemoveAffect(AFFECT_WAR_FLAG);
}
}
break;
default:
sys_err("unknown war map type %u index %d", m_kMapInfo.bType, m_kMapInfo.lMapIndex);
break;
}
}
void CWarMap::AddFlagBase(BYTE bIdx, DWORD x, DWORD y)
{
if (m_bEnded)
return;
assert(bIdx < 2);
TeamData & r = m_TeamData[bIdx];
if (r.pkChrFlagBase)
return;
if (x == 0)
{
x = m_kMapInfo.posStart[bIdx].x;
y = m_kMapInfo.posStart[bIdx].y;
}
r.pkChrFlagBase = CHARACTER_MANAGER::instance().SpawnMob(warmap::WAR_FLAG_BASE_VNUM, m_kMapInfo.lMapIndex, x, y, 0);
sys_log(0, "WarMap::AddFlagBase %u %p id %u", bIdx, get_pointer(r.pkChrFlagBase), r.dwID);
r.pkChrFlagBase->SetPoint(POINT_STAT, r.dwID);
r.pkChrFlagBase->SetWarMap(this);
}
void CWarMap::AddFlag(BYTE bIdx, DWORD x, DWORD y)
{
if (m_bEnded)
return;
assert(bIdx < 2);
TeamData & r = m_TeamData[bIdx];
if (r.pkChrFlag)
return;
if (x == 0)
{
x = m_kMapInfo.posStart[bIdx].x;
y = m_kMapInfo.posStart[bIdx].y;
}
r.pkChrFlag = CHARACTER_MANAGER::instance().SpawnMob(bIdx == 0 ? warmap::WAR_FLAG_VNUM0 : warmap::WAR_FLAG_VNUM1, m_kMapInfo.lMapIndex, x, y, 0);
sys_log(0, "WarMap::AddFlag %u %p id %u", bIdx, get_pointer(r.pkChrFlag), r.dwID);
r.pkChrFlag->SetPoint(POINT_STAT, r.dwID);
r.pkChrFlag->SetWarMap(this);
}
void CWarMap::RemoveFlag(BYTE bIdx)
{
assert(bIdx < 2);
TeamData & r = m_TeamData[bIdx];
if (!r.pkChrFlag)
return;
sys_log(0, "WarMap::RemoveFlag %u %p", bIdx, get_pointer(r.pkChrFlag));
r.pkChrFlag->Dead(NULL, true);
r.pkChrFlag = NULL;
}
bool CWarMap::IsFlagOnBase(BYTE bIdx)
{
assert(bIdx < 2);
TeamData & r = m_TeamData[bIdx];
if (!r.pkChrFlag)
return false;
const PIXEL_POSITION & pos = r.pkChrFlag->GetXYZ();
if (pos.x == m_kMapInfo.posStart[bIdx].x && pos.y == m_kMapInfo.posStart[bIdx].y)
return true;
return false;
}
EVENTFUNC(war_reset_flag_event)
{
war_map_info* info = dynamic_cast<war_map_info*>( event->info );
if ( info == NULL )
{
sys_err( "war_reset_flag_event> <Factor> Null pointer" );
return 0;
}
CWarMap * pMap = info->pWarMap;
pMap->AddFlag(0);
pMap->AddFlag(1);
pMap->SetResetFlagEvent(NULL);
return 0;
}
struct FRemoveFlagAffect
{
void operator() (LPCHARACTER ch)
{
if (ch->FindAffect(AFFECT_WAR_FLAG))
ch->RemoveAffect(AFFECT_WAR_FLAG);
}
};
void CWarMap::ResetFlag()
{
if (m_kMapInfo.bType != WAR_MAP_TYPE_FLAG)
return;
if (m_pkResetFlagEvent)
return;
if (m_bEnded)
return;
FRemoveFlagAffect f;
std::for_each(m_set_pkChr.begin(), m_set_pkChr.end(), f);
RemoveFlag(0);
RemoveFlag(1);
war_map_info* info = AllocEventInfo<war_map_info>();
info->pWarMap = this;
info->iStep = 0;
SetResetFlagEvent(event_create(war_reset_flag_event, info, PASSES_PER_SEC(10)));
}
/////////////////////////////////////////////////////////////////////////////////
// WarMapManager
/////////////////////////////////////////////////////////////////////////////////
CWarMapManager::CWarMapManager()
{
}
CWarMapManager::~CWarMapManager()
{
for( std::map<int, TWarMapInfo *>::const_iterator iter = m_map_kWarMapInfo.begin() ; iter != m_map_kWarMapInfo.end() ; ++iter )
{
M2_DELETE(iter->second);
}
m_map_kWarMapInfo.clear();
}
bool CWarMapManager::LoadWarMapInfo(const char * c_pszFileName)
{
TWarMapInfo * k;
k = M2_NEW TWarMapInfo;
k->bType = WAR_MAP_TYPE_NORMAL;
k->lMapIndex = 110;
k->posStart[0].x = 48 * 100 + 32000;
k->posStart[0].y = 52 * 100 + 0;
k->posStart[1].x = 183 * 100 + 32000;
k->posStart[1].y = 206 * 100 + 0;
k->posStart[2].x = 141 * 100 + 32000;
k->posStart[2].y = 117 * 100 + 0;
m_map_kWarMapInfo.insert(std::make_pair(k->lMapIndex, k));
k = M2_NEW TWarMapInfo;
k->bType = WAR_MAP_TYPE_FLAG;
k->lMapIndex = 111;
k->posStart[0].x = 68 * 100 + 57600;
k->posStart[0].y = 69 * 100 + 0;
k->posStart[1].x = 171 * 100 + 57600;
k->posStart[1].y = 182 * 100 + 0;
k->posStart[2].x = 122 * 100 + 57600;
k->posStart[2].y = 131 * 100 + 0;
m_map_kWarMapInfo.insert(std::make_pair(k->lMapIndex, k));
return true;
}
bool CWarMapManager::IsWarMap(int lMapIndex)
{
return GetWarMapInfo(lMapIndex) ? true : false;
}
bool CWarMapManager::GetStartPosition(int lMapIndex, BYTE bIdx, PIXEL_POSITION & pos)
{
assert(bIdx < 3);
TWarMapInfo * pi = GetWarMapInfo(lMapIndex);
if (!pi)
{
sys_log(0, "GetStartPosition FAILED [%d] WarMapInfoSize(%d)", lMapIndex, m_map_kWarMapInfo.size());
itertype(m_map_kWarMapInfo) it;
for (it = m_map_kWarMapInfo.begin(); it != m_map_kWarMapInfo.end(); ++it)
{
PIXEL_POSITION& cur=it->second->posStart[bIdx];
sys_log(0, "WarMap[%d]=Pos(%d, %d)", it->first, cur.x, cur.y);
}
return false;
}
pos = pi->posStart[bIdx];
return true;
}
int CWarMapManager::CreateWarMap(const TGuildWarInfo& guildWarInfo, DWORD dwGuildID1, DWORD dwGuildID2)
{
TWarMapInfo * pkInfo = GetWarMapInfo(guildWarInfo.lMapIndex);
if (!pkInfo)
{
sys_err("GuildWar.CreateWarMap.NOT_FOUND_MAPINFO[%d]", guildWarInfo.lMapIndex);
return 0;
}
DWORD lMapIndex = SECTREE_MANAGER::instance().CreatePrivateMap(guildWarInfo.lMapIndex);
if (lMapIndex)
{
m_mapWarMap.insert(std::make_pair(lMapIndex, M2_NEW CWarMap(lMapIndex, guildWarInfo, pkInfo, dwGuildID1, dwGuildID2)));
}
return lMapIndex;
}
TWarMapInfo * CWarMapManager::GetWarMapInfo(int lMapIndex)
{
if (lMapIndex >= 10000)
lMapIndex /= 10000;
itertype(m_map_kWarMapInfo) it = m_map_kWarMapInfo.find(lMapIndex);
if (m_map_kWarMapInfo.end() == it)
return NULL;
return it->second;
}
void CWarMapManager::DestroyWarMap(CWarMap* pMap)
{
int mapIdx = pMap->GetMapIndex();
sys_log(0, "WarMap::DestroyWarMap : %d", mapIdx);
m_mapWarMap.erase(pMap->GetMapIndex());
M2_DELETE(pMap);
SECTREE_MANAGER::instance().DestroyPrivateMap(mapIdx);
}
CWarMap * CWarMapManager::Find(int lMapIndex)
{
itertype(m_mapWarMap) it = m_mapWarMap.find(lMapIndex);
if (it == m_mapWarMap.end())
return NULL;
return it->second;
}
void CWarMapManager::OnShutdown()
{
itertype(m_mapWarMap) it = m_mapWarMap.begin();
while (it != m_mapWarMap.end())
(it++)->second->Draw();
}