#include "pch.h"
ALLOC_MSG_LIST;
bool g_bCheckFiles = false;
class ClientEventSource : public IClientEventSource
{
private:
TList<TRef<IClientEventSink> > m_listSinks;
void RemoveDeadSinks()
{
while (m_listSinks.Remove(NULL))
{
}
}
public:
void AddSink(IClientEventSink* psink)
{
m_listSinks.PushFront(psink);
}
void RemoveSink(IClientEventSink* psink)
{
m_listSinks.Replace(psink, NULL);
}
#define ForEachSink(fnc) \
TList<TRef<IClientEventSink> >::Iterator iter(m_listSinks); \
while (!iter.End()) \
{ \
if (iter.Value() != NULL) \
iter.Value()->fnc; \
iter.Next(); \
} \
RemoveDeadSinks(); \
void OnAddMission(MissionInfo* pMissionInfo)
{
ForEachSink( OnAddMission(pMissionInfo) )
}
void OnMissionCountdown(MissionInfo* pMissionInfo)
{
ForEachSink( OnMissionCountdown(pMissionInfo) )
}
void OnMissionStarted(MissionInfo* pMissionInfo)
{
ForEachSink( OnMissionStarted(pMissionInfo) )
}
void OnMissionEnded(MissionInfo* pMissionInfo)
{
ForEachSink( OnMissionEnded(pMissionInfo) )
}
void OnLockLobby(bool bLock)
{
ForEachSink( OnLockLobby(bLock) )
}
void OnLockSides(bool bLock)
{
ForEachSink( OnLockSides(bLock) )
}
void OnFoundPlayer(MissionInfo* pMissionInfo)
{
ForEachSink( OnFoundPlayer(pMissionInfo) )
}
void OnEnterMission()
{
ForEachSink( OnEnterMission() )
}
void OnDelMission(MissionInfo* pMissionInfo)
{
ForEachSink( OnDelMission(pMissionInfo) )
}
void OnAddPlayer(MissionInfo* pMissionInfo, SideID sideID, PlayerInfo* pPlayerInfo)
{
ForEachSink( OnAddPlayer(pMissionInfo, sideID, pPlayerInfo) )
}
void OnDelPlayer(MissionInfo* pMissionInfo, SideID sideID, PlayerInfo* pPlayerInfo, QuitSideReason reason, const char* szMessageParam)
{
ForEachSink( OnDelPlayer(pMissionInfo, sideID, pPlayerInfo, reason, szMessageParam) )
}
void OnAddRequest(MissionInfo* pMissionInfo, SideID sideID, PlayerInfo* pPlayerInfo)
{
ForEachSink( OnAddRequest(pMissionInfo, sideID, pPlayerInfo) )
}
void OnDelRequest(MissionInfo* pMissionInfo, SideID sideID, PlayerInfo* pPlayerInfo, DelPositionReqReason reason)
{
ForEachSink( OnDelRequest(pMissionInfo, sideID, pPlayerInfo, reason) )
}
void OnTeamInactive(MissionInfo* pMissionInfo, SideID sideID)
{
ForEachSink( OnTeamInactive(pMissionInfo, sideID) )
}
void OnTeamReadyChange(MissionInfo* pMissionInfo, SideID sideID, bool fTeamReady)
{
ForEachSink( OnTeamReadyChange(pMissionInfo, sideID, fTeamReady) )
}
void OnTeamForceReadyChange(MissionInfo* pMissionInfo, SideID sideID, bool fTeamForceReady)
{
ForEachSink( OnTeamForceReadyChange(pMissionInfo, sideID, fTeamForceReady) )
}
void OnTeamAutoAcceptChange(MissionInfo* pMissionInfo, SideID sideID, bool fAutoAccept)
{
ForEachSink( OnTeamAutoAcceptChange(pMissionInfo, sideID, fAutoAccept) )
}
void OnTeamCivChange(MissionInfo* pMissionInfo, SideID sideID, CivID civID)
{
ForEachSink( OnTeamCivChange(pMissionInfo, sideID, civID) )
}
void OnTeamNameChange(MissionInfo* pMissionInfo, SideID sideID)
{
ForEachSink( OnTeamNameChange(pMissionInfo, sideID) )
}
void OnPlayerStatusChange(MissionInfo* pMissionInfo, SideID sideID, PlayerInfo* pPlayerInfo)
{
ForEachSink( OnPlayerStatusChange(pMissionInfo, sideID, pPlayerInfo) )
}
void OnMoneyChange(PlayerInfo* pPlayerInfo)
{
ForEachSink( OnMoneyChange(pPlayerInfo) )
}
void OnBucketChange(BucketChange bc, IbucketIGC* b)
{
ForEachSink( OnBucketChange(bc, b) )
}
void OnTechTreeChanged(SideID sid)
{
ForEachSink( OnTechTreeChanged(sid) )
}
void OnStationCaptured(StationID stationID, SideID sideID)
{
ForEachSink( OnStationCaptured(stationID, sideID) )
}
void OnModelTerminated(ImodelIGC* pmodel)
{
ForEachSink( OnModelTerminated(pmodel) )
}
void OnLoadoutChanged(IpartIGC* ppart, LoadoutChange lc)
{
ForEachSink( OnLoadoutChanged(ppart, lc) )
}
void OnTurretStateChanging(bool bTurret)
{
ForEachSink( OnTurretStateChanging(bTurret) )
}
void OnPurchaseCompleted(bool bAllPartsBought)
{
ForEachSink( OnPurchaseCompleted(bAllPartsBought) )
}
void OnShipStatusChange(PlayerInfo* pplayer)
{
ForEachSink( OnShipStatusChange(pplayer) )
}
void OnBoardShip(IshipIGC* pshipChild, IshipIGC* pshipParent)
{
ForEachSink( OnBoardShip(pshipChild, pshipParent) )
}
void OnBoardFailed(IshipIGC* pshipParent)
{
ForEachSink( OnBoardFailed(pshipParent) )
}
void OnDiscoveredStation(IstationIGC* pstation)
{
ForEachSink( OnDiscoveredStation(pstation) )
}
void OnDiscoveredAsteroid(IasteroidIGC* pasteroid)
{
ForEachSink( OnDiscoveredAsteroid(pasteroid) )
}
void OnClusterChanged(IclusterIGC* pcluster)
{
ForEachSink( OnClusterChanged(pcluster) )
}
void OnGameoverStats()
{
ForEachSink( OnGameoverStats() )
}
void OnGameoverPlayers()
{
ForEachSink( OnGameoverPlayers() )
}
void OnDeleteChatMessage(ChatInfo* pchatInfo)
{
ForEachSink( OnDeleteChatMessage(pchatInfo) )
}
void OnNewChatMessage()
{
ForEachSink( OnNewChatMessage() )
}
void OnClearChat()
{
ForEachSink( OnClearChat() )
}
void OnChatMessageChange()
{
ForEachSink( OnChatMessageChange() )
}
void OnLostConnection(const char * szReason)
{
ForEachSink( OnLostConnection(szReason) )
}
void OnEnterModalState()
{
ForEachSink( OnEnterModalState() )
}
void OnLeaveModalState()
{
ForEachSink( OnLeaveModalState() )
}
void OnLogonClub()
{
ForEachSink( OnLogonClub() )
}
void OnLogonClubFailed(bool bRetry, const char * szReason)
{
ForEachSink( OnLogonClubFailed(bRetry, szReason) )
}
void OnLogonLobby()
{
ForEachSink( OnLogonLobby() )
}
void OnLogonLobbyFailed(bool bRetry, const char * szReason)
{
ForEachSink( OnLogonLobbyFailed(bRetry, szReason) )
}
void OnLogonGameServer()
{
ForEachSink( OnLogonGameServer() )
}
void OnLogonGameServerFailed(bool bRetry, const char * szReason)
{
ForEachSink( OnLogonGameServerFailed(bRetry, szReason) )
}
void OnServersList(int cCores, char *Cores, int cServers, char *Servers)
{
ForEachSink( OnServersList(cCores, Cores, cServers, Servers));
}
};
class ClientEventSinkDelegate : public IClientEventSink {
private:
IClientEventSink* m_psink;
public:
ClientEventSinkDelegate(IClientEventSink* psink) :
m_psink(psink)
{
}
void OnAddMission(MissionInfo* pMissionInfo)
{
m_psink->OnAddMission(pMissionInfo);
}
void OnMissionCountdown(MissionInfo* pMissionInfo)
{
m_psink->OnMissionCountdown(pMissionInfo);
}
void OnMissionStarted(MissionInfo* pMissionInfo)
{
m_psink->OnMissionStarted(pMissionInfo);
}
void OnMissionEnded(MissionInfo* pMissionInfo)
{
m_psink->OnMissionEnded(pMissionInfo);
}
void OnLockLobby(bool bLock)
{
m_psink->OnLockLobby(bLock);
}
void OnLockSides(bool bLock)
{
m_psink->OnLockSides(bLock);
}
void OnFoundPlayer(MissionInfo* pMissionDef)
{
m_psink->OnFoundPlayer(pMissionDef);
}
void OnEnterMission()
{
m_psink->OnEnterMission();
}
void OnDelMission(MissionInfo* pMissionInfo)
{
m_psink->OnDelMission(pMissionInfo);
}
void OnAddPlayer(MissionInfo* pMissionInfo, SideID sideID, PlayerInfo* pPlayerInfo)
{
m_psink->OnAddPlayer(pMissionInfo, sideID, pPlayerInfo);
}
void OnDelPlayer(MissionInfo* pMissionInfo, SideID sideID, PlayerInfo* pPlayerInfo, QuitSideReason reason, const char* szMessageParam)
{
m_psink->OnDelPlayer(pMissionInfo, sideID, pPlayerInfo, reason, szMessageParam);
}
void OnAddRequest(MissionInfo* pMissionInfo, SideID sideID, PlayerInfo* pPlayerInfo)
{
m_psink->OnAddRequest(pMissionInfo, sideID, pPlayerInfo);
}
void OnDelRequest(MissionInfo* pMissionInfo, SideID sideID, PlayerInfo* pPlayerInfo, DelPositionReqReason reason)
{
m_psink->OnDelRequest(pMissionInfo, sideID, pPlayerInfo, reason);
}
void OnTeamInactive(MissionInfo* pMissionInfo, SideID sideID)
{
m_psink->OnTeamInactive(pMissionInfo, sideID);
}
void OnTeamReadyChange(MissionInfo* pMissionInfo, SideID sideID, bool fTeamReady)
{
m_psink->OnTeamReadyChange(pMissionInfo, sideID, fTeamReady);
}
void OnTeamForceReadyChange(MissionInfo* pMissionInfo, SideID sideID, bool fTeamForceReady)
{
m_psink->OnTeamForceReadyChange(pMissionInfo, sideID, fTeamForceReady);
}
void OnTeamAutoAcceptChange(MissionInfo* pMissionInfo, SideID sideID, bool fAutoAccept)
{
m_psink->OnTeamAutoAcceptChange(pMissionInfo, sideID, fAutoAccept);
}
void OnTeamCivChange(MissionInfo* pMissionInfo, SideID sideID, CivID civID)
{
m_psink->OnTeamCivChange(pMissionInfo, sideID, civID);
}
void OnTeamNameChange(MissionInfo* pMissionInfo, SideID sideID)
{
m_psink->OnTeamNameChange(pMissionInfo, sideID);
}
void OnPlayerStatusChange(MissionInfo* pMissionInfo, SideID sideID, PlayerInfo* pPlayerInfo)
{
m_psink->OnPlayerStatusChange(pMissionInfo, sideID, pPlayerInfo);
}
void OnMoneyChange(PlayerInfo* pPlayerInfo)
{
m_psink->OnMoneyChange(pPlayerInfo);
}
void OnBucketChange(BucketChange bc, IbucketIGC* b)
{
m_psink->OnBucketChange(bc, b);
}
void OnTechTreeChanged(SideID sid)
{
m_psink->OnTechTreeChanged(sid);
}
void OnStationCaptured(StationID stationID, SideID sideID)
{
m_psink->OnStationCaptured(stationID, sideID);
}
void OnModelTerminated(ImodelIGC* pmodel)
{
m_psink->OnModelTerminated(pmodel);
}
void OnLoadoutChanged(IpartIGC* ppart, LoadoutChange lc)
{
m_psink->OnLoadoutChanged(ppart, lc);
}
void OnTurretStateChanging(bool bTurret)
{
m_psink->OnTurretStateChanging(bTurret);
}
void OnPurchaseCompleted(bool bAllPartsBought)
{
m_psink->OnPurchaseCompleted(bAllPartsBought);
}
void OnShipStatusChange(PlayerInfo* pplayer)
{
m_psink->OnShipStatusChange(pplayer);
}
void OnBoardShip(IshipIGC* pshipChild, IshipIGC* pshipParent)
{
m_psink->OnBoardShip(pshipChild, pshipParent);
}
void OnBoardFailed(IshipIGC* pshipParent)
{
m_psink->OnBoardFailed(pshipParent);
}
void OnDiscoveredStation(IstationIGC* pstation)
{
m_psink->OnDiscoveredStation(pstation);
}
void OnDiscoveredAsteroid(IasteroidIGC* pasteroid)
{
m_psink->OnDiscoveredAsteroid(pasteroid);
}
void OnClusterChanged(IclusterIGC* pcluster)
{
m_psink->OnClusterChanged(pcluster);
}
void OnGameoverStats()
{
m_psink->OnGameoverStats();
}
void OnGameoverPlayers()
{
m_psink->OnGameoverPlayers();
}
void OnDeleteChatMessage(ChatInfo* pchatInfo)
{
m_psink->OnDeleteChatMessage(pchatInfo);
}
void OnNewChatMessage()
{
m_psink->OnNewChatMessage();
}
void OnClearChat()
{
m_psink->OnClearChat();
}
void OnChatMessageChange()
{
m_psink->OnChatMessageChange();
}
void OnLostConnection(const char* szReason)
{
m_psink->OnLostConnection(szReason);
}
void OnEnterModalState()
{
m_psink->OnEnterModalState();
}
void OnLeaveModalState()
{
m_psink->OnLeaveModalState();
}
void OnLogonClub()
{
m_psink->OnLogonClub();
}
void OnLogonClubFailed(bool bRetry, const char * szReason)
{
m_psink->OnLogonClubFailed(bRetry, szReason);
}
void OnLogonLobby()
{
m_psink->OnLogonLobby();
}
void OnLogonLobbyFailed(bool bRetry, const char * szReason)
{
m_psink->OnLogonLobbyFailed(bRetry, szReason);
}
void OnLogonGameServer()
{
m_psink->OnLogonGameServer();
}
void OnLogonGameServerFailed(bool bRetry, const char * szReason)
{
m_psink->OnLogonGameServerFailed(bRetry, szReason);
}
void OnServersList(int cCores, char *Cores, int cServers, char *Servers)
{
m_psink->OnServersList(cCores, Cores, cServers, Servers);
}
};
TRef<IClientEventSink> IClientEventSink::CreateDelegate(IClientEventSink* psink)
{
return new ClientEventSinkDelegate(psink);
}
void ChatInfo::SetChat(ChatTarget ctRecipient,
const ZString& strText,
CommandID cid,
ImodelIGC* pmodelTarget,
const Color& color,
bool bFromPlayer,
bool bFromObjectModel,
bool bFromLeader)
{
logchat(strText); m_ctRecipient = ctRecipient;
m_cidCommand = cid;
m_pmodelTarget = pmodelTarget;
m_strMessage = strText;
m_colorMessage = color;
m_bFromPlayer = bFromPlayer;
m_bFromObjectModel = bFromObjectModel;
m_bFromLeader = bFromLeader;
}
void ChatInfo::ClearTarget(void)
{
m_cidCommand = c_cidNone;
if (m_pmodelTarget->GetObjectType() != OT_buoy)
{
m_strMessage += " <dead>";
}
m_pmodelTarget = NULL;
}
MissionInfo::MissionInfo(DWORD dwCookie) :
m_sideLobby(SIDE_TEAMLOBBY)
{
m_pfmMissionDef = new FMD_S_MISSIONDEF;
memset(m_pfmMissionDef, 0, sizeof(FMD_S_MISSIONDEF));
m_pfmMissionDef->dwCookie = dwCookie;
m_fGuaranteedSlotsAvailable = false;
m_fAnySlotsAvailable = false;
m_fCountdownStarted = false;
m_nNumPlayers = 0;
}
MissionInfo::~MissionInfo()
{
if (m_pfmMissionDef)
delete m_pfmMissionDef;
TMapListWrapper<SideID, SideInfo*>::Iterator iterSideInfo(m_mapSideInfo);
while (!iterSideInfo.End())
{
delete iterSideInfo.Value();
iterSideInfo.Next();
}
}
void MissionInfo::Update(FMD_S_MISSIONDEF* pfmMissionDef)
{
int numSidesOld = NumSides();
memcpy(m_pfmMissionDef, pfmMissionDef, sizeof(FMD_S_MISSIONDEF));
if (NumSides() > numSidesOld)
{
for(SideID sideID = numSidesOld; sideID < NumSides(); sideID++)
{
GetSideInfo(sideID);
}
}
else
{
for (SideID sideID = numSidesOld - 1; sideID >= NumSides(); sideID--)
{
m_mapSideInfo.Remove(sideID);
}
}
m_mapSideInfo.GetSink()();
}
void MissionInfo::Update(FMD_LS_LOBBYMISSIONINFO* pfmLobbyMissionInfo)
{
int numSidesOld = NumSides();
Strncpy(m_pfmMissionDef->misparms.strGameName, FM_VAR_REF(pfmLobbyMissionInfo, szGameName), c_cbGameName);
m_pfmMissionDef->misparms.strGameName[c_cbGameName - 1] = '\0';
m_strGameDetailsFiles = (FM_VAR_REF(pfmLobbyMissionInfo, szGameDetailsFiles) != NULL)
? FM_VAR_REF(pfmLobbyMissionInfo, szGameDetailsFiles) : "";
m_pfmMissionDef->misparms.nTeams = pfmLobbyMissionInfo->nTeams;
m_pfmMissionDef->misparms.nMinPlayersPerTeam = pfmLobbyMissionInfo->nMinPlayersPerTeam;
m_pfmMissionDef->misparms.nMaxPlayersPerTeam = pfmLobbyMissionInfo->nMaxPlayersPerTeam;
m_pfmMissionDef->misparms.iMinRank = pfmLobbyMissionInfo->nMinRank;
m_pfmMissionDef->misparms.iMaxRank = pfmLobbyMissionInfo->nMaxRank;
m_pfmMissionDef->misparms.timeStart = Time(pfmLobbyMissionInfo->dwStartTime);
m_nNumPlayers = pfmLobbyMissionInfo->nNumPlayers;
m_fGuaranteedSlotsAvailable = pfmLobbyMissionInfo->fGuaranteedSlotsAvailable;
m_fAnySlotsAvailable = pfmLobbyMissionInfo->fAnySlotsAvailable;
m_nNumPlayers = pfmLobbyMissionInfo->nNumPlayers;
SetInProgress(pfmLobbyMissionInfo->fInProgress);
SetCountdownStarted(pfmLobbyMissionInfo->fCountdownStarted);
m_pfmMissionDef->misparms.bScoresCount = pfmLobbyMissionInfo->fScoresCount;
m_pfmMissionDef->misparms.bAllowDevelopments = pfmLobbyMissionInfo->fAllowDevelopments;
m_pfmMissionDef->misparms.bInvulnerableStations = pfmLobbyMissionInfo->fInvulnerableStations;
m_pfmMissionDef->misparms.bObjectModelCreated = pfmLobbyMissionInfo->fMSArena;
Strncpy(m_pfmMissionDef->misparms.szIGCStaticFile, FM_VAR_REF(pfmLobbyMissionInfo, szIGCStaticFile), c_cbFileName);
Strncpy(m_pfmMissionDef->szServerName, FM_VAR_REF(pfmLobbyMissionInfo,szServerName), c_cbName);
Strncpy(m_pfmMissionDef->szServerAddr, FM_VAR_REF(pfmLobbyMissionInfo,szServerAddr), 16);
m_pfmMissionDef->misparms.nTotalMaxPlayersPerGame = pfmLobbyMissionInfo->nMaxPlayersPerGame;
m_pfmMissionDef->misparms.bSquadGame = pfmLobbyMissionInfo->fSquadGame;
m_pfmMissionDef->misparms.bEjectPods = pfmLobbyMissionInfo->fEjectPods;
if (pfmLobbyMissionInfo->fLimitedLives && m_pfmMissionDef->misparms.iLives == 0x7fff)
m_pfmMissionDef->misparms.iLives = 1;
else if (!pfmLobbyMissionInfo->fLimitedLives && m_pfmMissionDef->misparms.iLives != 0x7fff)
m_pfmMissionDef->misparms.iLives = 0x7fff;
if (pfmLobbyMissionInfo->fConquest && !m_pfmMissionDef->misparms.IsConquestGame())
m_pfmMissionDef->misparms.iGoalConquestPercentage = 100;
else if (!pfmLobbyMissionInfo->fConquest && m_pfmMissionDef->misparms.IsConquestGame())
m_pfmMissionDef->misparms.iGoalConquestPercentage = 0;
if (pfmLobbyMissionInfo->fDeathMatch && !m_pfmMissionDef->misparms.IsDeathMatchGame())
m_pfmMissionDef->misparms.nGoalTeamKills = 1;
else if (!pfmLobbyMissionInfo->fDeathMatch && m_pfmMissionDef->misparms.IsDeathMatchGame())
m_pfmMissionDef->misparms.nGoalTeamKills = 0;
if (pfmLobbyMissionInfo->fCountdown && !m_pfmMissionDef->misparms.IsCountdownGame())
m_pfmMissionDef->misparms.dtGameLength = 600;
else if (!pfmLobbyMissionInfo->fCountdown && m_pfmMissionDef->misparms.IsCountdownGame())
m_pfmMissionDef->misparms.dtGameLength = 0;
if (pfmLobbyMissionInfo->fProsperity && !m_pfmMissionDef->misparms.IsProsperityGame())
m_pfmMissionDef->misparms.fGoalTeamMoney = 100;
else if (!pfmLobbyMissionInfo->fProsperity && m_pfmMissionDef->misparms.IsProsperityGame())
m_pfmMissionDef->misparms.fGoalTeamMoney = 0;
if (pfmLobbyMissionInfo->fArtifacts && !m_pfmMissionDef->misparms.IsArtifactsGame())
m_pfmMissionDef->misparms.nGoalArtifactsCount = 10;
else if (!pfmLobbyMissionInfo->fArtifacts && m_pfmMissionDef->misparms.IsArtifactsGame())
m_pfmMissionDef->misparms.nGoalArtifactsCount = 0;
if (pfmLobbyMissionInfo->fFlags && !m_pfmMissionDef->misparms.IsFlagsGame())
m_pfmMissionDef->misparms.nGoalFlagsCount = 10;
else if (!pfmLobbyMissionInfo->fFlags && m_pfmMissionDef->misparms.IsFlagsGame())
m_pfmMissionDef->misparms.nGoalFlagsCount = 0;
if (pfmLobbyMissionInfo->fTerritorial && !m_pfmMissionDef->misparms.IsTerritoryGame())
m_pfmMissionDef->misparms.iGoalTerritoryPercentage = 70;
else if (!pfmLobbyMissionInfo->fTerritorial && m_pfmMissionDef->misparms.IsTerritoryGame())
m_pfmMissionDef->misparms.iGoalTerritoryPercentage = 100;
if (NumSides() > numSidesOld)
{
for(SideID sideID = numSidesOld; sideID < NumSides(); sideID++)
{
GetSideInfo(sideID);
}
}
else
{
for (SideID sideID = numSidesOld - 1; sideID >= NumSides(); sideID--)
{
m_mapSideInfo.Remove(sideID);
}
}
{
SideID sideID;
SquadID* vSquadIDs = (SquadID*)FM_VAR_REF(pfmLobbyMissionInfo, rgSquadIDs);
int numSquads = pfmLobbyMissionInfo->cbrgSquadIDs / sizeof(SquadID);
assert(numSquads < c_cSidesMax);
for (sideID = 0; sideID < numSquads; sideID++)
squadIDs[sideID] = vSquadIDs[sideID];
for (; sideID < c_cSidesMax; sideID++)
squadIDs[sideID] = NA;
}
m_mapSideInfo.GetSink()();
}
void MissionInfo::UpdateStartTime(Time timeStart)
{
m_pfmMissionDef->misparms.timeStart = timeStart;
}
int MissionInfo::GuaranteedPositions()
{
SideID sideID;
int nTotal = 0;
for(sideID = 0; sideID < NumSides(); sideID++)
{
if (SideActive(sideID) && (SideAutoAccept(sideID)
|| (SideNumPlayers(sideID) == 0 && AutoAcceptLeaders())))
{
nTotal += SideMaxPlayers(sideID) - SideNumPlayers(sideID);
}
}
return nTotal;
}
void MissionInfo::PurgePlayers()
{
TMapListWrapper<SideID, SideInfo*>::Iterator iterSideInfo(m_mapSideInfo);
while (!iterSideInfo.End())
{
delete iterSideInfo.Value();
iterSideInfo.Next();
}
m_mapSideInfo.SetEmpty();
for (SideID id = 0; id < NumSides(); id++)
{
m_pfmMissionDef->rgcPlayers[id] = 0;
}
}
bool MissionInfo::HasSquad(SquadID squadID)
{
for (SideID id = 0; id < NumSides(); id++)
{
if (squadIDs[id] == squadID)
return true;
}
return false;
}
void MissionInfo::SetSideLeader(PlayerInfo* pPlayerInfo)
{
m_pfmMissionDef->rgShipIDLeaders[pPlayerInfo->SideID()] = pPlayerInfo->ShipID();
if (pPlayerInfo->IsMissionOwner())
m_pfmMissionDef->iSideMissionOwner = pPlayerInfo->SideID();
GetSideInfo(pPlayerInfo->SideID())->GetMembers().GetSink()();
}
bool MissionInfo::FindPlayer(SideID sideID, ShipID shipID)
{
ZAssert(sideID != NA);
ZAssert(shipID >= 0);
return GetSideInfo(sideID)->FindPlayer(shipID);
}
void MissionInfo::AddPlayer(PlayerInfo* pPlayerInfo)
{
SideID sideID = pPlayerInfo->SideID();
ShipID shipID = pPlayerInfo->ShipID();
ZAssert(sideID != NA);
ZAssert(shipID >= 0);
SideInfo* psideInfo = GetSideInfo(sideID);
if (!psideInfo->FindPlayer(shipID))
{
if ((sideID >= 0) && pPlayerInfo->IsHuman())
m_pfmMissionDef->rgcPlayers[sideID]++;
psideInfo->RemoveRequest(shipID);
psideInfo->AddPlayer(shipID);
m_mapSideInfo.GetSink()();
}
}
void MissionInfo::RemovePlayer(PlayerInfo* pPlayerInfo)
{
SideID sideID = pPlayerInfo->SideID();
ShipID shipID = pPlayerInfo->ShipID();
ZAssert(sideID != NA);
ZAssert(shipID >= 0);
if (sideID != SIDE_TEAMLOBBY)
{
if (m_pfmMissionDef->rgShipIDLeaders[sideID] == pPlayerInfo->ShipID())
{
pPlayerInfo->SetTeamLeader(false);
m_pfmMissionDef->rgShipIDLeaders[sideID] = NA;
if (m_pfmMissionDef->iSideMissionOwner == sideID)
{
m_pfmMissionDef->iSideMissionOwner = NA;
pPlayerInfo->SetMissionOwner(false);
}
}
}
SideInfo* psideInfo = GetSideInfo(sideID);
if (psideInfo->FindPlayer(shipID))
{
if ((sideID >= 0) && pPlayerInfo->IsHuman())
m_pfmMissionDef->rgcPlayers[sideID]--;
psideInfo->RemovePlayer(shipID);
m_mapSideInfo.GetSink()();
}
}
bool MissionInfo::FindRequest(SideID sideID, ShipID shipID)
{
ZAssert(sideID != NA);
ZAssert(shipID >= 0);
if (sideID == SIDE_TEAMLOBBY)
return false;
return GetSideInfo(sideID)->FindRequest(shipID);
}
void MissionInfo::AddRequest(SideID sideID, ShipID shipID)
{
ZAssert(sideID != NA);
ZAssert(shipID >= 0);
if (sideID == SIDE_TEAMLOBBY)
return;
SideInfo* psideInfo = GetSideInfo(sideID);
ZAssert(psideInfo);
if (!psideInfo->FindPlayer(shipID) && !psideInfo->FindRequest(shipID))
psideInfo->AddRequest(shipID);
m_mapSideInfo.GetSink()();
}
void MissionInfo::RemoveRequest(SideID sideID, ShipID shipID)
{
ZAssert(sideID != NA);
ZAssert(shipID >= 0);
if (sideID == SIDE_TEAMLOBBY)
return;
GetSideInfo(sideID)->RemoveRequest(shipID);
m_mapSideInfo.GetSink()();
}
SideInfo* MissionInfo::GetSideInfo(SideID sideID)
{
ZAssert(sideID != NA);
SideInfo* pSideInfo = NULL;
if (sideID >= m_pfmMissionDef->misparms.nTeams)
{
assert(false);
return NULL;
}
else if (!m_mapSideInfo.Find(sideID, pSideInfo) && sideID != SIDE_TEAMLOBBY)
{
pSideInfo = new SideInfo(sideID);
m_mapSideInfo.Set(sideID, pSideInfo);
}
else if (sideID == SIDE_TEAMLOBBY)
{
return &m_sideLobby;
}
return pSideInfo;
}
List* MissionInfo::GetSideList()
{
for (SideID id = 0; id < NumSides(); id++)
GetSideInfo(id);
GetSideInfo(SIDE_TEAMLOBBY);
return new ListDelegate(&m_mapSideInfo);
}
PlayerInfo::PlayerInfo(void) :
m_pship(NULL),
m_vPersistPlayerScores(NULL),
m_cPersistPlayerScores(0),
m_bMute(false)
{
}
PlayerInfo::~PlayerInfo()
{
if (m_vPersistPlayerScores)
delete m_vPersistPlayerScores;
ResetShipStatus();
}
void PlayerInfo::Set(FMD_S_PLAYERINFO* pfmPlayerInfo)
{
if (m_vPersistPlayerScores)
delete m_vPersistPlayerScores;
memcpy(&m_fmPlayerInfo, pfmPlayerInfo, sizeof(m_fmPlayerInfo));
m_cPersistPlayerScores = pfmPlayerInfo->cbrgPersistPlayerScores / sizeof(PersistPlayerScoreObject);
if (m_cPersistPlayerScores > 0)
{
PersistPlayerScoreObject* vSrcScores
= (PersistPlayerScoreObject*)FM_VAR_REF(pfmPlayerInfo, rgPersistPlayerScores);
m_vPersistPlayerScores = new PersistPlayerScoreObject[m_cPersistPlayerScores];
for (int i = 0; i < m_cPersistPlayerScores; i++)
m_vPersistPlayerScores[i] = vSrcScores[i];
}
else
{
m_vPersistPlayerScores = NULL;
}
}
const PersistPlayerScoreObject& PlayerInfo::GetPersistScore(CivID civId) const
{
for (int i = 0; i < m_cPersistPlayerScores; i++)
{
if (m_vPersistPlayerScores[i].GetCivID() == civId)
return m_vPersistPlayerScores[i];
}
return m_persist;
}
void PlayerInfo::UpdateScore(PersistPlayerScoreObject& ppso)
{
CivID civId = ppso.GetCivID();
if (civId != NA)
{
int iCivScore;
for (iCivScore = 0; iCivScore < m_cPersistPlayerScores; ++iCivScore)
{
if (m_vPersistPlayerScores[iCivScore].GetCivID() == civId)
break;
}
if (iCivScore >= m_cPersistPlayerScores)
{
PersistPlayerScoreObject* vppsoNew
= new PersistPlayerScoreObject[m_cPersistPlayerScores + 1];
for (int i = 0; i < m_cPersistPlayerScores; ++i)
vppsoNew[i] = m_vPersistPlayerScores[i];
if (m_vPersistPlayerScores)
delete m_vPersistPlayerScores;
m_vPersistPlayerScores = vppsoNew;
++m_cPersistPlayerScores;
}
m_vPersistPlayerScores[iCivScore] = ppso;
}
}
CivID PlayerInfo::GetCivID() const
{
if (SideID() < 0)
return NA;
else
return GetShip()->GetSide()->GetCivilization()->GetObjectID();
}
BaseClient::BaseClient(void)
:
m_pCoreIGC(CreateMission()),
m_lastSend(Time::Now()),
m_lastLagCheck(Time::Now()),
m_serverOffset(0),
m_serverOffsetValidF(false),
m_selectedWeapon(0),
m_messageType(c_mtNone),
m_cookie(NA),
m_plinkSelectedChat(NULL),
m_pPlayerInfo(NULL),
m_pMissionInfo(NULL),
m_fLoggedOn(false),
m_fLoggedOnToLobby(false),
m_fLoggedOnToClub(false),
m_fm(this),
m_fmLobby(this),
m_fmClub(this),
m_ship(NULL),
m_pshipLastSender(NULL),
m_moneyLastRequest(0),
m_sync(1.0f),
m_viewCluster(NULL),
m_cUnansweredPings(0),
m_pAutoDownload(NULL),
m_fZoneClub(false),
m_fIsLobbied(false),
m_dwCookieToJoin(NA),
m_bInGame(false),
m_bWaitingForGameRestart(false),
m_cRankInfo(0),
m_vRankInfo(NULL),
m_cStaticMapInfo(0),
m_vStaticMapInfo(NULL),
m_lockdownCriteria(0),
m_lobbyServerOffset(0),
m_plistFindServerResults(NULL),
m_strCDKey(""),
m_sidBoardAfterDisembark(NA),
m_sidTeleportAfterDisembark(NA)
{
CoInitialize(NULL);
m_timeLastPing = m_lastSend;
m_plistMissions = new ListDelegate(&m_mapMissions);
m_pClientEventSource = new ClientEventSource();
m_szCharName[0] = '\0';
m_szClubCharName[0] = '\0';
m_szLobbyCharName[0] = '\0';
m_szIGCStaticFile[0] = '\0';
m_pMissionInfo = NULL;
}
BaseClient::~BaseClient(void)
{
#ifdef USEAUTH
FreeZoneAuthClient();
#endif
CoUninitialize();
TMapListWrapper<DWORD, MissionInfo*>::Iterator iterMissions(m_mapMissions);
while (!iterMissions.End())
{
delete iterMissions.Value();
iterMissions.Next();
}
if (m_pMissionInfo)
delete m_pMissionInfo;
if (m_ci.pZoneTicket)
HeapFree(GetProcessHeap(), 0, m_ci.pZoneTicket);
m_fm.Shutdown();
if (m_pAutoDownload)
delete m_pAutoDownload;
if (m_vRankInfo)
delete [] m_vRankInfo;
m_vRankInfo = NULL;
if (m_vStaticMapInfo)
delete [] m_vStaticMapInfo;
m_vStaticMapInfo = NULL;
}
void BaseClient::Initialize(Time timeNow)
{
assert (m_pCoreIGC);
CreateDummyShip();
m_pCoreIGC->Initialize(timeNow, this);
}
void BaseClient::Reinitialize(Time timeNow)
{
BaseClient::Terminate();
ZAssert(m_pCoreIGC == NULL);
m_pCoreIGC = CreateMission();
m_lastSend = timeNow;
m_lastLagCheck = timeNow;
m_timeLastPing = timeNow;
m_serverOffset = 0;
m_serverOffsetValidF = false;
m_selectedWeapon = NULL;
m_messageType = c_mtNone;
m_cookie = NA;
m_plinkSelectedChat = NULL;
m_pPlayerInfo = NULL;
if (m_pMissionInfo)
delete m_pMissionInfo;
m_pMissionInfo = NULL;
m_fLoggedOn = false;
m_pchaffLastCreated = NULL;
m_pshipLastSender = NULL;
m_moneyLastRequest = 0;
m_mapBucketStatusArray.SetEmpty();
m_listPlayers.purge(true);
m_chatList.purge(true);
Initialize(timeNow);
}
void BaseClient::Terminate(void)
{
assert (m_pCoreIGC);
Disconnect();
FlushGameState();
}
void BaseClient::FlushGameState()
{
m_pchaffLastCreated = NULL;
if (m_ship)
m_ship->AddRef();
{
const ShipListIGC* ships = m_pCoreIGC->GetShips();
ShipLinkIGC* l;
while ((l = ships->first()) != NULL)
{
l->data()->Terminate();
}
}
m_listPlayers.purge();
m_pCoreIGC->Terminate();
if (m_ship)
{
DestroyDummyShip();
m_ship->Release();
m_ship = NULL;
}
delete m_pCoreIGC;
m_pCoreIGC = NULL;
m_bInGame = false;
}
HRESULT BaseClient::ConnectToServer(ConnectInfo & ci, DWORD dwCookie, Time now, const char* szPassword, bool bStandalonePrivate)
{
HRESULT hr = S_OK;
assert(IFF(ci.cbZoneTicket > 0, ci.pZoneTicket));
Reinitialize(now);
assert (!m_fm.IsConnected() && !m_fLoggedOn);
if (ci.guidSession != GUID_NULL)
{
assert(ci.strServer.IsEmpty());
hr = m_fm.JoinSessionInstance(ci.guidSession, ci.szName);
}
else
{
if (bStandalonePrivate)
hr = m_fm.JoinSession(FEDSRV_STANDALONE_PRIVATE_GUID, ci.strServer, ci.szName);
else hr = m_fm.JoinSession(FEDSRV_GUID, ci.strServer, ci.szName, ci.dwPort);
}
if (m_strCDKey.IsEmpty())
m_strCDKey = ZString(ci.szName).ToUpper();
if (m_fm.IsConnected())
{
ZSucceeded(hr);
SetMessageType(c_mtGuaranteed);
BEGIN_PFM_CREATE(m_fm, pfmLogon, C, LOGONREQ)
FM_VAR_PARM(ci.szName, CB_ZTS)
FM_VAR_PARM(ci.pZoneTicket, ci.cbZoneTicket)
FM_VAR_PARM("FERAL-1234567890123456", CB_ZTS) FM_VAR_PARM(szPassword, CB_ZTS)
END_PFM_CREATE
pfmLogon->fedsrvVer = MSGVER;
pfmLogon->dwCookie = dwCookie;
pfmLogon->time = Time::Now ();
debugf("Logging on to game server \"%s\"...\n",
ci.strServer.IsEmpty() ? "" : (LPCSTR)ci.strServer);
SendMessages();
}
retailf("$$MSRGuard:Set:UserName=%s\n", ci.szName);
m_cUnansweredPings = 0;
m_serverOffsetValidF = false;
return hr;
}
HRESULT BaseClient::ConnectToLobby(ConnectInfo * pci) {
HRESULT hr = S_OK;
if (pci)
{
if (m_ci.pZoneTicket)
HeapFree(GetProcessHeap(), 0, m_ci.pZoneTicket);
m_ci = *pci;
}
m_ci.strServer = GetIsZoneClub() ? GetCfgInfo().strClubLobby : GetCfgInfo().strPublicLobby;
assert(IFF(m_ci.cbZoneTicket > 0, m_ci.pZoneTicket));
if (m_strCDKey.IsEmpty())
m_strCDKey = ZString(m_ci.szName).ToUpper();
if (m_fmLobby.IsConnected())
return S_OK;
assert(m_fLoggedOnToLobby == false);
TMapListWrapper<DWORD, MissionInfo*>::Iterator iterMissions(m_mapMissions);
while (!iterMissions.End())
{
delete iterMissions.Value();
iterMissions.Next();
}
m_mapMissions.SetEmpty();
hr = m_fmLobby.JoinSession(GetIsZoneClub() ? FEDLOBBYCLIENTS_GUID : FEDFREELOBBYCLIENTS_GUID, m_ci.strServer, m_ci.szName, GetCfgInfo().dwLobbyPort);
assert(IFF(m_fmLobby.IsConnected(), SUCCEEDED(hr)));
if (m_fmLobby.IsConnected())
{
DWORD dwTime = Time::Now().clock();
int crcFileList = (g_bCheckFiles ? 0 : FileCRC("FileList.txt", NULL));
char * szEncryptionKey = (char *)_alloca(strlen(CL_LOGON_KEY) + 30);
wsprintf(szEncryptionKey, CL_LOGON_KEY, dwTime, m_ci.szName);
BEGIN_PFM_CREATE(m_fmLobby, pfmLogon, C, LOGON_LOBBY)
FM_VAR_PARM(m_ci.pZoneTicket, m_ci.cbZoneTicket)
FM_VAR_PARM(PCC(m_strCDKey), CB_ZTS) END_PFM_CREATE
pfmLogon->verLobby = LOBBYVER;
pfmLogon->crcFileList = crcFileList;
pfmLogon->dwTime = dwTime;
lstrcpy(pfmLogon->szName, m_ci.szName);
debugf("Logging on to lobby \"%s\"...\n",
m_ci.strServer.IsEmpty() ? "" : (LPCSTR)m_ci.strServer);
lstrcpy(m_szLobbyCharName, m_ci.szName);
SendLobbyMessages();
}
retailf("$$MSRGuard:Set:UserName=%s\n", m_szLobbyCharName);
m_cUnansweredPings = 0;
m_serverOffsetValidF = false;
return hr;
}
HRESULT BaseClient::ConnectToClub(ConnectInfo * pci) {
HRESULT hr = S_OK;
if (m_fmClub.IsConnected())
return S_OK;
if (pci)
{
if (m_ci.pZoneTicket)
HeapFree(GetProcessHeap(), 0, m_ci.pZoneTicket);
m_ci = *pci;
}
assert(IFF(m_ci.cbZoneTicket > 0, m_ci.pZoneTicket));
if (m_fmClub.IsConnected())
return S_OK;
assert(m_fLoggedOnToClub == false);
hr = m_fmClub.JoinSession(FEDCLUB_GUID, m_ci.strServer, m_ci.szName);
assert(IFF(m_fmClub.IsConnected(), SUCCEEDED(hr)));
if (m_fmClub.IsConnected())
{
BEGIN_PFM_CREATE(m_fmClub, pfmLogon, C, LOGON_CLUB)
FM_VAR_PARM(pci->szName, CB_ZTS)
FM_VAR_PARM(m_ci.pZoneTicket, m_ci.cbZoneTicket)
END_PFM_CREATE
pfmLogon->verClub = ALLCLUBVER;
debugf("Logging on to Club Server...\n");
lstrcpy(m_szClubCharName, pci->szName);
SendClubMessages();
}
m_cUnansweredPings = 0;
m_serverOffsetValidF = false;
return hr;
}
void BaseClient::FindStandaloneServersByName(const char* szName, TList<TRef<LANServerInfo> >& listResults)
{
listResults.SetEmpty();
m_plistFindServerResults = &listResults;
m_fm.EnumSessions(FEDSRV_STANDALONE_PRIVATE_GUID, szName);
m_plistFindServerResults = NULL;
};
void BaseClient::SetCDKey(const ZString& strCDKey)
{
m_strCDKey = strCDKey;
}
void BaseClient::HandleAutoDownload(DWORD dwTimeAlloted)
{
if (m_pAutoDownload)
{
m_pAutoDownload->HandleAutoDownload(dwTimeAlloted);
}
}
IweaponIGC* BaseClient::GetWeapon(void)
{
return (IweaponIGC*)m_ship->GetMountedPart(ET_Weapon, m_selectedWeapon);
}
void BaseClient::SetAutoPilot(bool autoPilot)
{
m_ship->SetAutopilot(autoPilot);
}
void BaseClient::DisconnectLobby()
{
m_fLoggedOnToLobby = false;
if (m_fmLobby.IsConnected())
m_fmLobby.Shutdown();
}
void BaseClient::DisconnectClub()
{
m_fLoggedOnToClub = false;
if (m_fmClub.IsConnected())
m_fmClub.Shutdown();
m_szClubCharName[0] = '\0';
}
void BaseClient::Disconnect(void)
{
if (m_fLoggedOn)
{
SetMessageType(c_mtGuaranteed);
BEGIN_PFM_CREATE(m_fm, pfmLogoff, CS, LOGOFF)
END_PFM_CREATE
SendMessages();
Sleep(500);
}
if (m_fm.IsConnected())
{
m_fm.Shutdown();
m_fLoggedOn = false;
}
m_szCharName[0] = '\0';
m_szIGCStaticFile[0] = '\0';
}
void BaseClient::SetPlayerInfo(PlayerInfo* p)
{
assert (p);
m_pPlayerInfo = p;
m_ship->SetObjectID(p->ShipID());
m_ship->SetName(p->CharacterName());
assert (p->SideID() == NA);
assert (m_ship->GetSide() == NULL);
}
void BaseClient::SetViewCluster(IclusterIGC* pcluster, const Vector* pposition)
{
m_viewCluster = pcluster;
}
void BaseClient::ResetShip(void)
{
assert (GetSide());
{
const PartListIGC* plist = m_ship->GetParts();
PartLinkIGC* plink;
while (plink = plist->first()) {
plink->data()->Terminate();
}
}
m_ship->SetBaseHullType(GetSide()->GetCivilization()->GetLifepod());
m_ship->SetAmmo(0);
m_ship->SetFuel(0.0f);
m_pmodelServerTarget = NULL;
}
void BaseClient::ResetClusterScanners(IsideIGC* pside)
{
SideID sid = pside->GetObjectID();
{
for (StationLinkIGC* l = pside->GetStations()->first();
(l != NULL);
l = l->next())
{
IstationIGC* pstation = l->data();
pstation->GetCluster()->GetClusterSite()->AddScanner(sid, pstation);
}
}
{
}
}
void BaseClient::BuyLoadout(IshipIGC* pshipLoadout, bool bLaunch)
{
assert(pshipLoadout);
if (m_fm.IsConnected ())
{
SetMessageType(c_mtGuaranteed);
BEGIN_PFM_CREATE(m_fm, pfmBuyLoadout, C, BUY_LOADOUT)
FM_VAR_PARM(NULL, pshipLoadout->ExportShipLoadout(NULL))
END_PFM_CREATE
assert (pshipLoadout->GetBaseHullType());
pshipLoadout->ExportShipLoadout((ShipLoadout*)(FM_VAR_REF(pfmBuyLoadout, loadout)));
pfmBuyLoadout->fLaunch = bLaunch;
if (bLaunch)
StartLockDown("Preparing ship for launch....", lockdownLoadout);
else
StartLockDown("Loading out ship....", lockdownLoadout);
}
else
{
short size = pshipLoadout->ExportShipLoadout(NULL);
void* ptr = new char[size];
pshipLoadout->ExportShipLoadout (static_cast <ShipLoadout*> (ptr));
m_ship->PurchaseShipLoadout (size, static_cast <ShipLoadout*> (ptr));
m_pClientEventSource->OnPurchaseCompleted (true);
delete ptr;
}
}
IshipIGC* BaseClient::CopyCurrentShip(void)
{
assert (m_ship);
TRef<IshipIGC> pshipLoadout = CreateEmptyShip();
pshipLoadout->SetBaseHullType(m_ship->GetBaseHullType());
for (PartLinkIGC* ppl = m_ship->GetParts()->first(); (ppl != NULL); ppl = ppl->next())
{
IpartIGC* ppart = ppl->data();
pshipLoadout->CreateAndAddPart(ppart->GetPartType(), ppart->GetMountID(), ppart->GetAmount());
}
return pshipLoadout;
}
IshipIGC* BaseClient::CreateEmptyShip(ShipID sid)
{
DataShipIGC ds;
ds.hullID = NA;
ds.shipID = sid;
ds.nParts = 0;
ds.sideID = SIDE_TEAMLOBBY;
ds.name[0] = '\0';
ds.pilotType = c_ptCheatPlayer;
ds.abmOrders = 0;
ds.nDeaths = 0;
ds.nEjections = 0;
ds.nKills = 0;
ds.baseObjectID = NA;
IshipIGC* pship = (IshipIGC*)(m_pCoreIGC->CreateObject(m_lastSend, OT_ship, &ds, sizeof(ds)));
return pship;
}
void BaseClient::SetMoney(Money m)
{
assert(m >= 0);
if (m_pPlayerInfo)
{
m_pPlayerInfo->SetMoney(m);
m_pClientEventSource->OnMoneyChange(m_pPlayerInfo);
}
if (m_pMissionInfo)
{
SideInfo* psideinfo = m_pMissionInfo->GetSideInfo(GetSideID());
if (psideinfo)
{
psideinfo->GetMembers().GetSink()();
}
}
}
bool BaseClient::SendUpdate(Time now)
{
bool fSent = false;
if (flyingF() && m_fm.IsConnected())
{
if (m_ship->GetParentShip() == NULL)
{
static const int smSendUpdateNow = weaponsMaskIGC | selectedWeaponMaskIGC |
coastButtonIGC |
backwardButtonIGC | forwardButtonIGC |
leftButtonIGC | rightButtonIGC |
upButtonIGC | downButtonIGC |
afterburnerButtonIGC;
if ((now >= m_lastSend + c_dsecUpdateClient) )
{
ZAssert(m_ship->GetPosition().LengthSquared());
m_lastSend = now;
SetMessageType(c_mtNonGuaranteed);
BEGIN_PFM_CREATE(m_fm, pfmShip, C, SHIP_UPDATE)
END_PFM_CREATE
m_ship->ExportShipUpdate(&(pfmShip->shipupdate));
pfmShip->cookie = m_cookie;
pfmShip->timeUpdate = ServerTimeFromClientTime(m_ship->GetLastUpdate());
fSent = true;
}
}
else
{
static const int smSendUpdateNow = weaponsMaskIGC;
if ((now >= m_lastSend + c_dsecUpdateClient) )
{
m_lastSend = now;
SetMessageType(c_mtNonGuaranteed);
int stateM = m_ship->GetStateM();
if (stateM & weaponsMaskIGC)
{
BEGIN_PFM_CREATE(m_fm, pfmTurret, C, ACTIVE_TURRET_UPDATE)
END_PFM_CREATE
m_ship->ExportShipUpdate(&(pfmTurret->atu));
pfmTurret->timeUpdate = ServerTimeFromClientTime(m_ship->GetLastUpdate());
}
else
{
BEGIN_PFM_CREATE(m_fm, pfmTurret, C, INACTIVE_TURRET_UPDATE)
END_PFM_CREATE
}
fSent = true;
}
}
}
return(fSent);
}
void BaseClient::SetMessageType(MessageType messageType)
{
assert(IMPLIES(m_messageType == c_mtNone, m_fm.CbUsedSpaceInOutbox() == 0));
if (messageType != m_messageType)
{
SendMessages();
m_messageType = messageType;
}
}
void BaseClient::SendMessages(void)
{
assert (IMPLIES((m_messageType == c_mtNone), (m_fm.CbUsedSpaceInOutbox() == 0)));
if (m_messageType != c_mtNone)
{
ZSucceeded(m_fm.SendMessages(m_fm.GetServerConnection(),
m_messageType == c_mtGuaranteed ? FM_GUARANTEED : FM_NOT_GUARANTEED,
FM_FLUSH));
m_messageType = c_mtNone;
}
}
void BaseClient::NextWeapon(void)
{
assert (m_ship);
if (m_ship->GetParentShip() == NULL)
{
Mount nHardpoints = m_ship->GetHullType()->GetMaxFixedWeapons();
if (nHardpoints > 0)
{
Mount startWeapon = m_selectedWeapon;
IpartIGC* p;
do
{
m_selectedWeapon = (m_selectedWeapon + 1) % nHardpoints;
p = m_ship->GetMountedPart(ET_Weapon, m_selectedWeapon);
}
while ((p == NULL) && (m_selectedWeapon != startWeapon));
}
}
}
void BaseClient::PreviousWeapon(void)
{
assert (m_ship);
if (m_ship->GetParentShip() == NULL)
{
Mount nHardpoints = m_ship->GetHullType()->GetMaxFixedWeapons();
if (nHardpoints > 0)
{
Mount startWeapon = m_selectedWeapon;
IpartIGC* p;
do
{
m_selectedWeapon =
m_selectedWeapon ? (m_selectedWeapon - 1) : nHardpoints - 1;
p = m_ship->GetMountedPart(ET_Weapon, m_selectedWeapon);
}
while ((p == NULL) && (m_selectedWeapon != startWeapon));
}
}
}
void BaseClient::SetSelectedWeapon(Mount id)
{
assert (m_ship);
if (m_ship->GetParentShip() == NULL)
{
Mount nHardpoints = m_ship->GetHullType()->GetMaxFixedWeapons();
if (id < nHardpoints && m_ship->GetMountedPart(ET_Weapon, id))
{
m_selectedWeapon = id;
}
}
}
void BaseClient::JoinMission(MissionInfo * pMission, const char* szMissionPassword)
{
assert (pMission);
BEGIN_PFM_CREATE(m_fmLobby, pfmJoinGameReq, C, JOIN_GAME_REQ)
END_PFM_CREATE
pfmJoinGameReq->dwCookie = pMission->GetCookie();
SendLobbyMessages();
m_dwCookieToJoin = pMission->GetCookie();
assert(strlen(szMissionPassword) < c_cbGamePassword);
strncpy(m_strPasswordToJoin, szMissionPassword, c_cbGamePassword);
m_strPasswordToJoin[c_cbGamePassword - 1] = '\0';
}
void BaseClient::CreateMissionReq()
{
BEGIN_PFM_CREATE(m_fmLobby, pfmCreateMission, C, CREATE_MISSION_REQ)
END_PFM_CREATE
SendLobbyMessages();
}
void BaseClient::ServerListReq()
{
BEGIN_PFM_CREATE(m_fmLobby, pfmGetServerReq, C, GET_SERVERS_REQ)
END_PFM_CREATE
SendLobbyMessages();
}
void BaseClient::CreateMissionReq(const char *szServer, const char *szAddr, const char *szIGCStaticFile, const char *szGameName)
{
BEGIN_PFM_CREATE(m_fmLobby, pfmCreateMission, C, CREATE_MISSION_REQ)
FM_VAR_PARM(szServer, CB_ZTS)
FM_VAR_PARM(szAddr, CB_ZTS)
FM_VAR_PARM(szIGCStaticFile, CB_ZTS)
FM_VAR_PARM(szGameName, CB_ZTS)
END_PFM_CREATE
SendLobbyMessages();
}
#ifdef markcu
const int g_cPingsTimeout = int(unsigned(1<<31)-1); #else
const int g_cPingsTimeout = 5;
#endif
const DWORD g_sDeadTime = 30; void BaseClient::CheckServerLag(Time now)
{
const float maxLagCheck = 6.0f;
const float minLagCheck = 1.0f;
if (m_fm.IsConnected())
{
if (m_lastLagCheck + maxLagCheck <= now)
{
if (m_cUnansweredPings > g_cPingsTimeout && (now - m_timeLastServerMessage) >= g_sDeadTime)
{
OnSessionLost("Pings aren't coming back.", &m_fm);
}
else
{
m_lastLagCheck = now;
bool bGuaranteed = m_cUnansweredPings > g_cPingsTimeout;
SetMessageType(bGuaranteed ? c_mtGuaranteed : c_mtNonGuaranteed);
BEGIN_PFM_CREATE(m_fm, pfmPing, CS, PING)
END_PFM_CREATE
pfmPing->fmg = bGuaranteed ? FM_GUARANTEED : FM_NOT_GUARANTEED;
pfmPing->timeClient = Time::Now();
SendMessages();
m_cUnansweredPings++;
}
}
}
}
HRESULT BaseClient::ReceiveMessages(void)
{
HRESULT hr;
if (m_fm.IsConnected())
hr = m_fm.ReceiveMessages();
else
hr = S_OK;
if (m_fmLobby.IsConnected())
{
if (FAILED(hr)) m_fmLobby.ReceiveMessages();
else
hr = m_fmLobby.ReceiveMessages();
}
if (m_fmClub.IsConnected())
{
if (FAILED(hr)) m_fmClub.ReceiveMessages();
else
hr = m_fmClub.ReceiveMessages();
}
return(hr);
}
HRESULT BaseClient::OnSessionLost(char * szReason, FedMessaging * pthis)
{
debugf("OnSessionLost. %s. lastUpdate=%d now=%d Time::Now()=%d\n",
szReason, m_lastUpdate.clock(), m_now.clock(), Time::Now().clock());
m_fLoggedOn = false; if (pthis == &m_fm)
Disconnect();
else if (pthis == &m_fmClub)
DisconnectClub();
else if (pthis == &m_fmLobby)
DisconnectLobby();
else
assert(false);
return(S_OK);
}
void BaseClient::OnMessageNAK(FedMessaging * pthis, DWORD dwTime, CFMRecipient * prcp)
{
OnSessionLost("guaranteed message couldn't be delivered", pthis);
}
HRESULT BaseClient::OnSessionLost(FedMessaging * pthis)
{
return OnSessionLost("DPlay session terminated", pthis);
}
void BaseClient::OnSessionFound(FedMessaging * pthis, FMSessionDesc * pSessionDesc)
{
m_plistFindServerResults->PushEnd(
new LANServerInfo(pSessionDesc->GetInstance(), pSessionDesc->GetGameName(),
pSessionDesc->GetNumPlayers(), pSessionDesc->GetMaxPlayers())
);
}
void BaseClient::ReceiveChat(IshipIGC* pshipSender,
ChatTarget ctRecipient,
ObjectID oidRecipient,
SoundID voiceOver,
const char* pszText,
CommandID cid,
ObjectType otTarget,
ObjectID oidTarget,
ImodelIGC* pmodelTarget,
bool bObjectModel)
{
m_pClientEventSource->OnNewChatMessage();
}
bool BaseClient::ParseShellCommand(const char* pszCommand)
{
bool bCommand = false;
if (_strnicmp(pszCommand, "!mute ", 6) == 0)
{
PlayerInfo* ppi = FindPlayer(pszCommand + 6);
if (ppi)
ppi->SetMute(true);
bCommand = true;
}
else if (_strnicmp(pszCommand, "!unmute ", 8) == 0)
{
PlayerInfo* ppi = FindPlayer(pszCommand + 8);
if (ppi)
ppi->SetMute(false);
bCommand = true;
}
#ifdef _DEBUG
else if (_strnicmp(pszCommand, "!chatcountdown ", 8) == 0)
{
int i = atoi(pszCommand + strlen("!chatcountdown "));
char cbTemp[20];
for (; i > 0; i--)
{
SendChat(m_ship, CHAT_EVERYONE, NA, NA, _itoa(i, cbTemp, 10));
if (i % 16 == 0)
SendMessages();
}
bCommand = true;
}
#endif
return bCommand;
}
void BaseClient::SendChat(IshipIGC* pshipSender,
ChatTarget ctRecipient,
ObjectID oidRecipient,
SoundID soundID,
const char* pszText,
CommandID cid,
ObjectType otTarget,
ObjectID oidTarget,
ImodelIGC* pmodelTarget,
bool bObjectModel)
{
if (oidRecipient == NA)
{
switch (ctRecipient)
{
case CHAT_INDIVIDUAL:
oidRecipient = m_ship->GetObjectID();
break;
case CHAT_WING:
oidRecipient = m_ship->GetWingID();
break;
case CHAT_TEAM:
oidRecipient = m_ship->GetSide()->GetObjectID();
break;
case CHAT_ALL_SECTOR:
case CHAT_FRIENDLY_SECTOR:
{
IclusterIGC* pcluster = GetChatCluster();
if (pcluster)
oidRecipient = pcluster->GetObjectID();
else
{
oidRecipient = m_ship->GetSide()->GetObjectID();
ctRecipient = CHAT_TEAM;
}
}
break;
}
}
if ((ctRecipient == CHAT_INDIVIDUAL) || (ctRecipient == CHAT_GROUP) || (ctRecipient == CHAT_GROUP_NOECHO))
{
IshipIGC* pship = m_pCoreIGC->GetShip(oidRecipient);
if ((pship == NULL) || (pship->GetMission() == NULL))
return; PilotType pilotType = pship->GetPilotType();
if ((!m_fm.IsConnected ()) && (pilotType < c_ptPlayer) && (cid != c_cidNone))
{
if ((cid == c_cidDefault) && (pmodelTarget != NULL))
{
cid = c_cidGoto;
if (ctRecipient == CHAT_INDIVIDUAL)
{
switch (pilotType)
{
case c_ptMiner:
case c_ptBuilder:
{
if ((pmodelTarget->GetObjectType() == OT_asteroid) && ((IasteroidIGC*) pmodelTarget)->HasCapability(pship->GetOrdersABM()))
{
cid = (pilotType == c_ptMiner) ? c_cidMine : c_cidBuild;
}
}
break;
case c_ptLayer:
{
if (pmodelTarget->GetObjectType() == OT_buoy)
{
cid = c_cidBuild;
}
}
break;
case c_ptWingman:
{
if (pmodelTarget->GetSide() == pship->GetSide ())
cid = c_cidDefend;
else
cid = c_cidAttack;
}
}
}
}
pship->SetCommand (c_cmdCurrent, pmodelTarget, cid);
pship->SetCommand (c_cmdAccepted, pmodelTarget, cid);
}
}
if (m_fm.IsConnected() &&
(ctRecipient != CHAT_NOSELECTION) &&
((ctRecipient != CHAT_INDIVIDUAL) ||
(oidRecipient != m_ship->GetObjectID())))
{
SetMessageType(BaseClient::c_mtGuaranteed);
ChatData* pcd;
if (otTarget == OT_buoy)
{
BEGIN_PFM_CREATE(m_fm, pfmChatBuoy, CS, CHATBUOY)
FM_VAR_PARM(pszText, CB_ZTS)
END_PFM_CREATE
pcd = &(pfmChatBuoy->cd);
assert (pmodelTarget);
pmodelTarget->Export(&(pfmChatBuoy->db));
}
else
{
BEGIN_PFM_CREATE(m_fm, pfmChatMessage, CS, CHATMESSAGE)
FM_VAR_PARM(pszText, CB_ZTS)
END_PFM_CREATE
pcd = &(pfmChatMessage->cd);
pfmChatMessage->otTarget = otTarget;
pfmChatMessage->oidTarget = oidTarget;
}
pcd->chatTarget = ctRecipient;
pcd->oidRecipient = oidRecipient;
pcd->commandID = cid;
pcd->voiceOver = soundID;
pcd->bObjectModel = bObjectModel;
}
if (ctRecipient != CHAT_GROUP_NOECHO)
{
ReceiveChat(pshipSender,
ctRecipient, oidRecipient,
soundID, pszText,
cid, otTarget, oidTarget, pmodelTarget, bObjectModel);
}
}
void BaseClient::ScrollChatUp(void)
{
if (m_plinkSelectedChat == NULL)
m_plinkSelectedChat = m_chatList.last();
else if (m_plinkSelectedChat != m_chatList.first())
m_plinkSelectedChat = m_plinkSelectedChat->txen();
}
void BaseClient::ScrollChatDown(void)
{
if (m_plinkSelectedChat != NULL)
m_plinkSelectedChat = m_plinkSelectedChat->next();
}
ChatInfo* BaseClient::GetCurrentMessage(void)
{
ChatLink* l = (m_plinkSelectedChat != NULL)
? m_plinkSelectedChat
: m_chatList.last();
return l ? &(l->data()) : NULL;
}
BallotInfo* BaseClient::GetCurrentBallot()
{
Time now = Time::Now();
while (!m_listBallots.IsEmpty() && m_listBallots.GetFront().GetBallotExpirationTime() < now)
m_listBallots.PopFront();
if (m_listBallots.IsEmpty())
return NULL;
else
return &(m_listBallots.GetFront());
}
void BaseClient::Vote(bool bAgree)
{
if (!m_listBallots.IsEmpty())
{
SetMessageType(c_mtGuaranteed);
BEGIN_PFM_CREATE(m_fm, pfmVote, C, VOTE)
END_PFM_CREATE
pfmVote->ballotID = m_listBallots.GetFront().GetBallotID();
pfmVote->bAgree = bAgree;
m_listBallots.PopFront();
}
}
void BaseClient::SkipCurrentBallot()
{
if (!m_listBallots.IsEmpty())
{
m_listBallots.PopFront();
}
}
Money BaseClient::GetBucketStatus(StationID stationID, short iBucket)
{
TRef<BucketStatusArray> prgStatus;
if (m_mapBucketStatusArray.Find(stationID, prgStatus))
return (*prgStatus)[iBucket];
else
return 0;
}
Money BaseClient::AddMoneyToBucket(IbucketIGC* b,
Money m)
{
assert (b);
Money spent = b->AddMoney(m);
SetMoney(GetMoney() - spent);
if (m_fm.IsConnected())
{
SetMessageType(c_mtGuaranteed);
BEGIN_PFM_CREATE(m_fm, pfmBD, C, BUCKET_DONATE)
END_PFM_CREATE
pfmBD->moneyGiven = spent;
pfmBD->iBucket = b->GetObjectID();
}
return spent;
}
void BaseClient::DonateMoney(PlayerInfo* pPlayerInfo, Money money)
{
if (m_fm.IsConnected())
{
SetMessageType(c_mtGuaranteed);
BEGIN_PFM_CREATE(m_fm, pfmDonate, C, PLAYER_DONATE)
END_PFM_CREATE
pfmDonate->moneyGiven = money;
pfmDonate->shipID = pPlayerInfo->ShipID();
}
pPlayerInfo->SetMoney(pPlayerInfo->GetMoney() + money);
m_pClientEventSource->OnMoneyChange(pPlayerInfo);
SetMoney(GetMoney() - money);
}
MissionInfo* BaseClient::GetLobbyMission(DWORD dwCookie)
{
MissionInfo* pMissionInfo = NULL;
if (!m_mapMissions.Find(dwCookie, pMissionInfo))
{
pMissionInfo = new MissionInfo(dwCookie);
m_mapMissions.Set(dwCookie, pMissionInfo);
}
return pMissionInfo;
}
PlayerLink* BaseClient::FindPlayerLink(ShipID shipID)
{
PlayerLink* l = m_listPlayers.first();
while ((l != NULL) && (l->data().ShipID() != shipID))
l = l->next();
return l;
}
PlayerInfo* BaseClient::FindAndCreatePlayerLink(ShipID shipID)
{
PlayerLink* l = FindPlayerLink(shipID);
if (l == NULL)
{
l = new PlayerLink;
m_listPlayers.last(l);
}
return &(l->data ());
}
PlayerInfo* BaseClient::FindPlayer(ShipID shipID)
{
PlayerLink* l = FindPlayerLink(shipID);
return l ? &(l->data()) : NULL;
}
PlayerInfo* BaseClient::FindPlayer(const char* szName)
{
PlayerInfo* p = NULL;
for (PlayerLink* l = m_listPlayers.first(); (l != NULL); l = l->next())
{
if (_stricmp(l->data().CharacterName(), szName) == 0)
{
p = &(l->data());
break;
}
}
return p;
}
PlayerInfo* BaseClient::FindPlayerByPrefix(const char* szNamePrefix)
{
PlayerInfo* p = NULL;
int lenNamePrefix = strlen(szNamePrefix);
for (PlayerLink* l = m_listPlayers.first(); (l != NULL); l = l->next())
{
PlayerInfo& player = l->data();
if (_strnicmp(player.CharacterName(), szNamePrefix, lenNamePrefix) == 0)
{
p = &player;
break;
}
}
return p;
}
namespace {
void RemoveTrailingSpaces(char* sz)
{
for (int nIndex = strlen(sz); nIndex > 0 && sz[nIndex - 1] == ' '; --nIndex)
{
sz[nIndex - 1] = '\0';
}
};
}
ZString BaseClient::LookupRankName(RankID rank, CivID civ)
{
const char* szRankNameTemplate = "Unknown (%d)";
int nClosestRank = -1;
if (m_cRankInfo <= 0 && !GetIsZoneClub())
{
assert(!m_fm.IsConnected() || !GetIsZoneClub());
szRankNameTemplate = "";
}
else
{
if (!GetIsZoneClub()) civ = -1;
for (int iEntry = 0; iEntry < m_cRankInfo; iEntry++)
{
if (m_vRankInfo[iEntry].civ == civ
&& m_vRankInfo[iEntry].rank <= rank
&& m_vRankInfo[iEntry].rank >= nClosestRank)
{
szRankNameTemplate = m_vRankInfo[iEntry].RankName;
nClosestRank = m_vRankInfo[iEntry].rank;
}
}
assert(nClosestRank >= 0);
}
char cbTemp[c_cbName + 8];
wsprintf(cbTemp, szRankNameTemplate, rank - nClosestRank + 1);
RemoveTrailingSpaces(cbTemp);
return cbTemp;
}
List* BaseClient::GetMissionList()
{
return m_plistMissions;
}
void BaseClient::QuitMission()
{
BaseClient::SetMessageType(c_mtGuaranteed);
BEGIN_PFM_CREATE(*GetNetwork(), pfmQuitMission, CS, QUIT_MISSION)
END_PFM_CREATE
pfmQuitMission->shipID = GetShipID();
pfmQuitMission->reason = QSR_Quit;
}
bool BaseClient::MyMissionInProgress()
{
if (m_pMissionInfo)
return m_pMissionInfo->InProgress();
else
return false;
}
void BaseClient::SaveSquadMemberships(const char* szCharacterName)
{
}
void BaseClient::RestoreSquadMemberships(const char* szCharacterName)
{
}
bool BaseClient::HasPlayerSquad(MissionInfo* pMission)
{
for (TList<SquadMembership>::Iterator iterSquad(m_squadmemberships);
!iterSquad.End(); iterSquad.Next())
{
if (pMission->HasSquad(iterSquad.Value().GetID()))
return true;
}
return false;
}
void BaseClient::SendAllMissions(IClientEventSink* pSink)
{
TMapListWrapper<DWORD, MissionInfo*>::Iterator iterMissions(m_mapMissions);
MissionInfo* pMissionInfo;
while (!iterMissions.End())
{
pMissionInfo = iterMissions.Value();
pSink->OnAddMission(pMissionInfo);
iterMissions.Next();
}
}
void BaseClient::SendAllPlayers(IClientEventSink* pSink, MissionInfo* pMissionInfo, SideID sideID)
{
if (pMissionInfo)
{
ShipList::Iterator iterPlayers(pMissionInfo->GetSideInfo(sideID)->GetMembers());
PlayerInfo* pPlayerInfo;
ShipID shipID;
while (!iterPlayers.End())
{
shipID = iterPlayers.Value();
if (pPlayerInfo = FindPlayer(shipID))
pSink->OnAddPlayer(pMissionInfo, sideID, pPlayerInfo);
iterPlayers.Next();
}
}
}
void BaseClient::SendAllRequests(IClientEventSink* pSink, MissionInfo* pMissionInfo, SideID sideID)
{
ShipList::Iterator iterRequests(pMissionInfo->GetSideInfo(sideID)->GetRequests());
PlayerInfo* pPlayerInfo;
ShipID shipID;
while (!iterRequests.End())
{
shipID = iterRequests.Value();
if (pPlayerInfo = FindPlayer(shipID))
pSink->OnAddRequest(pMissionInfo, sideID, pPlayerInfo);
iterRequests.Next();
}
}
void BaseClient::TerminateModelEvent(ImodelIGC* pModel)
{
ObjectType type = pModel->GetObjectType();
if (type != OT_projectile) {
{
bool fChanges = false;
for (ChatLink* l = m_chatList.first();
(l != NULL);
l = l->next())
{
ChatInfo& cw = l->data();
if (cw.GetTarget() == pModel)
{
cw.ClearTarget();
fChanges = true;
}
}
if (fChanges)
m_pClientEventSource->OnChatMessageChange();
}
for (Command i = 0; (i < c_cmdMax); i++)
{
if (m_ship->GetCommandTarget(i) == pModel)
m_ship->SetCommand(i, NULL, c_cidNone);
}
if (pModel == m_pmodelServerTarget)
m_pmodelServerTarget = NULL;
}
m_pClientEventSource->OnModelTerminated(pModel);
}
void BaseClient::LoadoutChangeEvent(IshipIGC* pship, IpartIGC* ppart, LoadoutChange lc)
{
if (m_ship->GetSourceShip() == pship)
m_pClientEventSource->OnLoadoutChanged(ppart, lc);
}
void BaseClient::BucketChangeEvent(BucketChange bc, IbucketIGC* b)
{
m_pClientEventSource->OnBucketChange(bc, b);
}
void BaseClient::SideBuildingTechChange(IsideIGC* s)
{
SideID sid = s->GetObjectID();
m_pClientEventSource->OnTechTreeChanged(sid);
}
void BaseClient::SideDevelopmentTechChange(IsideIGC* s)
{
SideID sid = s->GetObjectID();
m_pClientEventSource->OnTechTreeChanged(sid);
}
void BaseClient::StationTypeChange(IstationIGC* s)
{
SideID sid = s->GetSide()->GetObjectID();
m_pClientEventSource->OnTechTreeChanged(sid);
}
static ItreasureIGC* CreateTreasure(BaseClient* pClient, Time now, IshipIGC* pship, IpartIGC* p, IpartTypeIGC* ppt, const Vector& position, float dv)
{
assert (ppt);
assert (dv > 1.0f);
assert (pship);
DataTreasureIGC dt;
dt.treasureCode = c_tcPart;
dt.treasureID = ppt->GetObjectID();
dt.objectID = pClient->m_pCoreIGC->GenerateNewTreasureID();
dt.p0 = position;
Vector direction;
{
direction.z = random(-1.0f, 1.0f);
float yaw = random(0.0f, pi);
float cosPitch = (float)sqrt(1.0f - direction.z * direction.z);
direction.x = cos(yaw) * cosPitch;
direction.y = sin(yaw) * cosPitch;
}
float radius = pship->GetRadius() + 10.0f;
dt.p0 += radius * direction;
dt.v0 = direction * dv + pship->GetVelocity();
switch (ppt->GetEquipmentType())
{
case ET_Magazine:
case ET_Dispenser:
{
assert (p);
dt.amount = ((IlauncherIGC*)p)->GetAmount();
}
break;
case ET_Pack:
{
DataPackTypeIGC* pdp = (DataPackTypeIGC*)(ppt->GetData());
dt.amount = pdp->amount;
}
break;
default:
dt.amount = 0;
}
dt.lifespan = 600.0f;
IclusterIGC* pcluster = pship->GetCluster();
dt.clusterID = pcluster->GetObjectID();
dt.createNow = false;
dt.time0 = pClient->ServerTimeFromClientTime(now);
ItreasureIGC* t = (ItreasureIGC *)
pClient->m_pCoreIGC->CreateObject(now, OT_treasure,
&dt, sizeof(dt));
assert (t);
t->Release();
return t;
}
void BaseClient::KillAsteroidEvent(IasteroidIGC* pasteroid, bool explodeF)
{
if (!m_fm.IsConnected())
{
if (explodeF)
pasteroid->GetCluster()->GetClusterSite()->AddExplosion(pasteroid, c_etAsteroid);
pasteroid->Terminate();
}
}
void BaseClient::KillProbeEvent(IprobeIGC* pprobe)
{
if (!m_fm.IsConnected())
pprobe->Terminate();
}
void BaseClient::KillMineEvent(ImineIGC* pmine)
{
if (!m_fm.IsConnected())
pmine->Terminate();
}
void BaseClient::KillMissileEvent(ImissileIGC* pmissile, const Vector& position)
{
if (!m_fm.IsConnected())
{
pmissile->Explode(position);
pmissile->Terminate();
}
else
pmissile->Disarm();
}
void BaseClient::KillShipEvent(Time now, IshipIGC* pShip, ImodelIGC* pLauncher, float flAmount, const Vector& p1, const Vector& p2)
{
if (!m_fm.IsConnected())
{
if (pShip == m_ship->GetSourceShip())
{
Vector v = pShip->GetVelocity();
pShip->SetBaseHullType(pShip->GetSide()->GetCivilization()->GetLifepod());
Vector f = Vector::RandomDirection();
Orientation o;
if (pLauncher)
{
if (pLauncher->GetCluster() == pShip->GetCluster())
{
Vector dp = (pLauncher->GetPosition() - p1).Normalize();
o.Set(dp);
f = (f + dp * 8.0f).Normalize();
}
else
{
o.Set(f);
}
}
else
{
Vector dp = (p2 - p1).Normalize();
o.Set(dp);
f = (f + dp * 8.0f).Normalize();
}
v -= f * 100.0f;
pShip->SetCurrentTurnRate(c_axisRoll, pi * 2.0f);
pShip->SetPosition(p1);
pShip->SetVelocity(v);
pShip->SetOrientation(o);
pShip->SetBB(now, now, 0.0f);
EjectPlayer(pLauncher);
}
else
{
PlayerInfo* pPlayerInfo = reinterpret_cast<PlayerInfo*> (pShip->GetPrivateData ());
RemovePlayerFromSide (pPlayerInfo, QSR_Quit);
RemovePlayerFromMission (pPlayerInfo, QSR_Quit);
}
}
}
void BaseClient::DamageStationEvent(IstationIGC* pStation,
ImodelIGC* pLauncher,
DamageTypeID type,
float flAmount,
float flLeakage)
{
if ((NULL != pStation->GetCluster()) &&
(pStation->GetCluster() == GetCluster()))
{
if (pStation->GetShieldFraction() < 0.0f)
this->PlaySoundEffect(otherHullHitSound, pStation);
else
this->PlaySoundEffect(otherShieldHitSound, pStation);
}
}
void BaseClient::KillStationEvent(IstationIGC* pStation,
ImodelIGC* pLauncher,
float flAmount,
float flLeakage)
{
if (!m_fm.IsConnected())
{
pStation->GetCluster()->GetClusterSite()->AddExplosion(pStation, c_etLargeStation);
pStation->Terminate();
}
}
void BaseClient::FireMissile(IshipIGC* pShip,
ImagazineIGC* pMagazine,
Time timeFired,
ImodelIGC* pTarget,
float flLock)
{
assert (pShip == m_ship);
if (pTarget &&
((pTarget->GetCluster() != m_ship->GetCluster()) ||
!m_ship->CanSee(pTarget)))
pTarget = NULL;
this->PlaySoundEffect(pMagazine->GetMissileType()->GetLaunchSound(), pShip);
this->PlayFFEffect(effectFire);
IclusterIGC* pCluster = pShip->GetCluster();
assert (pCluster);
const Vector& myVelocity = pShip->GetVelocity();
const Orientation& myOrientation = pShip->GetOrientation();
Vector myPosition = pShip->GetPosition() +
pMagazine->GetEmissionPt() * myOrientation;
int iNumMissiles = pMagazine->GetLaunchCount ();
int iNumRemainingMissiles = pMagazine->GetAmount ();
Time lastUpdate = pShip->GetLastUpdate();
if (iNumRemainingMissiles < iNumMissiles)
iNumMissiles = iNumRemainingMissiles;
iNumRemainingMissiles -= iNumMissiles;
DataMissileIGC dataMissile;
dataMissile.pmissiletype = pMagazine->GetMissileType();
dataMissile.pLauncher = pShip;
dataMissile.pTarget = pTarget;
dataMissile.pCluster = pCluster;
dataMissile.lock = flLock;
Vector vecLaunchPosition = myPosition + (myVelocity * (timeFired - lastUpdate));
Vector vecLaunchForward = myOrientation.GetForward();
Vector vecLaunchVelocity = myVelocity;
MissileLaunchData* missileLaunchData = new MissileLaunchData[iNumMissiles];
float fDispersion = dataMissile.pmissiletype->GetDispersion();
float fDispersionBase = -fDispersion;
float fUniformDispersion = (2.0f * fDispersion) / (float) iNumMissiles;
float fHalfUniformDispersion = fUniformDispersion * 0.5f;
for (int i = 0; i < iNumMissiles; i++)
{
missileLaunchData[i].vecForward = vecLaunchForward;
if (fDispersion != 0.0f)
{
float fRandomDispersion = (random (-0.75f, 0.75f) * fHalfUniformDispersion) + (fDispersionBase + fHalfUniformDispersion);
fDispersionBase += fUniformDispersion;
missileLaunchData[i].vecForward += fRandomDispersion * myOrientation.GetRight();
missileLaunchData[i].vecForward += (random (-0.1f, 0.1f) * fDispersion) * myOrientation.GetUp();
missileLaunchData[i].vecForward.SetNormalize();
}
ZRetailAssert(missileLaunchData[i].vecForward * missileLaunchData[i].vecForward >= 0.95f);
ZRetailAssert(missileLaunchData[i].vecForward * missileLaunchData[i].vecForward <= 1.05f);
missileLaunchData[i].vecPosition = vecLaunchPosition + (missileLaunchData[i].vecForward * (dataMissile.pmissiletype->GetInitialSpeed() * random (0.1f, 0.2f)));
ZRetailAssert(missileLaunchData[i].vecPosition * missileLaunchData[i].vecPosition >= 0.0f);
ZRetailAssert(missileLaunchData[i].vecPosition * missileLaunchData[i].vecPosition <= 4.0e10f);
missileLaunchData[i].vecVelocity = vecLaunchVelocity + (dataMissile.pmissiletype->GetInitialSpeed() * missileLaunchData[i].vecForward);
ZRetailAssert(missileLaunchData[i].vecVelocity * missileLaunchData[i].vecVelocity >= 0.0f);
ZRetailAssert(missileLaunchData[i].vecVelocity * missileLaunchData[i].vecVelocity <= 1.0e6);
}
if (!m_fm.IsConnected())
{
for (int i = 0; i < iNumMissiles; i++)
{
dataMissile.position = missileLaunchData[i].vecPosition;
dataMissile.forward = missileLaunchData[i].vecForward;
dataMissile.velocity = missileLaunchData[i].vecVelocity;
dataMissile.missileID = m_pCoreIGC->GenerateNewMissileID ();
dataMissile.bDud = false;
ImissileIGC* m = (ImissileIGC*)(m_pCoreIGC->CreateObject(timeFired, OT_missile, &dataMissile, sizeof(dataMissile)));
assert (m != NULL);
m->Release();
}
}
else
{
SetMessageType(c_mtGuaranteed);
BEGIN_PFM_CREATE(m_fm, pfmFM, CS, FIRE_MISSILE)
FM_VAR_PARM(missileLaunchData, sizeof(MissileLaunchData) * iNumMissiles)
END_PFM_CREATE
if (NULL != pTarget)
{
pfmFM->targetType = pTarget->GetObjectType();
pfmFM->targetID = pTarget->GetObjectID();
}
else
{
pfmFM->targetType = OT_invalid;
pfmFM->targetID = NA;
}
pfmFM->clusterID = pCluster->GetObjectID();
pfmFM->lock = flLock;
pfmFM->timeFired = ServerTimeFromClientTime(timeFired);
}
delete missileLaunchData;
pMagazine->SetAmount (iNumRemainingMissiles);
if (0 == iNumRemainingMissiles)
{
if (Reload(pShip, pMagazine, ET_Magazine))
{
PlayNotificationSound(salReloadingMissilesSound, GetShip());
PlaySoundEffect(startReloadSound, GetShip());
PostText(false, "Reloading missiles...");
}
else
{
PlayNotificationSound(salMissilesDepletedSound, GetShip());
PostText(false, "Missiles depleted.");
}
}
}
void BaseClient::FireExpendable(IshipIGC* pShip,
IdispenserIGC* pDispenser,
Time timeFired)
{
assert (pShip == m_ship);
this->PlayFFEffect(effectFire, pShip);
IclusterIGC* pCluster = pShip->GetCluster();
assert (pCluster);
IexpendableTypeIGC* pet = pDispenser->GetExpendableType();
ObjectType type = pet->GetObjectType();
switch (type)
{
case OT_chaffType:
this->PlaySoundEffect(deployChaffSound, pShip);
break;
case OT_mineType:
this->PlaySoundEffect(deployMineSound, pShip);
break;
case OT_probeType:
this->PlaySoundEffect(deployProbeSound, pShip);
break;
}
if (!m_fm.IsConnected())
{
const Vector& myPosition = pShip->GetPosition();
const Vector& myVelocity = pShip->GetVelocity();
if (type == OT_chaffType)
{
assert (type == OT_chaffType);
DataChaffIGC dataChaff;
dataChaff.time0 = timeFired;
dataChaff.p0 = myPosition;
dataChaff.v0 = myVelocity + pShip->GetOrientation().GetUp() * 25.0f;
dataChaff.pcluster = pCluster;
dataChaff.pchafftype = (IchaffTypeIGC*)pet;
IchaffIGC* c = (IchaffIGC*)(m_pCoreIGC->CreateObject(timeFired,
OT_chaff,
&dataChaff,
sizeof(dataChaff)));
assert (c != NULL);
c->Release();
}
else
{
float speed2 = myVelocity.LengthSquared();
float offset = (pet->GetRadius() + pShip->GetRadius()) + 5.0f;
Vector displace = (speed2 < 1.0f)
? (pShip->GetOrientation().GetBackward() * offset)
: (myVelocity * (-offset / float(sqrt(speed2))));
Vector launchPosition = myPosition + displace;
if (type == OT_mineType)
{
DataMineIGC dataMine;
dataMine.pminetype = (ImineTypeIGC*)pet;
dataMine.time0 = timeFired + 3.0f; dataMine.p0 = launchPosition;
dataMine.exportF = false;
dataMine.psideLauncher = pShip->GetSide(); dataMine.pshipLauncher = pShip;
dataMine.pcluster = pCluster;
dataMine.mineID = m_pCoreIGC->GenerateNewMineID();
ImineIGC* m = (ImineIGC*)(m_pCoreIGC->CreateObject(timeFired,
OT_mine,
&dataMine,
sizeof(dataMine)));
assert (m != NULL);
m->Release();
}
else if (type == OT_probeType)
{
DataProbeIGC dataProbe;
dataProbe.pprobetype = (IprobeTypeIGC*)pet;
dataProbe.time0 = timeFired;
dataProbe.p0 = launchPosition;
dataProbe.exportF = false;
dataProbe.pcluster = pCluster;
dataProbe.pside = pShip->GetSide();
dataProbe.pship = pShip;
dataProbe.pmodelTarget = pShip->GetCommandTarget(c_cmdCurrent);
dataProbe.probeID = m_pCoreIGC->GenerateNewProbeID();
IprobeIGC* p = (IprobeIGC*)(m_pCoreIGC->CreateObject(timeFired,
OT_probe,
&dataProbe,
sizeof(dataProbe)));
assert (p != NULL);
p->Release();
}
}
}
else
{
SetMessageType(c_mtGuaranteed);
BEGIN_PFM_CREATE(m_fm, pfmFE, C, FIRE_EXPENDABLE)
END_PFM_CREATE
pfmFE->et = pet->GetEquipmentType();
}
short amount = pDispenser->GetAmount() - 1;
pDispenser->SetAmount(amount);
if (0 == amount)
{
if (Reload(pShip, pDispenser, pet->GetEquipmentType()))
{
switch (pet->GetObjectType())
{
case OT_chaffType:
PlayNotificationSound(salReloadingChaffSound, GetShip());
PostText(false, "Reloading chaff...");
break;
default:
PlayNotificationSound(salReloadingDispenserSound, GetShip());
PostText(false, "Reloading dispenser...");
break;
}
PlaySoundEffect(startReloadSound, GetShip());
}
else
{
switch (pet->GetObjectType())
{
case OT_chaffType:
PlayNotificationSound(salChaffDepletedSound, GetShip());
PostText(false, "Chaff depleted.");
break;
default:
PlayNotificationSound(salDispenserEmptySound, GetShip());
PostText(false, "Dispenser empty.");
break;
}
}
}
}
bool BaseClient::Reload(IshipIGC* pship, IlauncherIGC* plauncher, EquipmentType type)
{
int nReloads = 0;
if (pship == m_ship)
{
const int c_MaxReloads = 8;
ReloadData reloads[c_MaxReloads];
const IhullTypeIGC* pht = pship->GetHullType();
switch (type)
{
case ET_Weapon:
case ET_Afterburner:
{
PackType ptDesired;
short ammo;
short maxAmmo;
if (type == ET_Weapon)
{
ptDesired = c_packAmmo;
ammo = pship->GetAmmo();
maxAmmo = pht->GetMaxAmmo();
}
else
{
ptDesired = c_packFuel;
ammo = short(pship->GetFuel());
maxAmmo = short(pht->GetMaxFuel());
}
while (ammo < maxAmmo)
{
IpackIGC* ppack = NULL;
short amount = 0x7fff;
{
for (Mount i = -1; (i >= -c_maxCargo); i--)
{
IpartIGC* ppart = pship->GetMountedPart(NA, i);
if (ppart && (ppart->GetObjectType() == OT_pack))
{
IpackIGC* p = (IpackIGC*)ppart;
if (p->GetPackType() == ptDesired)
{
ppack = p;
amount = p->GetAmount();
}
}
}
}
if (ppack)
{
reloads[nReloads].mount = ppack->GetMountID();
short transfer;
if (ammo + amount > maxAmmo)
{
transfer = maxAmmo - ammo;
ammo = maxAmmo;
ppack->SetAmount(amount - transfer);
}
else
{
transfer = NA;
ammo += amount;
ppack->Terminate();
}
reloads[nReloads++].amountTransfered = transfer;
}
else
break;
}
if (nReloads != 0)
{
if (type == ET_Weapon)
{
pship->SetAmmo(ammo);
Mount maxWeapons = pht->GetMaxWeapons();
for (Mount i = 0; (i < maxWeapons); i++)
{
IweaponIGC* pw = (IweaponIGC*)(pship->GetMountedPart(ET_Weapon, i));
if (pw && (pw->GetAmmoPerShot() != 0))
pw->SetMountedFraction(0.0f);
}
}
else
{
pship->SetFuel(float(ammo));
IpartIGC* p = pship->GetMountedPart(ET_Afterburner, 0);
if (p)
p->SetMountedFraction(0.0f);
}
}
}
break;
case ET_Magazine:
case ET_Dispenser:
case ET_ChaffLauncher:
{
IpartTypeIGC* pparttype;
short ammo;
short maxAmmo;
if (plauncher)
{
pparttype = plauncher->GetPartType();
ammo = plauncher->GetAmount();
maxAmmo = ((IlauncherTypeIGC*)pparttype)->GetAmount(pship);
}
else
{
pparttype = NULL;
ammo = 0;
maxAmmo = 0x7fff;
}
while (ammo < maxAmmo)
{
IlauncherIGC* plauncherReload = NULL;
IpartTypeIGC* pptReload;
short amount = 0x7fff;
{
for (Mount mount = -1; (mount >= -c_maxCargo); mount--)
{
IpartIGC* p = pship->GetMountedPart(NA, mount);
if (p && (p->GetEquipmentType() == type))
{
IpartTypeIGC* ppt = p->GetPartType();
if (pht->CanMount(ppt, 0))
{
short a = ((IlauncherIGC*)p)->GetAmount();
assert (a > 0);
if (pparttype == NULL)
{
reloads[nReloads].amountTransfered = NA;
reloads[nReloads++].mount = mount;
if (plauncher)
plauncher->Terminate();
p->SetMountID(0);
plauncher = (IlauncherIGC*)p;
pparttype = plauncher->GetPartType();
ammo = plauncher->GetAmount();
assert (ammo > 0);
maxAmmo = ((IlauncherTypeIGC*)pparttype)->GetAmount(pship);
assert (plauncherReload == NULL);
if (ammo == maxAmmo)
break; }
else if ((ppt == pparttype) )
{
plauncherReload = (IlauncherIGC*)p;
pptReload = ppt;
amount = a;
}
}
}
}
}
if (plauncherReload)
{
reloads[nReloads].mount = plauncherReload->GetMountID();
short transfer;
if (ammo + amount <= maxAmmo)
{
transfer = amount;
plauncherReload->Terminate();
}
else
{
transfer = maxAmmo - ammo;
plauncherReload->SetAmount(amount - transfer);
}
ammo += transfer;
plauncher->SetAmount(ammo);
plauncher->SetMountedFraction(0.0f);
plauncher->ResetTimeLoaded();
reloads[nReloads++].amountTransfered = transfer;
}
else if (pparttype && (ammo == 0))
{
assert (plauncher);
pparttype = NULL;
maxAmmo = 0x7fff;
}
else
break;
}
}
break;
}
if (m_fm.IsConnected())
{
if (nReloads > 0)
{
int size = sizeof(ReloadData) * nReloads;
SetMessageType(c_mtGuaranteed);
BEGIN_PFM_CREATE(m_fm, pfmReload, CS, RELOAD)
FM_VAR_PARM(NULL, size)
END_PFM_CREATE
memcpy(FM_VAR_REF(pfmReload, rgReloads), reloads, size);
}
else if (plauncher && (plauncher->GetAmount() == 0))
{
SetMessageType(c_mtGuaranteed);
BEGIN_PFM_CREATE(m_fm, pfmDrop, CS, DROP_PART)
END_PFM_CREATE
pfmDrop->et = plauncher->GetEquipmentType();
pfmDrop->mount = plauncher->GetMountID();
plauncher->Terminate();
}
}
}
return nReloads > 0;
}
void BaseClient::OnQuitSide()
{
m_bInGame = false;
m_bWaitingForGameRestart = false;
if (IsLockedDown())
EndLockDown(lockdownDonating | lockdownLoadout | lockdownTeleporting);
PlayerLink* l = m_listPlayers.first();
while (l != NULL)
{
PlayerInfo& playerCurrent = l->data();
playerCurrent.ResetShipStatus();
l = l->next();
}
assert (m_ship->GetStation() == NULL);
assert (m_ship->GetCluster() == NULL);
{
ShipLinkIGC* plinkShip = m_pCoreIGC->GetShips()->first();
while (plinkShip)
{
plinkShip->data()->SetCluster(NULL);
plinkShip = plinkShip->next();
}
}
SetViewCluster(NULL);
m_pCoreIGC->ResetMission();
m_listBallots.SetEmpty();
};
void BaseClient::OnJoinSide()
{
ResetShip();
m_strBriefingText.SetEmpty();
m_bGenerateCivBriefing = false;
if (m_pPlayerInfo->SideID() != SIDE_TEAMLOBBY)
SetMoney(m_pPlayerInfo->GetMoney());
if (m_pMissionInfo->InProgress())
{
m_pCoreIGC->SetMissionStage(STAGE_STARTED);
}
m_pClientEventSource->OnChatMessageChange();
m_plinkSelectedChat = NULL;
if (m_pPlayerInfo->SideID() == SIDE_TEAMLOBBY)
m_pClientEventSource->OnAddPlayer(m_pMissionInfo, m_pPlayerInfo->SideID(), m_pPlayerInfo);
};
void BaseClient::OnQuitMission(QuitSideReason reason, const char* szMessageParam)
{
Disconnect();
m_chatList.purge(true);
m_pClientEventSource->OnClearChat();
m_ship->AddRef();
{
ShipLinkIGC* plinkShip = m_pCoreIGC->GetShips()->first();
while (plinkShip)
{
ShipLinkIGC* lNext = plinkShip->next();
IshipIGC* s = plinkShip->data();
plinkShip->data()->Terminate();
plinkShip = lNext;
}
}
m_ship->Release();
CreateDummyShip();
{
const SideListIGC * pSides = m_pCoreIGC->GetSides();
SideLinkIGC * pSidelink = NULL;
while (pSidelink = pSides->first())
pSidelink->data()->Terminate();
}
{
m_listPlayers.purge(true);
m_pPlayerInfo = NULL;
}
delete m_pMissionInfo;
m_pMissionInfo = NULL;
};
void BaseClient::OnEnterGame()
{
m_pCoreIGC->EnterGame();
m_bInGame = true;
m_pClientEventSource->OnEnterMission();
};
void BaseClient::CreateDummyShip()
{
DataShipIGC ds;
ds.hullID = NA;
ds.shipID = NA;
ds.nParts = 0;
ds.sideID = NA;
ds.name[0] = '\0';
ds.pilotType = c_ptCheatPlayer;
ds.abmOrders = 0;
ds.nDeaths = 0;
ds.nEjections = 0;
ds.nKills = 0;
ds.baseObjectID = NA;
ModifyShipData(&ds);
m_ship = (IshipIGC*)(m_pCoreIGC->CreateObject(m_lastSend, OT_ship, &ds, sizeof(ds)));
assert (m_ship);
m_ship->Release();
};
void BaseClient::DestroyDummyShip()
{
}
void BaseClient::RemovePlayerFromSide(PlayerInfo* pPlayerInfo, QuitSideReason reason, const char* szMessageParam)
{
if (!pPlayerInfo)
{
assert(false);
return;
}
ZAssert(pPlayerInfo->SideID() != SIDE_TEAMLOBBY && pPlayerInfo->SideID() != NA);
SideID sideOld = pPlayerInfo->SideID();
ZAssert(pPlayerInfo->SideID() != NA);
pPlayerInfo->SetTeamLeader(false);
pPlayerInfo->SetMissionOwner(false);
pPlayerInfo->Reset(false);
if (STAGE_STARTED != m_pMissionInfo->GetStage())
pPlayerInfo->GetShip()->SetExperience(1.0f);
m_pClientEventSource->OnMoneyChange(pPlayerInfo);
m_pMissionInfo->RemovePlayer(pPlayerInfo);
m_pClientEventSource->OnDelPlayer(m_pMissionInfo, pPlayerInfo->SideID(), pPlayerInfo, reason);
IshipIGC* pship = m_pCoreIGC->GetShip(pPlayerInfo->ShipID());
pship->SetSide(NULL);
if (pPlayerInfo == m_pPlayerInfo)
{
OnQuitSide();
}
else
{
if (pPlayerInfo->IsHuman() && (m_pMissionInfo->GetStage() == STAGE_STARTED) && (m_fm.IsConnected ()))
{
ZString msg;
if (m_pPlayerInfo->SideID() == sideOld)
{
switch (reason)
{
case QSR_LeaderBooted:
msg = pPlayerInfo->CharacterName() + ZString(" was booted from the team by the team leader.");
ReceiveChat(NULL, CHAT_TEAM, NA, salQuitSound, msg, c_cidNone, NA, NA);
break;
case QSR_OwnerBooted:
msg = pPlayerInfo->CharacterName() + ZString(" was booted from the game by the mission owner.");
ReceiveChat(NULL, CHAT_TEAM, NA, salQuitSound, msg, c_cidNone, NA, NA);
break;
case QSR_AdminBooted:
msg = pPlayerInfo->CharacterName() + ZString(" was booted from the team by an admin.");
ReceiveChat(NULL, CHAT_TEAM, NA, salQuitSound, msg, c_cidNone, NA, NA);
break;
case QSR_ServerShutdown:
break;
case QSR_SquadChange:
msg = pPlayerInfo->CharacterName() + ZString(" was booted because of a squad change.");
ReceiveChat(NULL, CHAT_TEAM, NA, salQuitSound, msg, c_cidNone, NA, NA);
break;
case QSR_SideDestroyed:
break;
case QSR_RankLimits:
msg = pPlayerInfo->CharacterName() + ZString(" was booted because he/she did not meet the new rank limits.");
ReceiveChat(NULL, CHAT_TEAM, NA, salQuitSound, msg, c_cidNone, NA, NA);
break;
case QSR_TeamSizeLimits:
msg = pPlayerInfo->CharacterName() + ZString(" was booted to reduce the team size within it's new limits.");
ReceiveChat(NULL, CHAT_TEAM, NA, salQuitSound, msg, c_cidNone, NA, NA);
break;
case QSR_Quit:
msg = pPlayerInfo->CharacterName() + ZString(" has quit.");
ReceiveChat(NULL, CHAT_TEAM, NA, salQuitSound, msg, c_cidNone, NA, NA);
break;
case QSR_SwitchingSides:
msg = pPlayerInfo->CharacterName() + ZString(" is switching sides.");
ReceiveChat(NULL, CHAT_TEAM, NA, salChangeSidesSound, msg, c_cidNone, NA, NA);
break;
case QSR_DuplicateLocalLogon:
case QSR_DuplicateCDKey:
break;
case QSR_RandomizeSides:
break;
case QSR_DuplicateRemoteLogon:
msg = pPlayerInfo->CharacterName() + ZString(" has been booted due to a duplicate logon.");
ReceiveChat(NULL, CHAT_TEAM, NA, salQuitSound, msg, c_cidNone, NA, NA);
break;
default:
ZAssert(false);
case QSR_LinkDead:
msg = pPlayerInfo->CharacterName() + ZString(" is MIA.");
ReceiveChat(NULL, CHAT_TEAM, NA, salMIASound, msg, c_cidNone, NA, NA);
break;
};
}
else
{
msg = pPlayerInfo->CharacterName() + ZString(" has left ")
+ GetCore()->GetSide(sideOld)->GetName() + ZString(".");
ReceiveChat(NULL, CHAT_TEAM, NA, salEnemyLeavesSound, msg, c_cidNone, NA, NA);
}
}
}
pPlayerInfo->SetTeamLeader(false);
pPlayerInfo->SetMissionOwner(false);
pPlayerInfo->SetSideID(SIDE_TEAMLOBBY);
pPlayerInfo->SetMoney(0);
IsideIGC* pside = m_pCoreIGC->GetSide(SIDE_TEAMLOBBY);
pship->SetSide(pside);
if (pPlayerInfo == m_pPlayerInfo)
{
ResetShip();
m_pClientEventSource->OnChatMessageChange();
m_plinkSelectedChat = NULL;
}
m_pMissionInfo->AddPlayer(pPlayerInfo);
if (m_pPlayerInfo->SideID() == SIDE_TEAMLOBBY)
m_pClientEventSource->OnAddPlayer(m_pMissionInfo, pPlayerInfo->SideID(), pPlayerInfo);
}
void BaseClient::RemovePlayerFromMission(PlayerInfo* pPlayerInfo, QuitSideReason reason, const char* szMessageParam)
{
if (!pPlayerInfo)
{
assert(false);
return;
}
ZAssert(pPlayerInfo->SideID() == SIDE_TEAMLOBBY);
assert(pPlayerInfo);
m_pMissionInfo->RemovePlayer(pPlayerInfo);
if (pPlayerInfo == m_pPlayerInfo)
{
m_pClientEventSource->OnDelPlayer(m_pMissionInfo, pPlayerInfo->SideID(), pPlayerInfo, reason);
}
pPlayerInfo->SetSideID(NA);
IshipIGC* pship = pPlayerInfo->GetShip();
pship->SetSide(NULL);
if (pPlayerInfo != m_pPlayerInfo)
{
pship->Terminate();
PlayerLink* l = FindPlayerLink(pPlayerInfo->ShipID());
delete l;
}
else
{
OnQuitMission(reason, szMessageParam);
}
}
void BaseClient::AddPlayerToMission(PlayerInfo* pPlayerInfo)
{
assert(pPlayerInfo);
pPlayerInfo->SetSideID(SIDE_TEAMLOBBY);
IshipIGC* pship = pPlayerInfo->GetShip();
IsideIGC* pside = m_pCoreIGC->GetSide(SIDE_TEAMLOBBY);
pship->SetSide(pside);
if (pPlayerInfo == m_pPlayerInfo)
{
m_pCoreIGC->SetMissionParams(&(m_pMissionInfo->GetMissionParams()));
m_pCoreIGC->UpdateSides(Time::Now(), &(m_pMissionInfo->GetMissionParams()), m_pMissionInfo->GetMissionDef().rgszName);
OnJoinSide();
}
m_pMissionInfo->AddPlayer(pPlayerInfo);
}
void BaseClient::AddPlayerToSide(PlayerInfo* pPlayerInfo, SideID sideID)
{
assert(pPlayerInfo);
assert(pPlayerInfo->SideID() == SIDE_TEAMLOBBY);
SideID sideOld = pPlayerInfo->SideID();
m_pMissionInfo->RemovePlayer(pPlayerInfo);
assert(pPlayerInfo->GetMoney() == 0);
if (pPlayerInfo == m_pPlayerInfo)
{
OnQuitSide();
}
pPlayerInfo->SetSideID(sideID);
IshipIGC* pship = pPlayerInfo->GetShip();
IsideIGC* pside = m_pCoreIGC->GetSide(sideID);
pship->SetSide(pside);
if (pPlayerInfo == m_pPlayerInfo)
{
OnJoinSide();
}
m_pMissionInfo->AddPlayer(pPlayerInfo);
if (pPlayerInfo->IsTeamLeader())
m_pMissionInfo->SetSideLeader(pPlayerInfo);
if (m_pMissionInfo->FindRequest(pPlayerInfo->SideID(), pPlayerInfo->ShipID()))
m_pMissionInfo->RemoveRequest(pPlayerInfo->SideID(), pPlayerInfo->ShipID());
pPlayerInfo->ResetShipStatus();
m_pClientEventSource->OnAddPlayer(m_pMissionInfo, pPlayerInfo->SideID(), pPlayerInfo);
if (pPlayerInfo->IsHuman() && m_pMissionInfo->GetStage() == STAGE_STARTED && m_fm.IsConnected())
{
if ((m_pPlayerInfo != pPlayerInfo) && (m_pPlayerInfo->SideID() == pPlayerInfo->SideID()))
{
ZString msg = pPlayerInfo->CharacterName() + ZString(" has joined your team.");
ReceiveChat(NULL, CHAT_TEAM, NA, salRecruitsArrivedSound, msg, c_cidNone, NA, NA);
}
else if (m_pPlayerInfo && GetSide() && GetSideID() != SIDE_TEAMLOBBY)
{
ZString msg = pPlayerInfo->CharacterName() + ZString(" has joined ")
+ pside->GetName() + ZString(".");
ReceiveChat(NULL, CHAT_TEAM, NA, salEnemyJoinersSound, msg, c_cidNone, NA, NA);
}
}
}
static void DoDecrypt(int size, char* pdata)
{
DWORD encrypt = 0;
for (int i = 0; (i < size); i += 4)
{
DWORD* p = (DWORD*)(pdata + i);
encrypt = *p = *p ^ encrypt;
}
}
bool BaseClient::ResetStaticData(const char * szIGCStaticFile, ImissionIGC** ppStaticIGC, Time tNow, bool bEncrypt)
{
assert(ppStaticIGC);
if (&m_pCoreIGC == ppStaticIGC)
{
FlushGameState();
*ppStaticIGC = CreateMission();
Initialize(tNow);
}
else
{
assert(*ppStaticIGC);
}
lstrcpy(m_szIGCStaticFile, szIGCStaticFile);
int iStaticCoreVersion = LoadIGCStaticCore (szIGCStaticFile, *ppStaticIGC, true); if (iStaticCoreVersion != m_pMissionInfo->GetIGCStaticVer())
{
return false;
}
LoadIGCStaticCore (szIGCStaticFile, *ppStaticIGC, false, bEncrypt ? DoDecrypt : NULL); return true;
}
void BaseClient::StartLockDown(const ZString& strReason, LockdownCriteria criteria)
{
ZAssert((m_lockdownCriteria & criteria) == 0);
m_lockdownCriteria |= criteria;
m_strLockDownReason = strReason;
}
void BaseClient::EndLockDown(LockdownCriteria criteria)
{
ZAssert(m_lockdownCriteria != 0);
m_lockdownCriteria &= ~criteria;
}
void BaseClient::BoardShip(IshipIGC* pship)
{
SetMessageType(BaseClient::c_mtGuaranteed);
BEGIN_PFM_CREATE(m_fm, pfmBoardShip, C, BOARD_SHIP)
END_PFM_CREATE
pfmBoardShip->sidParent = pship ? pship->GetObjectID() : NA;
if (pship)
{
assert(GetShip()->GetParentShip() == NULL);
StartLockDown("Boarding " + ZString(pship->GetName()) + "'s ship....", lockdownTeleporting);
}
else
{
IshipIGC* pshipParent = GetShip()->GetParentShip();
assert(pshipParent);
StartLockDown("Disembarking from " + ZString(pshipParent->GetName()) + "'s ship....", lockdownTeleporting);
}
}
DWORD CfgInfo::GetCfgProfileString(
const char *c_szCfgApp,
const char *c_szKeyName,
const char *c_szDefaultValue,
char *szStr,
DWORD dwSize)
{
return GetPrivateProfileString(
c_szCfgApp,
c_szKeyName,
c_szDefaultValue,
szStr,
dwSize,
m_szConfigFile);
}
void CfgInfo::SetCfgFile(const char * szConfig)
{
m_szConfigFile = ZString(szConfig);
}
void CfgInfo::Load(const char * szConfig)
{
m_szConfigFile = ZString(szConfig); const char * c_szCfgApp = "Allegiance";
char szStr[128];
GetPrivateProfileString(c_szCfgApp, "ZAuth", "auth.zone.com",
szStr, sizeof(szStr), szConfig);
strZAuth = szStr;
GetPrivateProfileString(c_szCfgApp, "ClubLobby", "",
szStr, sizeof(szStr), szConfig);
strClubLobby = szStr;
GetPrivateProfileString(c_szCfgApp, "PublicLobby", "",
szStr, sizeof(szStr), szConfig);
strPublicLobby = szStr;
GetPrivateProfileString(c_szCfgApp, "Club", "",
szStr, sizeof(szStr), szConfig);
strClub = szStr;
GetPrivateProfileString(c_szCfgApp, "ClubMessageURL", "http://fdl.msn.com/zone/allegiance/messageoftheday.mdl", szStr, sizeof(szStr), szConfig);
strClubMessageURL = szStr;
GetPrivateProfileString(c_szCfgApp, "PublicMessageURL", "http://fdl.msn.com/zone/allegiance/messageoftheday.mdl", szStr, sizeof(szStr), szConfig);
strPublicMessageURL = szStr;
GetPrivateProfileString(c_szCfgApp, "ZoneEventsURL", "", szStr, sizeof(szStr), szConfig);
strZoneEventsURL = szStr;
GetPrivateProfileString(c_szCfgApp, "ZoneEventDetailsURL", "http://fdl.msn.com/zone/allegiance/zoneevents.mdl",
szStr, sizeof(szStr), szConfig);
strZoneEventDetailsURL = szStr;
GetPrivateProfileString(c_szCfgApp, "TrainingURL", "http://www.zone.com/allegiance/downloads.asp",
szStr, sizeof(szStr), szConfig);
strTrainingURL = szStr;
GetPrivateProfileString(c_szCfgApp, "PassportUpdateURL", "http://www.zone.com/allegiance/passportupdate.html",
szStr, sizeof(szStr), szConfig);
strPassportUpdateURL = szStr;
GetPrivateProfileString(c_szCfgApp, "ZoneAuthGUID", "{00000000-0000-0000-C000-000000000046}",
szStr, sizeof(szStr), szConfig);
int cbStr = strlen(szStr) + 1;
LPOLESTR wszStr = (LPOLESTR)_alloca(sizeof(OLECHAR) * cbStr);
MultiByteToWideChar(CP_ACP, 0, PCC(szStr), cbStr, wszStr, cbStr);
if (cbStr == 1 || !ZSucceeded(IIDFromString(wszStr, &guidZoneAuth)))
{
guidZoneAuth = GUID_NULL;
}
GetPrivateProfileString(c_szCfgApp, "FilelistCRC", "0",
szStr, sizeof(szStr), szConfig);
_strupr(szStr);
crcFileList = UTL::hextoi(szStr);
if (crcFileList == 0)
debugf("FilelistCRC is missing or invalid from %s.\n", szConfig);
GetPrivateProfileString(c_szCfgApp, "FilelistSize", "0",
szStr, sizeof(szStr), szConfig);
nFilelistSize = atoi(szStr);
if (nFilelistSize == 0)
debugf("FilelistSize is missing or invalid from %s.\n", szConfig);
GetPrivateProfileString(c_szCfgApp, "FilelistSite", "",
szStr, sizeof(szStr), szConfig);
strFilelistSite = szStr;
GetPrivateProfileString(c_szCfgApp, "FilelistDirectory", "",
szStr, sizeof(szStr), szConfig);
strFilelistDirectory = szStr;
GetPrivateProfileString(c_szCfgApp, "ClubMessageCRC", "0",
szStr, sizeof(szStr), szConfig);
_strupr(szStr);
crcClubMessageFile = UTL::hextoi(szStr);
GetPrivateProfileString(c_szCfgApp, "PublicMessageCRC", "0",
szStr, sizeof(szStr), szConfig);
_strupr(szStr);
crcPublicMessageFile = UTL::hextoi(szStr);
GetPrivateProfileString(c_szCfgApp, "UsePassport", "0",
szStr, sizeof(szStr), szConfig);
bUsePassport = atoi(szStr) != 0;
GetPrivateProfileString(c_szCfgApp, "LobbyClientPort", "2302",
szStr, sizeof(szStr), szConfig);
dwLobbyPort = atoi(szStr);
}
void _debugf(const char* format, ...)
{
const size_t size = 512;
char bfr[size];
va_list vl;
va_start(vl, format);
_vsnprintf(bfr, size, format, vl);
va_end(vl);
debugf(bfr);
}