#include "pch.h"
#include <limits.h>
HRESULT BaseClient::HandleMsg(FEDMESSAGE* pfm,
Time lastUpdate, Time now)
{
HRESULT hr = S_OK; #ifdef DUMPMSGS
debugf("Received message type %d of length %d\n", pfm->fmid, pfm->cbmsg);
#endif if (!m_ship || !IsInGame() || GetCluster() == NULL || pfm->fmid == FM_CS_PING
|| pfm->fmid == FM_S_HEAVY_SHIPS_UPDATE || pfm->fmid == FM_S_LIGHT_SHIPS_UPDATE)
{
m_timeLastServerMessage = now;
}
switch(pfm->fmid)
{
case FM_S_LOGONACK:
{
CASTPFM(pfmLogonAck, S, LOGONACK, pfm);
if (pfmLogonAck->fValidated)
{
debugf("I am ship %s, shipid=%d\n", FM_VAR_REF(pfmLogonAck, CharName_OR_FailureReason), pfmLogonAck->shipID);
lstrcpy(m_szCharName, FM_VAR_REF(pfmLogonAck, CharName_OR_FailureReason)); m_fLoggedOn = true;
SetCookie(pfmLogonAck->cookie);
{
m_cUnansweredPings = 0;
DWORD newLag = 100; DWORD newOffset = pfmLogonAck->timeServer.clock() - now.clock() + newLag;
m_serverOffsetValidF = true;
m_serverLag = newLag;
m_serverOffset = newOffset;
m_timeLastPing = now;
m_timeLastPingServer = pfmLogonAck->timeServer;
}
}
char * szFailureReason = pfmLogonAck->fValidated ? NULL : FM_VAR_REF(pfmLogonAck, CharName_OR_FailureReason);
OnLogonAck(pfmLogonAck->fValidated, pfmLogonAck->fRetry, szFailureReason);
}
break;
case FM_S_URLROOT:
{
CASTPFM(pfmUrlRoot, S, URLROOT, pfm);
UTL::SetUrlRoot(FM_VAR_REF(pfmUrlRoot, UrlRoot));
}
break;
case FM_S_EXPORT:
{
if (IsWaitingForGameRestart())
break;
CASTPFM(pfmExport, S, EXPORT, pfm);
IObject* u = m_pCoreIGC->CreateObject(lastUpdate,
pfmExport->objecttype,
FM_VAR_REF(pfmExport, exportData),
pfmExport->cbexportData);
if (u)
u->Release();
else
{
}
Sleep(0);
}
break;
case FM_S_POSTER:
{
assert(false);
}
break;
case FM_S_RELAUNCH_SHIP:
{
if (!IsInGame())
break;
CASTPFM(pfmRelaunch, S, RELAUNCH_SHIP, pfm);
IshipIGC* pShip = m_pCoreIGC->GetShip(pfmRelaunch->shipID);
if (pShip)
{
IshipIGC* pshipParent = m_pCoreIGC->GetShip(pfmRelaunch->carrierID);
assert (pshipParent);
pShip->SetParentShip(NULL);
pShip->ProcessShipLoadout(pfmRelaunch->cbloadout, (const ShipLoadout*)(FM_VAR_REF(pfmRelaunch, loadout)), true);
pShip->SetAmmo(SHRT_MAX);
pShip->SetFuel(FLT_MAX);
pShip->SetEnergy(pShip->GetHullType()->GetMaxEnergy());
pShip->SetPosition(pfmRelaunch->position);
pShip->SetVelocity(pfmRelaunch->velocity);
{
Orientation o;
pfmRelaunch->orientation.Export(&o);
pShip->SetOrientation(o);
}
if (pShip == m_ship)
{
SetCookie(pfmRelaunch->cookie);
PlayNotificationSound(salRepairedAtCarrierSound, GetShip());
OverrideCamera(pshipParent);
}
}
}
break;
case FM_S_EJECT:
{
if (!IsInGame())
break;
IclusterIGC* pcluster = GetCluster();
if (pcluster)
{
CASTPFM(pfmEject, S, EJECT, pfm);
IshipIGC* pShip = m_pCoreIGC->GetShip(pfmEject->shipID);
if (pShip)
{
if (pShip->GetParentShip())
{
pShip->SetParentShip(NULL);
m_pClientEventSource->OnBoardShip(pShip, NULL);
}
else
{
assert (pShip->GetChildShips()->n() == 0);
{
const PartListIGC* plist = pShip->GetParts();
PartLinkIGC* plink;
while (plink = plist->first()) plink->data()->Terminate();
}
pShip->SetAmmo(0);
pShip->SetFuel(0.0f);
}
{
{
for (MissileLinkIGC* pml = pcluster->GetMissiles()->first();
(pml != NULL);
pml = pml->next())
{
ImissileIGC* pmissile = pml->data();
if (pmissile->GetTarget() == pShip)
pmissile->SetTarget(NULL);
}
}
pShip->SetBaseHullType(pShip->GetSide()->GetCivilization()->GetLifepod());
pShip->SetCurrentTurnRate(c_axisRoll, pi * 2.0f);
pShip->SetPosition(pfmEject->position);
pShip->SetVelocity(pfmEject->velocity);
{
Orientation o(pfmEject->forward);
pShip->SetOrientation(o);
}
}
if (pShip == m_ship)
{
SetCookie(pfmEject->cookie);
ImodelIGC* pNearestBase = FindTarget (pShip, c_ttStation | c_ttFriendly | c_ttAnyCluster | c_ttProbe, pShip->GetCommandTarget (c_cmdCurrent), pcluster, &pfmEject->position, NULL, c_sabmRescue | c_sabmRescueAny | c_sabmLand);
pShip->SetCommand (c_cmdCurrent, pNearestBase, c_cidGoto);
SetAutoPilot (true);
bInitTrekJoyStick = true;
PlayNotificationSound(salAutopilotEngageSound, GetShip());
}
}
}
}
break;
case FM_S_DESTROY_TREASURE:
{
if (!IsInGame())
break;
CASTPFM(pfmTreasure, S, DESTROY_TREASURE, pfm);
{
IclusterIGC* c = m_pCoreIGC->GetCluster(pfmTreasure->sectorID);
assert (c);
ItreasureIGC* treasure = c->GetTreasure(pfmTreasure->treasureID);
if (treasure)
treasure->Terminate();
}
}
break;
case FM_S_ACQUIRE_TREASURE:
{
if (!IsInGame())
break;
CASTPFM(pfmTreasure, S, ACQUIRE_TREASURE, pfm);
switch (pfmTreasure->treasureCode)
{
case c_tcPart:
{
SetMessageType(BaseClient::c_mtGuaranteed);
BEGIN_PFM_CREATE(m_fm, pfmAck, C, TREASURE_ACK)
END_PFM_CREATE
pfmAck->mountID = m_ship->HitTreasure(c_tcPart, pfmTreasure->treasureID, pfmTreasure->amount);
}
break;
case c_tcPowerup:
PlaySoundEffect(pickUpPowerupSound, GetShip());
break;
case c_tcDevelopment:
PlaySoundEffect(pickUpDevelopmentSound, GetShip());
break;
case c_tcCash:
{
PlaySoundEffect(pickUpCashSound, GetShip());
IshipIGC* pshipDonate = m_ship->GetAutoDonate();
if (pshipDonate)
PostText(false, "You donated your reward of $%d to %s.", pfmTreasure->amount, pshipDonate->GetName());
else
PostText(false, "You received a reward of $%d.", pfmTreasure->amount);
}
break;
case c_tcFlag:
PlaySoundEffect(pickUpDevelopmentSound, GetShip()); break;
}
}
break;
case FM_S_PLAYER_RESCUED:
{
CASTPFM(pfmPlayerRescued, S, PLAYER_RESCUED, pfm);
ShipID sid = GetShipID();
if (pfmPlayerRescued->shipIDRescuer == sid)
{
PlayerInfo* pplayerRescuee = FindPlayer(pfmPlayerRescued->shipIDRescuee);
if (!pplayerRescuee)
{
assert(false);
break;
}
PostText(false, "You rescued %s.", pplayerRescuee->CharacterName());
PlaySoundEffect(rescuePlayerSound, GetShip());
}
else if (pfmPlayerRescued->shipIDRescuee == sid)
{
PlayerInfo* pplayerRescuer = FindPlayer(pfmPlayerRescued->shipIDRescuer);
if (!pplayerRescuer)
{
assert(false);
break;
}
PostText(true, "%s rescued you.", pplayerRescuer->CharacterName());
PlaySoundEffect(jumpSound);
}
}
break;
case FM_S_BALLOT:
{
CASTPFM(pfmBallot, S, BALLOT, pfm);
if (!(pfmBallot->otInitiator == OT_ship && pfmBallot->oidInitiator == GetShipID())
&& !(pfmBallot->otInitiator == OT_side && pfmBallot->oidInitiator == GetSideID()))
{
if (pfmBallot->bHideToLeader && MyPlayerInfo()->IsTeamLeader())
{
SetMessageType(c_mtGuaranteed);
BEGIN_PFM_CREATE(m_fm, pfmVote, C, VOTE)
END_PFM_CREATE
pfmVote->ballotID = pfmBallot->ballotID;
pfmVote->bAgree = false;
}
else
{
m_listBallots.PushEnd(BallotInfo(
(char*)(FM_VAR_REF(pfmBallot, BallotText)) + ZString("Press [Y] to vote yes, [N] to vote no."),
pfmBallot->ballotID,
ClientTimeFromServerTime(pfmBallot->timeExpiration)
));
}
}
}
break;
case FM_S_CANCEL_BALLOT:
{
CASTPFM(pfmCancelBallot, S, CANCEL_BALLOT, pfm);
BallotList::Iterator iterBallot(m_listBallots);
while (!iterBallot.End())
{
if (iterBallot.Value().GetBallotID() == pfmCancelBallot->ballotID)
iterBallot.Remove();
else
iterBallot.Next();
}
}
break;
case FM_CS_PING:
{
CASTPFM(pfmPing, CS, PING, pfm);
assert (now >= pfmPing->timeClient);
DWORD newLag = (now.clock() - pfmPing->timeClient.clock()) >> 1;
if (newLag < 1000)
{
m_cUnansweredPings = 0;
DWORD newOffset = pfmPing->timeServer.clock() - now.clock() + newLag;
if (m_serverOffsetValidF)
{
float currentSync = float(now.clock() - m_timeLastPing.clock()) /
float(pfmPing->timeServer.clock() - m_timeLastPingServer.clock());
m_sync = m_sync * 3/4 + currentSync/4;
if (newLag > m_serverLag)
{
m_serverOffset += ((int)(newOffset - m_serverOffset)) >> 3;
m_serverLag = (m_serverLag * 7 + newLag) >> 3;
}
else
{
m_serverOffset += ((int)(newOffset - m_serverOffset)) >> 1;
m_serverLag = (m_serverLag + newLag) >> 1;
}
}
else
{
m_serverOffsetValidF = true;
m_serverLag = newLag;
m_serverOffset = newOffset;
}
m_timeLastPing = now;
m_timeLastPingServer = pfmPing->timeServer;
}
}
break;
case FM_S_VIEW_CLUSTER:
{
if (!IsInGame())
break;
CASTPFM(pfmViewCluster, S, VIEW_CLUSTER, pfm);
IclusterIGC* pcluster = m_pCoreIGC->GetCluster(pfmViewCluster->clusterID);
assert (pcluster);
SetViewCluster(pcluster, pfmViewCluster->bUsePosition ? &(pfmViewCluster->position) : NULL);
}
break;
case FM_S_SHIP_DELETE:
{
CASTPFM(pfmShipDelete, S, SHIP_DELETE, pfm);
if (pfmShipDelete->shipID != GetShipID())
{
IshipIGC* ship = m_pCoreIGC->GetShip(pfmShipDelete->shipID);
if (ship)
{
switch (pfmShipDelete->sdr)
{
case SDR_TERMINATE:
case SDR_KILLED:
{
ship->SetCluster(NULL);
}
break;
default:
{
if (m_ship->GetParentShip() != ship)
ship->SetCluster(NULL);
}
}
}
if (pfmShipDelete->sdr == SDR_LOGGEDOFF)
{
PlayerLink* l = FindPlayerLink(pfmShipDelete->shipID);
if (l)
{
PlayerInfo* pPlayerInfo = &(l->data());
assert (pPlayerInfo);
debugf("Logging off ship for %s, ID=%d\n",
pPlayerInfo->CharacterName(), pPlayerInfo->ShipID());
RemovePlayerFromSide(pPlayerInfo, QSR_Quit);
RemovePlayerFromMission(pPlayerInfo, QSR_Quit);
}
}
}
}
break;
case FM_S_STATION_DESTROYED:
{
if (!IsInGame())
break;
CASTPFM(pfmStation, S, STATION_DESTROYED, pfm);
IstationIGC * station = m_pCoreIGC->GetStation(
pfmStation->stationID);
if (station)
{
station->GetCluster()->GetClusterSite()->AddExplosion(station,
station->GetStationType()->HasCapability(c_sabmFlag)
? c_etLargeStation
: c_etSmallStation);
if (pfmStation->launcher != NA)
{
IshipIGC * pship = GetCore()->GetShip(pfmStation->launcher);
PostText(true, START_COLOR_STRING "%s" END_COLOR_STRING " destroyed " START_COLOR_STRING "%s's %s" END_COLOR_STRING " in %s.",
(PCC) ConvertColorToString (pship ? pship->GetSide ()->GetColor () : Color::White ()),
(pship ? pship->GetName() : "Unknown ship"),
(PCC) ConvertColorToString (station->GetSide ()->GetColor ()),
station->GetSide()->GetName(),
station->GetName(),
station->GetCluster()->GetName()
);
}
else
PostText(true, START_COLOR_STRING "%s's %s" END_COLOR_STRING " in %s was destroyed.",
(PCC) ConvertColorToString (station->GetSide()->GetColor ()),
station->GetSide()->GetName(),
station->GetName(),
station->GetCluster()->GetName());
if (station->GetSide() == GetSide())
PlaySoundEffect(station->GetStationType()->GetDestroyedSound());
else
PlaySoundEffect(station->GetStationType()->GetEnemyDestroyedSound());
station->Terminate();
}
}
break;
case FM_S_STATIONS_UPDATE:
{
if (!IsInGame())
break;
CASTPFM(pfmStation, S, STATIONS_UPDATE, pfm);
IclusterIGC* pcluster = GetChatCluster();
if (pcluster)
{
for (int i = int(pfmStation->cbrgStationStates /
sizeof(StationState)) - 1; (i >= 0); i--)
{
StationState* pss = ((StationState*)(FM_VAR_REF(pfmStation, rgStationStates))) + i;
IstationIGC * station = pcluster->GetStation(pss->stationID);
if (station)
{
station->SetFraction(pss->bpHullFraction);
station->SetShieldFraction(pss->bpShieldFraction);
}
}
}
}
break;
case FM_S_PROBES_UPDATE:
{
if (!IsInGame())
break;
CASTPFM(pfmProbe, S, PROBES_UPDATE, pfm);
IclusterIGC* pcluster = GetCluster();
if (pcluster)
{
for (int i = int(pfmProbe->cbrgProbeStates /
sizeof(ProbeState)) - 1; (i >= 0); i--)
{
ProbeState* pps = ((ProbeState*)(FM_VAR_REF(pfmProbe, rgProbeStates))) + i;
IprobeIGC * probe = pcluster->GetProbe(pps->probeID);
if (probe)
probe->SetFraction(pps->bpFraction);
}
}
}
break;
case FM_S_ASTEROIDS_UPDATE:
{
if (!IsInGame())
break;
CASTPFM(pfmAsteroids, S, ASTEROIDS_UPDATE, pfm);
IclusterIGC* pcluster = GetCluster();
if (pcluster)
{
for (int i = int(pfmAsteroids->cbrgAsteroidStates /
sizeof(AsteroidState)) - 1; (i >= 0); i--)
{
AsteroidState* pas = ((AsteroidState*)(FM_VAR_REF(pfmAsteroids, rgAsteroidStates))) + i;
IasteroidIGC* asteroid = pcluster->GetAsteroid(pas->asteroidID);
if (asteroid)
{
Orientation o;
pas->co.Export(&o);
asteroid->SetOrientation(o);
asteroid->SetOre(float(pas->ore));
asteroid->SetFraction(pas->bpFraction);
}
}
}
}
break;
case FM_S_STATION_CAPTURE:
{
if (!IsInGame())
break;
CASTPFM(pfmStationCapture, S, STATION_CAPTURE, pfm);
IstationIGC * station = m_pCoreIGC->GetStation(pfmStationCapture->stationID);
if (station)
{
TRef<BucketStatusArray> prgStatus;
if ((pfmStationCapture->sidOld == GetSide()->GetObjectID()) &&
m_mapBucketStatusArray.Find(pfmStationCapture->stationID, prgStatus))
{
m_mapBucketStatusArray.Remove(pfmStationCapture->stationID);
}
m_pClientEventSource->OnStationCaptured(pfmStationCapture->stationID, pfmStationCapture->sidNew);
IsideIGC* psideNew = m_pCoreIGC->GetSide(pfmStationCapture->sidNew);
PostText(true, START_COLOR_STRING "%s" END_COLOR_STRING " captured " START_COLOR_STRING "%s's %s" END_COLOR_STRING " in %s.",
(PCC) ConvertColorToString (GetCore()->GetShip(pfmStationCapture->shipIDCredit)->GetSide ()->GetColor ()),
GetCore()->GetShip(pfmStationCapture->shipIDCredit)->GetName(),
(PCC) ConvertColorToString (station->GetSide()->GetColor ()),
station->GetSide()->GetName(),
station->GetName(),
station->GetCluster()->GetName()
);
if (pfmStationCapture->sidOld == GetSideID())
PlaySoundEffect(station->GetStationType()->GetCapturedSound());
else if (pfmStationCapture->sidNew == GetSideID())
PlaySoundEffect(station->GetStationType()->GetEnemyCapturedSound());
station->SetSide(psideNew);
}
}
break;
case FM_S_LIGHT_SHIPS_UPDATE:
{
if (GetCluster())
{
CASTPFM(pfmLight, S, LIGHT_SHIPS_UPDATE, pfm);
ShipID myShipID = m_ship->GetObjectID();
ShipID* pitu = (ShipID*)(FM_VAR_REF(pfmLight, rgInactiveTurretUpdates));
if (pitu)
{
ShipID* pituMax = (ShipID*)((char*)pitu + pfmLight->cbrgInactiveTurretUpdates);
while (pitu < pituMax)
{
ShipID shipID = *(pitu++);
if (shipID != myShipID)
{
IshipIGC* pship = m_pCoreIGC->GetShip(shipID);
if (pship && pship->GetParentShip() && pship->GetCluster())
pship->SetStateM(0); }
}
}
ServerLightShipUpdate* plsu = (ServerLightShipUpdate*)(FM_VAR_REF(pfmLight, rgLightShipUpdates));
if (plsu)
{
ServerLightShipUpdate* plsuMax = (ServerLightShipUpdate*)((char*)plsu + pfmLight->cbrgLightShipUpdates);
while (plsu < plsuMax)
{
ServerLightShipUpdate& lsu = *(plsu++);
assert (lsu.shipID != myShipID);
IshipIGC* pship = m_pCoreIGC->GetShip(lsu.shipID);
if (pship && (pship->GetParentShip() == NULL) && pship->GetCluster())
{
pship->ProcessShipUpdate(lsu);
}
}
}
}
}
break;
case FM_S_HEAVY_SHIPS_UPDATE:
{
if (GetCluster())
{
CASTPFM(pfmHeavy, S, HEAVY_SHIPS_UPDATE, pfm);
if (m_pmodelServerTarget && m_pmodelServerTarget->GetCluster() && (pfmHeavy->bpTargetHull.GetChar() != 255))
{
switch(m_pmodelServerTarget->GetObjectType())
{
case OT_ship:
{
IshipIGC* pship = ((IshipIGC*)(ImodelIGC*)m_pmodelServerTarget)->GetSourceShip();
pship->SetFraction(pfmHeavy->bpTargetHull);
IshieldIGC* pshield = (IshieldIGC*)(pship->GetMountedPart(ET_Shield, 0));
if (pshield)
pshield->SetFraction(pfmHeavy->bpTargetShield);
}
break;
case OT_station:
{
IstationIGC* pstation = (IstationIGC*)(ImodelIGC*)m_pmodelServerTarget;
pstation->SetFraction(pfmHeavy->bpTargetHull);
pstation->SetShieldFraction(pfmHeavy->bpTargetShield);
}
break;
case OT_probe:
case OT_asteroid:
case OT_missile:
{
((IdamageIGC*)(ImodelIGC*)m_pmodelServerTarget)->SetFraction(pfmHeavy->bpTargetHull);
}
}
}
ServerActiveTurretUpdate* patu = (ServerActiveTurretUpdate*)(FM_VAR_REF(pfmHeavy, rgActiveTurretUpdates));
if (patu)
{
ServerActiveTurretUpdate* patuMax = (ServerActiveTurretUpdate*)((char*)patu + pfmHeavy->cbrgActiveTurretUpdates);
while (patu < patuMax)
{
ServerActiveTurretUpdate& atu= *(patu++);
assert (atu.shipID != m_ship->GetObjectID());
IshipIGC* pship = m_pCoreIGC->GetShip(atu.shipID);
if (pship && pship->GetParentShip() && pship->GetCluster())
{
pship->ProcessShipUpdate(pfmHeavy->timeReference, atu);
}
}
}
ServerHeavyShipUpdate* phsu = (ServerHeavyShipUpdate*)(FM_VAR_REF(pfmHeavy, rgHeavyShipUpdates));
if (phsu)
{
ServerHeavyShipUpdate* phsuMax = (ServerHeavyShipUpdate*)((char*)phsu + pfmHeavy->cbrgHeavyShipUpdates);
while (phsu < phsuMax)
{
ServerHeavyShipUpdate& hsu = *(phsu++);
assert (hsu.shipID != m_ship->GetObjectID());
IshipIGC* pship = m_pCoreIGC->GetShip(hsu.shipID);
if (pship && (pship->GetParentShip() == NULL) && pship->GetCluster())
{
pship->ProcessShipUpdate(pfmHeavy->timeReference, pfmHeavy->positionReference, hsu);
}
}
}
m_ship->GetSourceShip()->ProcessFractions(pfmHeavy->fractions);
}
}
break;
case FM_S_PROMOTE:
{
if (!IsInGame())
break;
CASTPFM(pfmPromote, S, PROMOTE, pfm);
IshipIGC* pship = m_pCoreIGC->GetShip(pfmPromote->shipidPromoted);
assert (pship);
IshipIGC* pshipParent = pship->GetParentShip();
if (pshipParent)
{
pship->Promote();
m_pClientEventSource->OnBoardShip(pship, NULL);
m_pClientEventSource->OnBoardShip(pshipParent, pship);
if (pshipParent == m_ship)
PostText(true, "You have been demoted to a turret gunner");
else if (pship == m_ship)
PostText(true, "You have been promoted to pilot");
}
}
break;
case FM_S_WARP_BOMB:
{
if (!IsInGame())
break;
CASTPFM(pfmWarpBomb, S, WARP_BOMB, pfm);
IwarpIGC* pwarp = m_pCoreIGC->GetWarp(pfmWarpBomb->warpidBombed);
if (pwarp)
{
ImissileTypeIGC* pmt = (ImissileTypeIGC*)(m_pCoreIGC->GetExpendableType(pfmWarpBomb->expendableidMissile));
assert (pmt);
assert (pmt->GetObjectType() == OT_missileType);
pwarp->AddBomb(ClientTimeFromServerTime(pfmWarpBomb->timeExplosion), pmt);
IclusterIGC* pclusterMe = GetCluster();
IclusterIGC* pc1 = pwarp->GetCluster();
IclusterIGC* pc2 = pwarp->GetDestination()->GetCluster();
if ((pclusterMe == pc1) || (pclusterMe == pc2))
PostText(true, "Aleph to %s destabilized\n", (pclusterMe == pc1) ? pc2->GetName() : pc1->GetName());
}
}
break;
case FM_S_RIPCORD_ACTIVATE:
{
if (!IsInGame())
break;
CASTPFM(pfmRipcordActivate, S, RIPCORD_ACTIVATE, pfm);
IshipIGC* pshipSource = m_ship->GetSourceShip();
if (pfmRipcordActivate->shipidRipcord == pshipSource->GetObjectID())
{
ImodelIGC* pmodelRipcord = m_pCoreIGC->GetModel(pfmRipcordActivate->otRipcord,
pfmRipcordActivate->oidRipcord);
IclusterIGC* pclusterDesired = m_pCoreIGC->GetCluster(pfmRipcordActivate->sidRipcord);
assert (pclusterDesired);
assert (pmodelRipcord);
IclusterIGC* pclusterRipcord = pmodelRipcord->GetCluster();
if (pclusterRipcord == NULL)
{
assert (pmodelRipcord->GetObjectType() == OT_ship);
PlayerInfo* ppi = (PlayerInfo*)(((IshipIGC*)pmodelRipcord)->GetPrivateData());
assert (ppi->StatusIsCurrent());
pclusterRipcord = m_pCoreIGC->GetCluster(ppi->LastSeenSector());
assert (pclusterRipcord);
}
const char* name = pclusterRipcord->GetName();
char bfr[100];
if (pclusterRipcord != pclusterDesired)
sprintf(bfr, "Ripcording to %s, which is closest to %s",
name, pclusterDesired->GetName());
else
sprintf(bfr, "Ripcording to %s", name);
PostText(true, bfr);
if (pmodelRipcord != pshipSource->GetRipcordModel())
{
pshipSource->SetRipcordModel(pmodelRipcord);
pshipSource->ResetRipcordTimeLeft();
}
pshipSource->GetThingSite ()->SetTimeUntilRipcord (pshipSource->GetRipcordTimeLeft ());
}
else
{
IshipIGC* pship = m_pCoreIGC->GetShip(pfmRipcordActivate->shipidRipcord);
pship->SetRipcordModel(pship);
pship->ResetRipcordTimeLeft ();
pship->GetThingSite ()->SetTimeUntilRipcord (pship->GetRipcordTimeLeft ());
}
}
break;
case FM_S_RIPCORD_DENIED:
{
if (!IsInGame())
break;
PlayNotificationSound(salNoRipcordSound, m_ship);
}
break;
case FM_S_RIPCORD_ABORTED:
{
if (!IsInGame())
break;
CASTPFM(pfmRipcordAborted, S, RIPCORD_ABORTED, pfm);
IshipIGC* pship = m_pCoreIGC->GetShip(pfmRipcordAborted->shipidRipcord);
assert (pship);
pship->SetRipcordModel(NULL);
if (pship == m_ship->GetSourceShip())
PlayNotificationSound(salRipcordAbortedSound, pship);
pship->GetThingSite ()->SetTimeUntilRipcord (-1.0f);
}
break;
case FM_S_SET_CLUSTER:
{
CASTPFM(pfmSetCluster, S, SET_CLUSTER, pfm);
if (IsLockedDown())
EndLockDown(lockdownLoadout | lockdownTeleporting);
m_bLaunchAfterDisembark = false;
m_sidBoardAfterDisembark = NA;
m_sidTeleportAfterDisembark = NA;
IclusterIGC* pcluster = m_pCoreIGC->GetCluster(pfmSetCluster->sectorID);
assert (pcluster);
IshipIGC* pship = m_ship->GetSourceShip();
{
const ShipListIGC* ships = m_pCoreIGC->GetShips();
assert (ships);
for (ShipLinkIGC* l = ships->first();
(l != NULL);
l = l->next())
{
IshipIGC* s = l->data();
if ((s != pship) && (s != m_ship))
s->SetCluster(NULL);
}
}
{
assert (pship->GetThingSite());
pship->GetThingSite()->SetTrailColor(GetShip()->GetSide()->GetColor());
IclusterIGC* pclusterOld;
Orientation orientationOld;
if (pship != m_ship)
{
pclusterOld = NULL;
orientationOld = pship->GetOrientation();
}
Time time = pcluster->GetLastUpdate();
pship->SetLastUpdate(time);
pfmSetCluster->shipupdate.time = ClientTimeFromServerTime(pfmSetCluster->shipupdate.time);
pship->ProcessShipUpdate(pfmSetCluster->shipupdate);
if (m_ship->GetStation() != NULL)
{
assert (m_ship->GetCluster() == NULL);
m_ship->SetStation(NULL); }
else
{
pclusterOld = m_ship->GetCluster();
if (pclusterOld != NULL)
{
PlaySoundEffect(jumpSound);
}
}
assert (m_ship->GetStation() == NULL);
if (pship == m_ship)
{
SetCookie(pfmSetCluster->cookie);
}
else
{
Mount tid = m_ship->GetTurretID();
if (tid != NA)
{
if (pclusterOld == NULL)
{
Orientation oTurret = pship->GetHullType()->GetWeaponOrientation(tid) *
pship->GetOrientation();
m_ship->SetOrientation(oTurret);
}
else
{
m_ship->SetOrientation(pship->GetOrientation().TimesInverse(orientationOld) * m_ship->GetOrientation());
}
}
}
pship->SetCluster(pcluster);
}
}
break;
case FM_S_DOCKED:
{
CASTPFM(pfmDocked, S, DOCKED, pfm);
{
const ShipListIGC* ships = m_pCoreIGC->GetShips();
assert (ships);
for (ShipLinkIGC* l = ships->first();
(l != NULL);
l = l->next())
{
IshipIGC* s = l->data();
if (s != m_ship)
s->SetCluster(NULL);
}
}
m_ship->SetStation(m_pCoreIGC->GetStation(pfmDocked->stationID));
assert (m_ship->GetCluster() == NULL);
}
break;
case FM_S_SINGLE_SHIP_UPDATE:
{
if (IsWaitingForGameRestart())
break;
IclusterIGC* pcluster = GetCluster();
if (pcluster)
{
CASTPFM(pfmSSU, S, SINGLE_SHIP_UPDATE, pfm);
if (m_ship->GetObjectID() != pfmSSU->shipupdate.shipID)
{
IshipIGC* pshipParent = m_ship->GetParentShip();
if ((pshipParent == NULL) ||
(pshipParent->GetObjectID() != pfmSSU->shipupdate.shipID))
{
IshipIGC* ship = m_pCoreIGC->GetShip(pfmSSU->shipupdate.shipID);
assert (ship);
assert (ship->GetBaseHullType());
assert (ship->GetParentShip() == NULL);
assert (ship->GetThingSite());
ship->GetThingSite()->SetTrailColor(ship->GetSide()->GetColor());
Time time = pcluster->GetLastUpdate();
ship->SetLastUpdate(time);
pfmSSU->shipupdate.time = ClientTimeFromServerTime(pfmSSU->shipupdate.time);
ship->ProcessShipUpdate(pfmSSU->shipupdate);
ship->SetRipcordModel(pfmSSU->bIsRipcording ? ship : NULL); {
ImodelIGC* pmodel = m_pCoreIGC->GetModel(pfmSSU->otTarget, pfmSSU->oidTarget);
ship->SetCommand(c_cmdCurrent, pmodel, c_cidNone);
}
if (ship->GetCluster() == NULL)
{
debugf("Moving %s/%d to %s\n",
ship->GetName(), ship->GetObjectID(),
pcluster->GetName());
ship->SetCluster(pcluster);
ship->SetLastUpdate(time);
}
else
assert (ship->GetCluster() == pcluster);
}
}
}
}
break;
case FM_S_SHIP_RESET:
{
CASTPFM(pfmShipReset, S, SHIP_RESET, pfm);
if (m_ship->GetCluster() && (m_ship->GetParentShip() == NULL))
{
pfmShipReset->shipupdate.time = ClientTimeFromServerTime(pfmShipReset->shipupdate.time);
m_ship->ProcessShipUpdate(pfmShipReset->shipupdate, false);
SetCookie(pfmShipReset->cookie);
}
}
break;
case FM_S_AUTODONATE:
{
CASTPFM(pfmAutoDonate, S, AUTODONATE, pfm);
IshipIGC* pshipBy = m_ship->GetSide()->GetShip(pfmAutoDonate->sidDonateBy);
assert (pshipBy);
IshipIGC* pshipTo = pfmAutoDonate->sidDonateTo == NA
? NULL
: m_ship->GetSide()->GetShip(pfmAutoDonate->sidDonateTo);
IshipIGC* pshipOld = pshipBy->GetAutoDonate();
pshipBy->SetAutoDonate(pshipTo);
if ((m_pCoreIGC->GetMissionStage() == STAGE_STARTED) && (pshipOld != pshipTo))
{
if (pshipBy == GetShip())
{
if (pshipTo)
{
char bfr[100];
sprintf(bfr, "You have started donating your income to %s", pshipTo->GetName());
PostText(true, bfr);
}
else
{
PostText(true, "You have stopped donating your income to %s", pshipOld->GetName());
}
}
else if (pshipTo == GetShip())
{
char bfr[100];
sprintf(bfr, "%s is now donating to you", pshipBy->GetName());
PostText(true, bfr);
int nNumDonors = 0;
for (ShipLinkIGC* psl = GetSide()->GetShips()->first();
(psl != NULL);
psl = psl->next())
{
if (psl->data()->GetAutoDonate() == GetShip())
nNumDonors++;
}
if (nNumDonors == 1)
PlaySoundEffect(investorSound);
}
else if (pshipOld == GetShip())
{
char bfr[100];
sprintf(bfr, "%s has stopped donating to you", pshipBy->GetName());
PostText(true, bfr);
}
}
if (pfmAutoDonate->amount != 0)
{
if (pshipTo)
{
PlayerInfo* ppiTo = (PlayerInfo*)(pshipTo->GetPrivateData());
ppiTo->SetMoney(ppiTo->GetMoney() + pfmAutoDonate->amount);
m_pClientEventSource->OnMoneyChange(ppiTo);
if (pshipBy != m_ship) {
PlayerInfo* ppiBy = (PlayerInfo*)(pshipBy->GetPrivateData());
ppiBy->SetMoney(ppiBy->GetMoney() - pfmAutoDonate->amount);
m_pClientEventSource->OnMoneyChange(ppiBy);
}
}
else if (pshipBy == m_ship)
{
SetMoney(GetMoney() + pfmAutoDonate->amount);
m_pClientEventSource->OnMoneyChange(m_pPlayerInfo);
}
}
SideInfo* psideinfo = m_pMissionInfo->GetSideInfo(GetSideID());
if (psideinfo)
{
psideinfo->GetMembers().GetSink()();
}
}
break;
case FM_S_PAYDAY:
{
if (!IsInGame())
break;
CASTPFM(pfmPayday, S, PAYDAY, pfm);
Money moneyReceived = 0;
for (ShipLinkIGC* psl = GetSide()->GetShips()->first();
(psl != NULL);
psl = psl->next())
{
IshipIGC* pship = psl->data();
if (pship->GetPilotType() >= c_ptPlayer)
{
IshipIGC* pshipDonate = pship->GetAutoDonate();
if (pshipDonate)
{
if (pshipDonate == m_ship)
moneyReceived += pfmPayday->dMoney;
}
else
pshipDonate = pship;
PlayerInfo* ppi = (PlayerInfo*)(pshipDonate->GetPrivateData());
ppi->SetMoney(ppi->GetMoney() + pfmPayday->dMoney);
m_pClientEventSource->OnMoneyChange(ppi);
}
}
m_pMissionInfo->GetSideInfo(GetSide()->GetObjectID())->GetMembers().GetSink()();
PlaySoundEffect(paydaySound);
{
IshipIGC* pshipDonate = m_ship->GetAutoDonate();
if (pshipDonate)
PostText(false, "You donated your payday of $%d to %s.", pfmPayday->dMoney, pshipDonate->GetName());
else if (moneyReceived == 0)
PostText(false, "You received a payday of $%d.", pfmPayday->dMoney);
else
PostText(false, "You received $%d in pay and donations.", pfmPayday->dMoney + moneyReceived);
}
}
break;
case FM_S_MONEY_CHANGE:
{
if (!IsInGame())
break;
CASTPFM(pfmMoney, S, MONEY_CHANGE, pfm);
ShipID sid = GetShipID();
if (sid != pfmMoney->sidFrom)
{
IshipIGC* pshipTo = m_pCoreIGC->GetShip(pfmMoney->sidTo);
assert (pshipTo);
{
PlayerInfo* ppiTo = (PlayerInfo*)(pshipTo->GetPrivateData());
ppiTo->SetMoney(ppiTo->GetMoney() + pfmMoney->dMoney);
m_pClientEventSource->OnMoneyChange(ppiTo);
}
if ((pfmMoney->sidTo != pfmMoney->sidFrom) && (pfmMoney->sidFrom != NA))
{
IshipIGC* pshipFrom = m_pCoreIGC->GetShip(pfmMoney->sidFrom);
assert (pshipFrom);
{
PlayerInfo* ppiFrom = (PlayerInfo*)(pshipFrom->GetPrivateData());
ppiFrom->SetMoney(ppiFrom->GetMoney() - pfmMoney->dMoney);
m_pClientEventSource->OnMoneyChange(ppiFrom);
if (pfmMoney->sidTo == sid)
PostText(false, "%s gave you $%d. You now have $%d.",
ppiFrom->CharacterName(), pfmMoney->dMoney, MyPlayerInfo()->GetMoney());
}
}
m_pMissionInfo->GetSideInfo(GetSide()->GetObjectID())->GetMembers().GetSink()();
}
}
break;
case FM_S_SET_MONEY:
{
CASTPFM(pfmMoney, S, SET_MONEY, pfm);
IshipIGC* pship = m_pCoreIGC->GetShip(pfmMoney->shipID);
assert (pship);
{
PlayerInfo* ppi = (PlayerInfo*)(pship->GetPrivateData());
ppi->SetMoney(pfmMoney->money);
m_pClientEventSource->OnMoneyChange(ppi);
}
m_pMissionInfo->GetSideInfo(GetSide()->GetObjectID())->GetMembers().GetSink()();
}
break;
case FM_S_ADD_PART:
{
if (!IsInGame())
break;
CASTPFM(pfmAddPart, S, ADD_PART, pfm);
if (pfmAddPart->shipID != m_ship->GetObjectID())
{
IshipIGC* pShip = m_pCoreIGC->GetShip(pfmAddPart->shipID);
assert (pShip);
assert (pShip->GetParentShip() == NULL);
assert (pShip->GetBaseHullType());
IpartTypeIGC* ppt = m_pCoreIGC->GetPartType(pfmAddPart->newPartData.partID);
assert (ppt);
IpartIGC* ppart = pShip->GetMountedPart(ppt->GetEquipmentType(), pfmAddPart->newPartData.mountID);
if (ppart)
{
assert (ppart->GetPartType() == ppt);
ppart->SetAmount(ppart->GetAmount() + pfmAddPart->newPartData.amount);
}
else
pShip->CreateAndAddPart(ppt, pfmAddPart->newPartData.mountID, pfmAddPart->newPartData.amount);
}
}
break;
case FM_CS_DROP_PART:
{
if (!IsInGame())
break;
CASTPFM(pfmDropPart, CS, DROP_PART, pfm);
if (pfmDropPart->shipID != m_ship->GetObjectID())
{
IshipIGC* pShip = m_pCoreIGC->GetShip(pfmDropPart->shipID);
assert (pShip);
assert (pShip->GetParentShip() == NULL);
assert (pShip->GetBaseHullType());
IpartIGC* ppart = pShip->GetMountedPart(pfmDropPart->et, pfmDropPart->mount);
assert (ppart);
ppart->Terminate();
}
}
break;
case FM_CS_SWAP_PART:
{
if (!IsInGame())
break;
CASTPFM(pfmSwapPart, CS, SWAP_PART, pfm);
if (pfmSwapPart->shipID != m_ship->GetObjectID())
{
IshipIGC* pShip = m_pCoreIGC->GetShip(pfmSwapPart->shipID);
assert (pShip);
assert (pShip->GetParentShip() == NULL);
assert (pShip->GetBaseHullType());
assert (pfmSwapPart->mountNew >= -c_maxCargo);
IpartIGC* ppart = pShip->GetMountedPart(pfmSwapPart->etOld, pfmSwapPart->mountOld);
assert (ppart);
IpartIGC* ppartNew = pShip->GetMountedPart(pfmSwapPart->etOld, pfmSwapPart->mountNew);
if (ppartNew)
{
ppart->SetMountID(c_mountNA);
ppartNew->SetMountID(pfmSwapPart->mountOld);
}
ppart->SetMountID(pfmSwapPart->mountNew);
}
}
break;
case FM_CS_RELOAD:
{
if (!IsInGame())
break;
CASTPFM(pfmReload, CS, RELOAD, pfm);
if (pfmReload->shipID != m_ship->GetObjectID())
{
IshipIGC* pship = m_pCoreIGC->GetShip(pfmReload->shipID);
assert (pship);
ReloadData* prlNext = (ReloadData*)FM_VAR_REF(pfmReload, rgReloads);
int nReloads = pfmReload->cbrgReloads / sizeof(ReloadData);
ReloadData* prlStop = prlNext + nReloads;
while (prlNext < prlStop)
{
assert (prlNext->mount < 0);
assert (prlNext->mount >= -c_maxCargo);
IpartIGC* ppart = pship->GetMountedPart(NA, prlNext->mount);
ObjectType type = ppart->GetObjectType();
if (type == OT_pack)
{
IpackIGC* ppack = (IpackIGC*)ppart;
PackType packtype = ppack->GetPackType();
short amount = ppack->GetAmount();
if (prlNext->amountTransfered == NA)
{
OnReload(ppart, true);
ppack->Terminate();
}
else
{
OnReload(ppart, false);
assert (prlNext->amountTransfered > 0);
assert (prlNext->amountTransfered < amount);
ppack->SetAmount(amount - prlNext->amountTransfered);
amount = prlNext->amountTransfered;
}
if (packtype == c_packAmmo)
{
pship->SetAmmo(pship->GetAmmo() + amount);
Mount maxWeapons = pship->GetHullType()->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
{
assert (packtype == c_packFuel);
pship->SetFuel(pship->GetFuel() + float(amount));
IpartIGC* pa = pship->GetMountedPart(ET_Afterburner, 0);
if (pa)
pa->SetMountedFraction(0.0f);
}
}
else
{
assert (IlauncherIGC::IsLauncher(type));
IlauncherIGC* plauncher = (IlauncherIGC*)ppart;
IlauncherIGC* plauncherMounted = (IlauncherIGC*)(pship->GetMountedPart(plauncher->GetEquipmentType(), 0));
if (prlNext->amountTransfered == NA)
{
OnReload(ppart, true);
assert ((plauncherMounted == NULL) || (plauncherMounted->GetAmount() == 0));
if (plauncherMounted)
plauncherMounted->Terminate();
plauncher->SetMountID(0);
}
else
{
assert (prlNext->amountTransfered <= plauncher->GetAmount());
assert (plauncherMounted);
short amount = plauncher->GetAmount();
if (amount == prlNext->amountTransfered)
{
OnReload(ppart, true);
plauncher->Terminate();
}
else
{
OnReload(ppart, false);
plauncher->SetAmount(amount - prlNext->amountTransfered);
}
plauncherMounted->SetAmount(plauncherMounted->GetAmount() + prlNext->amountTransfered);
plauncherMounted->SetMountedFraction(0.0f);
plauncherMounted->ResetTimeLoaded();
}
}
prlNext++;
}
}
}
break;
case FM_CS_FIRE_MISSILE:
{
if (!IsInGame())
break;
CASTPFM(pfmFireMissile, CS, FIRE_MISSILE, pfm);
DataMissileIGC dm;
dm.pLauncher = m_pCoreIGC->GetShip(pfmFireMissile->launcherID);
if (dm.pLauncher)
{
dm.pmissiletype = (ImissileTypeIGC*)(m_pCoreIGC->GetExpendableType(pfmFireMissile->missiletypeID));
dm.pTarget = m_pCoreIGC->GetModel(pfmFireMissile->targetType, pfmFireMissile->targetID);
dm.pCluster = m_pCoreIGC->GetCluster(pfmFireMissile->clusterID);
dm.lock = pfmFireMissile->lock;
Time timeFired = ClientTimeFromServerTime(pfmFireMissile->timeFired);
int iNumMissiles = pfmFireMissile->cbmissileLaunchData / sizeof(MissileLaunchData);
MissileLaunchData* pMissileLaunchData = (MissileLaunchData*) (FM_VAR_REF(pfmFireMissile, missileLaunchData));
for (int i = 0; i < iNumMissiles; i++)
{
dm.position = pMissileLaunchData[i].vecPosition;
dm.velocity = pMissileLaunchData[i].vecVelocity;
dm.forward = pMissileLaunchData[i].vecForward;
dm.missileID = pMissileLaunchData[i].missileID;
dm.bDud = pfmFireMissile->bDud;
ImissileIGC* m = (ImissileIGC*)(m_pCoreIGC->CreateObject(timeFired, OT_missile, &dm, sizeof(dm)));
if (m)
m->Release();
}
if (pfmFireMissile->launcherID != m_ship->GetObjectID())
{
ImagazineIGC* pmagazine = (ImagazineIGC*)(dm.pLauncher->GetMountedPart(ET_Magazine, 0));
if (pmagazine)
{
short amount = pmagazine->GetAmount() - iNumMissiles;
assert (amount >= 0);
pmagazine->SetAmount(amount);
}
}
}
}
break;
case FM_S_FIRE_EXPENDABLE:
{
if (!IsInGame())
break;
CASTPFM(pfmFireExpendable, S, FIRE_EXPENDABLE, pfm);
if (pfmFireExpendable->launcherID != m_ship->GetObjectID())
{
IshipIGC* pshipLauncher = m_pCoreIGC->GetShip(pfmFireExpendable->launcherID);
if (pshipLauncher)
{
IdispenserIGC* pdispenser = (IdispenserIGC*)(pshipLauncher->GetMountedPart(pfmFireExpendable->equipmentType, 0));
if (pdispenser)
{
short amount = pdispenser->GetAmount() - 1;
assert (amount >= 0);
pdispenser->SetAmount(amount);
}
}
}
}
break;
case FM_S_CREATE_CHAFF:
{
CASTPFM(pfmChaff, S, CREATE_CHAFF, pfm);
DataChaffIGC dc;
if (GetCluster())
{
dc.time0 = pfmChaff->time0;
dc.p0 = pfmChaff->p0;
dc.v0 = pfmChaff->v0;
dc.pchafftype = (IchaffTypeIGC*)(m_pCoreIGC->GetExpendableType(pfmChaff->etid));
assert (dc.pchafftype->GetObjectType() == OT_chaffType);
dc.pcluster = GetCluster();
IchaffIGC* c = (IchaffIGC*)(m_pCoreIGC->CreateObject(lastUpdate, OT_chaff, &dc, sizeof(dc)));
assert (c);
m_pchaffLastCreated = c;
c->Release();
}
}
break;
case FM_S_MISSILE_SPOOFED:
{
CASTPFM(pfmMissileSpoofed, S, MISSILE_SPOOFED, pfm);
if (GetCluster())
{
ImissileIGC* pmissile = GetCluster()->GetMissile(pfmMissileSpoofed->missileID);
if (pmissile)
{
assert (m_pchaffLastCreated);
pmissile->SetTarget(m_pchaffLastCreated);
}
}
}
break;
case FM_S_END_SPOOFING:
{
m_pchaffLastCreated = NULL;
}
break;
case FM_S_ASTEROID_DESTROYED:
{
if (!IsInGame())
break;
CASTPFM(pfmAD, S, ASTEROID_DESTROYED, pfm);
IclusterIGC* pcluster = m_pCoreIGC->GetCluster(pfmAD->clusterID);
assert (pcluster);
IasteroidIGC* pasteroid = pcluster->GetAsteroid(pfmAD->asteroidID);
if (pasteroid)
{
if (pfmAD->explodeF)
pasteroid->GetCluster()->GetClusterSite()->AddExplosion(pasteroid, c_etAsteroid);
else
{
if (pasteroid->GetBuildingEffect())
pasteroid->SetBuildingEffect(NULL);
}
pasteroid->Terminate();
}
}
break;
case FM_S_ASTEROID_DRAINED:
{
if (!IsInGame())
break;
CASTPFM(pfmAD, S, ASTEROID_DRAINED, pfm);
IclusterIGC* pcluster = m_pCoreIGC->GetCluster(pfmAD->clusterID);
assert (pcluster);
IasteroidIGC* pasteroid = pcluster->GetAsteroid(pfmAD->asteroidID);
if (pasteroid)
{
pasteroid->SetOre(0.0f);
}
}
break;
case FM_S_PROBE_DESTROYED:
{
if (!IsInGame())
break;
CASTPFM(pfmPD, S, PROBE_DESTROYED, pfm);
IclusterIGC* pcluster = m_pCoreIGC->GetCluster(pfmPD->clusterID);
assert (pcluster);
IprobeIGC* pprobe = pcluster->GetProbe(pfmPD->probeID);
if (pprobe)
pprobe->Terminate();
}
break;
case FM_S_BUILDINGEFFECT_DESTROYED:
{
if (!IsInGame())
break;
CASTPFM(pfmBED, S, BUILDINGEFFECT_DESTROYED, pfm);
IasteroidIGC* pasteroid = m_pCoreIGC->GetAsteroid(pfmBED->asteroidID);
if (pasteroid)
{
IbuildingEffectIGC* pbe = pasteroid->GetBuildingEffect();
if (pbe)
pbe->Terminate();
}
}
break;
case FM_S_MISSILE_DESTROYED:
{
if (!IsInGame())
break;
CASTPFM(pfmMD, S, MISSILE_DESTROYED, pfm);
IclusterIGC* pcluster = m_pCoreIGC->GetCluster(pfmMD->clusterID);
assert (pcluster);
ImissileIGC* pmissile = pcluster->GetMissile(pfmMD->missileID);
if (pmissile)
{
if (pfmMD->position != Vector::GetZero())
pmissile->Explode(pfmMD->position);
pmissile->Terminate();
}
}
break;
case FM_S_MINE_DESTROYED:
{
if (!IsInGame())
break;
CASTPFM(pfmMD, S, MINE_DESTROYED, pfm);
IclusterIGC* pcluster = m_pCoreIGC->GetCluster(pfmMD->clusterID);
assert (pcluster);
ImineIGC* pmine = pcluster->GetMine(pfmMD->mineID);
if (pmine)
pmine->Terminate();
}
break;
case FM_CS_ORDER_CHANGE:
{
if (!IsInGame())
break;
SideInfo* psideinfo = m_pMissionInfo->GetSideInfo(GetSideID());
if (psideinfo)
{
CASTPFM(pfmOC, CS, ORDER_CHANGE, pfm);
IshipIGC* pship = m_pCoreIGC->GetShip(pfmOC->shipID);
if (pship)
{
ImodelIGC* pmodel = m_pCoreIGC->GetModel(pfmOC->objectType, pfmOC->objectID);
if (pship != m_ship)
pship->SetCommand(pfmOC->command, pmodel, pfmOC->commandID);
else if (pfmOC->command == c_cmdCurrent)
m_pmodelServerTarget = pmodel;
psideinfo->GetMembers().GetSink()();
}
}
}
break;
case FM_S_TELEPORT_ACK:
{
if (!IsInGame())
break;
if (IsLockedDown())
EndLockDown(lockdownTeleporting);
CASTPFM(pfmAck, S, TELEPORT_ACK, pfm);
if (pfmAck->stationID != NA)
{
IstationIGC* pstation = m_pCoreIGC->GetStation(pfmAck->stationID);
assert (pstation);
m_ship->SetStation(pstation);
if (pfmAck->bNewHull)
{
{
const ShipListIGC* pshipsChildren = m_ship->GetChildShips();
ShipLinkIGC* psl;
while (psl = pshipsChildren->first()) {
IshipIGC* pshipChild = psl->data();
pshipChild->SetParentShip(NULL);
m_pClientEventSource->OnBoardShip(pshipChild, NULL);
}
}
const PartListIGC* pparts = m_ship->GetParts();
PartLinkIGC* ppl;
while (ppl = pparts->first()) ppl->data()->Terminate();
ReplaceLoadout(pstation);
}
PlaySoundEffect(personalJumpSound);
}
}
break;
case FM_S_BOARD_NACK:
{
if (!IsInGame())
break;
if (IsLockedDown())
EndLockDown(lockdownTeleporting);
CASTPFM(pfmBoardNack, S, BOARD_NACK, pfm);
IshipIGC* pshipRequestedParent = m_pCoreIGC->GetShip(pfmBoardNack->sidRequestedParent);
m_pClientEventSource->OnBoardFailed(pshipRequestedParent);
}
break;
case FM_S_LEAVE_SHIP:
{
if (!IsInGame())
break;
CASTPFM(pfmLeave, S, LEAVE_SHIP, pfm);
IshipIGC* pshipChild = m_pCoreIGC->GetShip(pfmLeave->sidChild);
assert (pshipChild);
pshipChild->SetParentShip(NULL);
m_pClientEventSource->OnBoardShip(pshipChild, NULL);
if (pshipChild == m_ship)
{
assert (pshipChild->GetBaseHullType() == NULL);
assert (pshipChild->GetParts()->n() == 0);
if (IsLockedDown())
EndLockDown(lockdownTeleporting);
pshipChild->SetBaseHullType(pshipChild->GetSide()->GetCivilization()->GetLifepod());
ReplaceLoadout(m_ship->GetStation(), m_bLaunchAfterDisembark);
m_bLaunchAfterDisembark = false;
}
else if (pshipChild->GetParentShip() == m_ship)
PostText(true, "%s has left your ship.", pshipChild->GetName());
}
break;
case FM_S_ENTER_LIFEPOD:
{
if (!IsInGame())
break;
CASTPFM(pfmEnter, S, ENTER_LIFEPOD, pfm);
m_ship->SetParentShip(NULL);
m_pClientEventSource->OnBoardShip(m_ship, NULL);
{
const ShipListIGC* pshipsChildren = m_ship->GetChildShips();
ShipLinkIGC* psl;
while (psl = pshipsChildren->first()) {
IshipIGC* pshipChild = psl->data();
pshipChild->SetParentShip(NULL);
m_pClientEventSource->OnBoardShip(pshipChild, NULL);
}
}
{
const PartListIGC* pparts = m_ship->GetParts();
PartLinkIGC* ppl;
while (ppl = pparts->first()) ppl->data()->Terminate();
}
m_ship->SetBaseHullType(m_ship->GetSide()->GetCivilization()->GetLifepod());
}
break;
case FM_CS_LOGOFF:
{
m_fLoggedOn = false;
Disconnect(); break;
}
case FM_S_LOADOUT_CHANGE:
{
if (IsWaitingForGameRestart())
break;
CASTPFM(pfmLC, S, LOADOUT_CHANGE, pfm);
IshipIGC* pship = pfmLC->sidShip == NA
? m_ship
: m_pCoreIGC->GetShip(pfmLC->sidShip);
assert (pship);
pship->SetParentShip(NULL);
m_pClientEventSource->OnBoardShip(pship, NULL);
{
const ShipListIGC* pshipsChildren = pship->GetChildShips();
ShipLinkIGC* psl;
while (psl = pshipsChildren->first()) {
IshipIGC* pshipChild = psl->data();
pshipChild->SetParentShip(NULL);
m_pClientEventSource->OnBoardShip(pshipChild, NULL);
}
}
if (pfmLC->sidShip != GetShipID())
{
pship->ProcessShipLoadout(pfmLC->cbloadout,
(const ShipLoadout*)(FM_VAR_REF(pfmLC, loadout)), (pship->GetCluster() == NULL));
}
{
const PassengerData* ppassengersLC = (const PassengerData*)(FM_VAR_REF(pfmLC, rgPassengers));
const PassengerData* pstop = (const PassengerData*)(((char*)ppassengersLC) + pfmLC->cbrgPassengers);
for (const PassengerData* ppd = ppassengersLC; (ppd < pstop); ppd++)
{
IshipIGC* pshipChild = m_pCoreIGC->GetShip(ppd->shipID);
assert (pshipChild);
if (pshipChild == m_ship)
{
SetAutoPilot(false);
if ((ppd->turretID != NA) && (m_ship->GetCluster() != NULL) && (pshipChild->GetTurretID() != ppd->turretID))
{
Orientation oTurret = pship->GetHullType()->GetWeaponOrientation(ppd->turretID) *
pship->GetOrientation();
pshipChild->SetOrientation(oTurret);
}
}
else
{
assert (pshipChild->GetAutopilot() == false);
}
pshipChild->SetParentShip(pship);
assert (pshipChild->GetBaseHullType() == NULL);
assert (pshipChild->GetParts()->n() == 0);
if (pship == m_ship && m_ship->GetCluster() == NULL)
{
if (ppd->turretID != NA)
PostText(true, "%s has boarded your ship as a turret.", pshipChild->GetName());
else
PostText(true, "%s has boarded your ship as an observer.", pshipChild->GetName());
PlaySoundEffect(boardSound);
}
pshipChild->SetTurretID(ppd->turretID);
m_pClientEventSource->OnBoardShip(pshipChild, pship);
if (pshipChild == m_ship && IsLockedDown())
EndLockDown(lockdownTeleporting);
}
}
assert ((m_ship->GetParentShip() != NULL) || (m_ship->GetBaseHullType() != NULL));
}
break;
case FM_CS_SET_WINGID:
{
CASTPFM(pfmSW, CS, SET_WINGID, pfm);
IshipIGC* pship = m_ship->GetSide()->GetShip(pfmSW->shipID);
assert (pship);
if ((pship != m_ship) || pfmSW->bCommanded)
{
pship->SetWingID(pfmSW->wingID);
if (pfmSW->bCommanded && (pship == m_ship))
PostText(true, "You have been assigned to wing %s", c_pszWingName[pfmSW->wingID]);
}
m_pMissionInfo->GetSideInfo(pship->GetSide()->GetObjectID())->GetMembers().GetSink()();
}
break;
case FM_S_JOINED_MISSION:
{
CASTPFM(pfmJoinedMission, S, JOINED_MISSION, pfm);
assert(m_pMissionInfo != NULL);
assert(m_dwCookieToJoin == pfmJoinedMission->dwCookie || !m_fmLobby.IsConnected());
debugf("I am ship %d\n", pfmJoinedMission->shipID);
if (lstrcmp(m_pMissionInfo->GetIGCStaticFile(), m_szIGCStaticFile) != 0
&& !ResetStaticData(m_pMissionInfo->GetIGCStaticFile(), &m_pCoreIGC, now, GetIsZoneClub()))
{
Disconnect();
delete m_pMissionInfo;
m_pMissionInfo = NULL;
OnLogonAck(false, false, "The client and server data files are out of sync. Please restart and go to a games list to auto-update "
"the latest files. If this doesn't work, try deleting the file 'filelist.txt' from the install directory and restarting the application.");
}
else
{
PlayerInfo* pPlayerInfo = m_pPlayerInfo;
if (!pPlayerInfo)
{
PlayerLink* l = new PlayerLink;
m_listPlayers.last(l);
pPlayerInfo = &(l->data());
}
pPlayerInfo->SetMission(m_pCoreIGC);
FMD_S_PLAYERINFO fmPlayerInfo;
memset(&fmPlayerInfo, 0, sizeof(fmPlayerInfo));
strcpy(fmPlayerInfo.CharacterName, "<error>");
fmPlayerInfo.shipID = pfmJoinedMission->shipID;
fmPlayerInfo.iSide = NA;
pPlayerInfo->Set(&fmPlayerInfo);
SetPlayerInfo(pPlayerInfo);
assert (m_pPlayerInfo == pPlayerInfo);
pPlayerInfo->SetShip(m_ship);
ZAssert(m_pPlayerInfo);
if (m_pPlayerInfo->ShipID() != pfmJoinedMission->shipID)
SetPlayerInfo(FindPlayer(pfmJoinedMission->shipID));
m_pMissionInfo->PurgePlayers();
}
break;
}
case FM_S_PLAYERINFO:
{
if (NULL == m_pCoreIGC->GetSide(SIDE_TEAMLOBBY))
{
assert(false);
OnSessionLost("Unexpected message received.", &m_fm);
}
CASTPFM(pfmPlayerInfo, S, PLAYERINFO, pfm);
PlayerLink* l = FindPlayerLink(pfmPlayerInfo->shipID);
debugf("Got Player Info for %s\n", pfmPlayerInfo->CharacterName);
SideID sideID = pfmPlayerInfo->iSide;
bool bReady = pfmPlayerInfo->fReady;
pfmPlayerInfo->iSide = NA;
if (l != NULL)
l->data().Set(pfmPlayerInfo);
else
{
l = new PlayerLink;
l->data().Set(pfmPlayerInfo);
m_listPlayers.last(l);
}
ZAssert(l);
PlayerInfo* pPlayerInfo = &(l->data());
pPlayerInfo->SetMission(m_pCoreIGC);
{
DataShipIGC ds;
ds.hullID = NA;
ds.shipID = pfmPlayerInfo->shipID;
ds.nParts = 0;
ds.sideID = NA;
ds.nDeaths = pfmPlayerInfo->nDeaths;
ds.nEjections = pfmPlayerInfo->nEjections;
ds.nKills = pfmPlayerInfo->nKills;
ds.pilotType = pfmPlayerInfo->pilotType;
ds.abmOrders = pfmPlayerInfo->abmOrders;
ds.baseObjectID = pfmPlayerInfo->baseObjectID;
strcpy(ds.name, pfmPlayerInfo->CharacterName);
IshipIGC* pship = (IshipIGC*)(m_pCoreIGC->CreateObject(m_lastSend, OT_ship, &ds, sizeof(ds)));
if (pship != NULL)
{
pship->Release();
}
else
{
pship = m_pCoreIGC->GetShip(pfmPlayerInfo->shipID);
assert (pship);
}
pPlayerInfo->SetShip(pship);
pship->SetExperience(pfmPlayerInfo->fExperience);
}
AddPlayerToMission(pPlayerInfo);
if (sideID != SIDE_TEAMLOBBY)
{
AddPlayerToSide(pPlayerInfo, sideID);
}
debugf("PlayerInfo for %s, ship=%d, side=%d\n", pPlayerInfo->CharacterName(),
pPlayerInfo->ShipID(), pPlayerInfo->SideID());
break;
}
case FM_CS_PLAYER_READY:
{
ZAssert(m_pMissionInfo);
CASTPFM(pfmPlayerReady, CS, PLAYER_READY, pfm);
PlayerInfo* pPlayerInfo = FindPlayer(pfmPlayerReady->shipID);
if (pPlayerInfo)
{
pPlayerInfo->Update(pfmPlayerReady);
if (pPlayerInfo->IsHuman())
m_pClientEventSource->OnPlayerStatusChange(m_pMissionInfo, pPlayerInfo->SideID(), pPlayerInfo);
m_pMissionInfo->GetSideInfo(pPlayerInfo->SideID())->GetMembers().GetSink()();
}
break;
}
case FM_S_MISSION_STAGE:
{
CASTPFM(pfmMissionStage, S, MISSION_STAGE, pfm);
m_pMissionInfo->SetStage(pfmMissionStage->stage);
switch (pfmMissionStage->stage)
{
case STAGE_NOTSTARTED:
{
m_pMissionInfo->SetInProgress(false);
m_pMissionInfo->SetCountdownStarted(false);
m_bWaitingForGameRestart = false;
m_pClientEventSource->OnMissionEnded(m_pMissionInfo);
break;
}
case STAGE_STARTING:
{
m_pMissionInfo->SetCountdownStarted(true);
m_pClientEventSource->OnMissionCountdown(m_pMissionInfo);
break;
}
case STAGE_STARTED:
{
m_pMissionInfo->SetCountdownStarted(false);
m_pMissionInfo->SetInProgress(true);
assert (memcmp(m_pCoreIGC->GetMissionParams(),
&m_pMissionInfo->GetMissionParams(),
sizeof(m_pMissionInfo->GetMissionParams())) == 0);
m_pCoreIGC->SetMissionStage(STAGE_STARTED);
m_pClientEventSource->OnMissionStarted(m_pMissionInfo);
break;
}
case STAGE_OVER:
{
m_pMissionInfo->SetInProgress(false);
m_bWaitingForGameRestart = false;
m_pClientEventSource->OnMissionEnded(m_pMissionInfo);
break;
}
case STAGE_TERMINATE:
{
RemovePlayerFromSide(m_pPlayerInfo, QSR_Quit);
RemovePlayerFromMission(m_pPlayerInfo, QSR_Quit);
break;
}
default:
{
assert(false);
}
}
m_mapMissions.GetSink()();
break;
}
case FM_S_CREATE_BUCKETS:
{
m_pCoreIGC->SetMissionParams(&m_pMissionInfo->GetMissionParams());
IsideIGC* pside = GetSide();
assert (pside);
assert (pside->GetObjectID() != SIDE_TEAMLOBBY);
{
m_pCoreIGC->GetSide(SIDE_TEAMLOBBY)->SetGlobalAttributeSet(pside->GetGlobalAttributeSet());
CASTPFM(pfmCB, S, CREATE_BUCKETS, pfm);
pside->SetDevelopmentTechs(pfmCB->ttbmDevelopments);
pside->SetInitialTechs(pfmCB->ttbmInitial);
pside->CreateBuckets();
}
}
break;
case FM_S_GAME_STATE:
{
CASTPFM(pfmGS, S, GAME_STATE, pfm);
SideID sid = 0;
for (SideLinkIGC* l = m_pCoreIGC->GetSides()->first(); (l != NULL); l = l->next())
{
assert (sid == l->data()->GetObjectID());
l->data()->SetConquestPercent(pfmGS->conquest[sid]);
l->data()->SetTerritoryCount(pfmGS->territory[sid]);
l->data()->SetFlags(pfmGS->nFlags[sid]);
l->data()->SetArtifacts(pfmGS->nArtifacts[sid++]);
}
}
break;
case FM_S_MISSIONDEF:
{
CASTPFM(pfmMissionDef, S, MISSIONDEF, pfm);
pfmMissionDef->misparms.timeStart = ClientTimeFromServerTime(pfmMissionDef->misparms.timeStart);
if (m_pMissionInfo == NULL)
{
m_pMissionInfo = new MissionInfo(pfmMissionDef->dwCookie);
m_pMissionInfo->Update(pfmMissionDef);
}
else
{
m_pMissionInfo->Update(pfmMissionDef);
m_pCoreIGC->SetMissionParams(&pfmMissionDef->misparms);
m_pCoreIGC->UpdateSides(Time::Now(), &(m_pMissionInfo->GetMissionParams()), pfmMissionDef->rgszName);
}
m_pClientEventSource->OnAddMission(m_pMissionInfo);
break;
}
case FM_S_SIDE_TECH_CHANGE:
{
CASTPFM(pfmSTC, S, SIDE_TECH_CHANGE, pfm);
IsideIGC* pSide = m_pCoreIGC->GetSide(pfmSTC->sideID);
assert (pSide);
pSide->SetDevelopmentTechs(pfmSTC->ttbmDevelopments);
}
break;
case FM_S_SIDE_ATTRIBUTE_CHANGE:
{
CASTPFM(pfmSAC, S, SIDE_ATTRIBUTE_CHANGE, pfm);
IsideIGC* pSide = m_pCoreIGC->GetSide(pfmSAC->sideID);
assert (pSide);
pSide->SetGlobalAttributeSet(pfmSAC->gasAttributes);
if (pSide == GetSide())
GetCore()->GetSide(SIDE_TEAMLOBBY)->SetGlobalAttributeSet(pfmSAC->gasAttributes);
}
break;
case FM_S_BUCKET_STATUS:
{
CASTPFM(pfmBucketStatus, S, BUCKET_STATUS, pfm);
IsideIGC* pside = m_pCoreIGC->GetSide(pfmBucketStatus->sideID);
assert (pside);
IbucketIGC* b = pside->GetBucket(pfmBucketStatus->iBucket);
if (b)
b->SetTimeAndMoney(pfmBucketStatus->timeTotal,
pfmBucketStatus->moneyTotal);
break;
}
case FM_S_POSITIONREQ: {
CASTPFM(pfmPosReq, S, POSITIONREQ, pfm);
PlayerInfo* ppi = FindPlayer(pfmPosReq->shipID);
m_pMissionInfo->AddRequest(pfmPosReq->iSide, pfmPosReq->shipID);
m_pClientEventSource->OnAddRequest(m_pMissionInfo, pfmPosReq->iSide, ppi);
if (MyPlayerInfo()->IsTeamLeader() && (pfmPosReq->iSide == GetSideID()))
PostText(true, "%s wishes to join your team", ppi->CharacterName());
PlaySoundEffect(salPlayerWaitingSound);
break;
}
case FM_CS_DELPOSITIONREQ:
{
CASTPFM(pfmDelPositionReq, CS, DELPOSITIONREQ, pfm);
PlayerInfo* pPlayerInfo = FindPlayer(pfmDelPositionReq->shipID);
if (pPlayerInfo && pfmDelPositionReq->iSide < m_pMissionInfo->GetMissionParams().nTeams
&& m_pMissionInfo->FindRequest(pfmDelPositionReq->iSide, pfmDelPositionReq->shipID))
{
m_pMissionInfo->RemoveRequest(pfmDelPositionReq->iSide, pfmDelPositionReq->shipID);
}
m_pClientEventSource->OnDelRequest(m_pMissionInfo, pfmDelPositionReq->iSide, pPlayerInfo, pfmDelPositionReq->reason);
break;
}
case FM_CS_QUIT_MISSION:
{
if (m_pMissionInfo)
{
CASTPFM(pfmQuitMission, CS, QUIT_MISSION, pfm);
PlayerInfo* pPlayerInfo = FindPlayer(pfmQuitMission->shipID);
if (!pPlayerInfo || pPlayerInfo->SideID() == NA)
{
assert(false);
break;
}
if (pPlayerInfo->SideID() != SIDE_TEAMLOBBY)
{
assert(false);
RemovePlayerFromSide(pPlayerInfo, QSR_Quit);
}
SideID sideIDOld = pPlayerInfo->SideID();
RemovePlayerFromMission(pPlayerInfo, pfmQuitMission->reason, FM_VAR_REF(pfmQuitMission, szMessageParam));
m_pClientEventSource->OnDelRequest(m_pMissionInfo, sideIDOld, pPlayerInfo, DPR_Canceled);
}
break;
}
case FM_CS_CHANGE_TEAM_CIV:
{
CASTPFM(pfmChangeCiv, CS, CHANGE_TEAM_CIV, pfm);
m_pCoreIGC->GetSide(pfmChangeCiv->iSide)->SetCivilization(m_pCoreIGC->GetCivilization(pfmChangeCiv->civID));
m_pClientEventSource->OnTeamCivChange(m_pMissionInfo, pfmChangeCiv->iSide, pfmChangeCiv->civID);
break;
}
case FM_CS_SET_TEAM_INFO:
{
CASTPFM(pfmSetTeamInfo, CS, SET_TEAM_INFO, pfm);
IsideIGC* pside = m_pCoreIGC->GetSide(pfmSetTeamInfo->sideID);
assert(pside);
pside->SetSquadID(pfmSetTeamInfo->squadID);
pside->SetName(pfmSetTeamInfo->SideName);
m_pMissionInfo->SetSideName(pfmSetTeamInfo->sideID, pfmSetTeamInfo->SideName);
m_pClientEventSource->OnTeamNameChange(m_pMissionInfo, pfmSetTeamInfo->sideID);
break;
}
case FM_S_TEAM_READY:
{
CASTPFM(pfmTeamReady, S, TEAM_READY, pfm);
m_pMissionInfo->SetSideReady(pfmTeamReady->iSide, pfmTeamReady->fReady);
m_pClientEventSource->OnTeamReadyChange(m_pMissionInfo, pfmTeamReady->iSide, pfmTeamReady->fReady);
break;
}
case FM_CS_SIDE_INACTIVE: {
CASTPFM(pfmSideInactive, CS, SIDE_INACTIVE, pfm); debugf("Side inactive, side=%d\n", pfmSideInactive->sideID);
m_pMissionInfo->SetSideActive(pfmSideInactive->sideID, pfmSideInactive->bActive); if (pfmSideInactive->bChangeAET)
m_pMissionInfo->SetAllowEmptyTeams(pfmSideInactive->bAET);
m_pClientEventSource->OnTeamInactive(m_pMissionInfo, pfmSideInactive->sideID);
m_mapMissions.GetSink()();
break;
}
case FM_CS_FORCE_TEAM_READY:
{
CASTPFM(pfmTeamForceReady, CS, FORCE_TEAM_READY, pfm);
m_pMissionInfo->SetSideForceReady(pfmTeamForceReady->iSide, pfmTeamForceReady->fForceReady);
m_pClientEventSource->OnTeamForceReadyChange(m_pMissionInfo, pfmTeamForceReady->iSide, pfmTeamForceReady->fForceReady);
}
break;
case FM_CS_AUTO_ACCEPT:
{
CASTPFM(pfmAutoAccept, CS, AUTO_ACCEPT, pfm);
m_pMissionInfo->SetSideAutoAccept(pfmAutoAccept->iSide, pfmAutoAccept->fAutoAccept);
m_pClientEventSource->OnTeamAutoAcceptChange(m_pMissionInfo, pfmAutoAccept->iSide, pfmAutoAccept->fAutoAccept);
m_mapMissions.GetSink()();
}
break;
case FM_CS_LOCK_LOBBY:
{
CASTPFM(pfmLockLobby, CS, LOCK_LOBBY, pfm);
m_pMissionInfo->SetLockLobby(pfmLockLobby->fLock);
m_pClientEventSource->OnLockLobby(pfmLockLobby->fLock);
m_mapMissions.GetSink()();
}
break;
case FM_CS_LOCK_SIDES:
{
CASTPFM(pfmLockSides, CS, LOCK_SIDES, pfm);
m_pMissionInfo->SetLockSides(pfmLockSides->fLock);
m_pClientEventSource->OnLockSides(pfmLockSides->fLock);
m_mapMissions.GetSink()();
}
break;
case FM_CS_REQUEST_MONEY:
{
CASTPFM(pfmRequest, CS, REQUEST_MONEY, pfm);
IshipIGC* pship = m_ship->GetSide()->GetShip(pfmRequest->shipidRequest);
if (pship)
{
GetMoneyRequest(pship, pfmRequest->amount, pfmRequest->hidFor);
}
}
break;
case FM_CS_CHATMESSAGE:
{
CASTPFM(pfmChat, CS, CHATMESSAGE, pfm);
if (pfmChat->cd.sidSender != m_ship->GetObjectID())
{
ReceiveChat(m_pCoreIGC->GetShip(pfmChat->cd.sidSender),
pfmChat->cd.chatTarget,
pfmChat->cd.oidRecipient,
pfmChat->cd.voiceOver,
FM_VAR_REF(pfmChat, Message),
pfmChat->cd.commandID,
pfmChat->otTarget,
pfmChat->oidTarget,
NULL,
pfmChat->cd.bObjectModel);
}
break;
}
case FM_CS_CHATBUOY:
{
if (!IsInGame())
break;
CASTPFM(pfmBuoy, CS, CHATBUOY, pfm);
if (pfmBuoy->cd.sidSender != m_ship->GetObjectID())
{
IbaseIGC* b = m_pCoreIGC->CreateObject(lastUpdate, OT_buoy, &(pfmBuoy->db), sizeof(pfmBuoy->db));
assert (b);
((IbuoyIGC*)b)->AddConsumer();
ReceiveChat(m_pCoreIGC->GetShip(pfmBuoy->cd.sidSender),
pfmBuoy->cd.chatTarget,
pfmBuoy->cd.oidRecipient,
pfmBuoy->cd.voiceOver,
FM_VAR_REF(pfmBuoy, Message),
pfmBuoy->cd.commandID,
OT_buoy,
b->GetObjectID(),
(ImodelIGC*)b,
pfmBuoy->cd.bObjectModel);
((IbuoyIGC*)b)->ReleaseConsumer();
b->Release();
}
}
break;
case FM_CS_MISSIONPARAMS:
{
assert(false);
CASTPFM(pfmMissionParams, CS, MISSIONPARAMS, pfm);
pfmMissionParams->missionparams.timeStart = ClientTimeFromServerTime(pfmMissionParams->missionparams.timeStart);
m_pCoreIGC->SetMissionParams(&(pfmMissionParams->missionparams));
}
break;
case FM_S_SET_START_TIME:
{
CASTPFM(pfmStartTime, S, SET_START_TIME, pfm);
ZAssert(MyMission());
Time timeStart = ClientTimeFromServerTime(pfmStartTime->timeStart);
MyMission()->UpdateStartTime(timeStart);
m_pCoreIGC->SetStartTime(timeStart);
}
break;
case FM_S_SHIP_STATUS:
{
if (IsWaitingForGameRestart())
break;
CASTPFM(pfmShipStatus, S, SHIP_STATUS, pfm);
PlayerInfo* pPlayerInfo = FindPlayer(pfmShipStatus->shipID);
if (pPlayerInfo && m_pMissionInfo)
{
if ((pfmShipStatus->status.GetSectorID() != NA) &&
(pfmShipStatus->status.GetSectorID() != pPlayerInfo->LastSeenSector()))
{
ShipWarped(pPlayerInfo->GetShip(),
pPlayerInfo->LastSeenSector(),
pfmShipStatus->status.GetSectorID());
}
pPlayerInfo->SetShipStatus(pfmShipStatus->status);
m_pMissionInfo->GetSideInfo(pPlayerInfo->SideID())->GetMembers().GetSink()();
m_pClientEventSource->OnShipStatusChange(pPlayerInfo);
if ((pfmShipStatus->status.GetState() == c_ssTurret) !=
(pPlayerInfo->LastSeenState() == c_ssTurret))
{
m_pClientEventSource->OnTurretStateChanging(pfmShipStatus->status.GetState() == c_ssTurret);
}
}
break;
}
case FM_S_KILL_SHIP:
{
CASTPFM(pfmKillShip, S, KILL_SHIP, pfm);
PlayerInfo* pPlayerInfo = FindPlayer(pfmKillShip->shipID);
ZAssert(pPlayerInfo);
ImodelIGC* pmodelKiller = m_pCoreIGC->GetModel(pfmKillShip->typeCredit, pfmKillShip->idCredit);
PlayerInfo* pLauncherInfo = ((pfmKillShip->typeCredit == OT_ship) && pmodelKiller)
? (PlayerInfo*)(((IshipIGC*)pmodelKiller)->GetPrivateData())
: NULL;
IsideIGC* pside = GetSide();
SideID sideID = pside->GetObjectID();
ShipID shipID = GetShipID();
IshipIGC* pship = pPlayerInfo->GetShip();
assert (pship);
TargetKilled(pship);
if (pfmKillShip->bDeathCredit)
{
pPlayerInfo->AddDeath();
pPlayerInfo->GetShip()->SetExperience(0.0f);
}
else
pPlayerInfo->AddEjection();
MyMission()->GetSideInfo(pPlayerInfo->SideID())->GetMembers().GetSink()();
const char* pszVictim = pPlayerInfo->CharacterName();
bool bConstructorOrMiner;
{
PilotType pt = pship->GetPilotType();
bConstructorOrMiner = (pt == c_ptBuilder) ||
(pt == c_ptMiner) ||
(pt == c_ptCarrier);
}
if (!pLauncherInfo)
{
if (pfmKillShip->bKillCredit)
{
assert (pfmKillShip->typeCredit != NA);
IsideIGC* pside = pmodelKiller ? pmodelKiller->GetSide() : m_pCoreIGC->GetSide(pfmKillShip->sideidKiller);
assert (pside);
pside->AddKill();
}
if (pfmKillShip->shipID == shipID)
PostText(true, pfmKillShip->bDeathCredit ? "You were killed" : "You ejected");
else if (bConstructorOrMiner)
PostText(pPlayerInfo->SideID() == GetSideID(), START_COLOR_STRING "%s" END_COLOR_STRING " was killed", (PCC) ConvertColorToString (m_pCoreIGC->GetSide(pPlayerInfo->SideID())->GetColor ()), pszVictim);
else
PostText(false, pfmKillShip->bDeathCredit ? START_COLOR_STRING "%s" END_COLOR_STRING " was killed" : START_COLOR_STRING "%s" END_COLOR_STRING " ejected", (PCC) ConvertColorToString (m_pCoreIGC->GetSide(pPlayerInfo->SideID())->GetColor ()), pszVictim);
}
else
{
const char* pszLauncher = pLauncherInfo->CharacterName();
if (pfmKillShip->bKillCredit)
{
pLauncherInfo->AddKill();
if (pLauncherInfo->GetShip()->GetSide() != pship->GetSide())
pLauncherInfo->GetShip()->AddExperience();
}
MyMission()->GetSideInfo(pLauncherInfo->SideID())->GetMembers().GetSink()();
if (pfmKillShip->shipID == shipID)
PostText(true,
pfmKillShip->bDeathCredit
? "You were killed by " START_COLOR_STRING "%s" END_COLOR_STRING
: "You were forced to eject by " START_COLOR_STRING "%s" END_COLOR_STRING,
(PCC) ConvertColorToString (pLauncherInfo->GetShip()->GetSide()->GetColor ()), pszLauncher);
else if (pmodelKiller == m_ship)
PostText(true,
pfmKillShip->bDeathCredit
? "You killed " START_COLOR_STRING "%s" END_COLOR_STRING
: "You forced " START_COLOR_STRING "%s" END_COLOR_STRING " to eject",
(PCC) ConvertColorToString (pPlayerInfo->GetShip()->GetSide()->GetColor ()), pszVictim);
else
{
if (bConstructorOrMiner && pPlayerInfo->SideID() != GetSideID())
PostText(bConstructorOrMiner,
pfmKillShip->bDeathCredit
? (START_COLOR_STRING "%s %s" END_COLOR_STRING " was killed by %s")
: (START_COLOR_STRING "%s %s" END_COLOR_STRING " was forced to eject by %s"),
(PCC) ConvertColorToString (pPlayerInfo->GetShip()->GetSide()->GetColor ()),
pPlayerInfo->GetShip()->GetSide()->GetName(),
pszVictim, pszLauncher);
else
PostText(bConstructorOrMiner,
pfmKillShip->bDeathCredit
? "%s was killed by %s"
: "%s was forced to eject by %s", pszVictim, pszLauncher);
}
}
IclusterIGC * pCluster = pship->GetCluster();
if (NULL != pCluster)
{
IhullTypeIGC* pht = pship->GetBaseHullType();
if (pht)
pCluster->GetClusterSite()->AddExplosion(pship,
pht->HasCapability(c_habmFighter)
? c_etSmallShip
: c_etBigShip);
}
if (!pPlayerInfo->IsHuman())
{
if (sideID == pPlayerInfo->SideID())
{
SoundID destroyedSound;
switch (pship->GetPilotType())
{
case c_ptCarrier: destroyedSound = carrierDestroyedSound;
break;
case c_ptMiner:
destroyedSound = minerDestroyedSound;
break;
case c_ptBuilder:
destroyedSound =
((IstationTypeIGC*)(IbaseIGC*)(pship->GetBaseData()))
->GetConstructorDestroyedSound();
break;
case c_ptLayer:
if (pship->GetBaseData()->GetObjectType() == OT_mineType)
destroyedSound = minefieldLayerDestroyedSound;
else
destroyedSound = towerLayerDestroyedSound;
break;
default:
assert(false);
case c_ptWingman:
destroyedSound = towerLayerDestroyedSound;
break;
}
PlaySoundEffect(destroyedSound);
}
}
else if ((pship == m_ship) && pfmKillShip->bDeathCredit)
{
EjectPlayer(m_pCoreIGC->GetModel(pfmKillShip->typeCredit, pfmKillShip->idCredit));
}
ChangeGameState();
}
break;
case FM_S_JOIN_SIDE:
{
CASTPFM(pfmJoinSide, S, JOIN_SIDE, pfm);
PlayerInfo* pplayer = FindPlayer(pfmJoinSide->shipID);
AddPlayerToSide(pplayer, pfmJoinSide->sideID);
}
break;
case FM_CS_SET_TEAM_LEADER:
{
CASTPFM(pfmSetTeamLeader, CS, SET_TEAM_LEADER, pfm);
PlayerInfo* pplayer = FindPlayer(pfmSetTeamLeader->shipID);
if (MyMission()->SideLeaderShipID(pplayer->SideID()) != NA)
{
PlayerInfo* pplayerOld = FindPlayer(MyMission()->SideLeaderShipID(pplayer->SideID()));
pplayerOld->SetTeamLeader(false);
pplayerOld->SetMissionOwner(false);
m_pClientEventSource->OnPlayerStatusChange(MyMission(), pplayerOld->SideID(), pplayerOld);
}
pplayer->SetTeamLeader(true);
pplayer->SetMissionOwner(MyMission()->MissionOwnerSideID() == pplayer->SideID());
MyMission()->SetSideLeader(pplayer);
if ((m_pCoreIGC->GetMissionStage() == STAGE_STARTED) &&
pplayer->SideID() == MyPlayerInfo()->SideID())
{
if (pplayer == MyPlayerInfo())
PostText(true, "You have become the team leader");
else
{
char bfr[100];
sprintf(bfr, "%s has become the team leader", pplayer->CharacterName());
PostText(true, bfr);
}
}
if (pplayer == MyPlayerInfo())
PlaySoundEffect(commanderSound);
m_pClientEventSource->OnPlayerStatusChange(MyMission(), pplayer->SideID(), pplayer);
}
break;
case FM_CS_SET_MISSION_OWNER:
{
CASTPFM(pfmSetMissionOwner, CS, SET_MISSION_OWNER, pfm);
if (MyMission()->MissionOwnerSideID() != NA)
{
PlayerInfo* pplayerOld = FindPlayer(MyMission()->MissionOwnerShipID());
pplayerOld->SetMissionOwner(false);
m_pClientEventSource->OnPlayerStatusChange(MyMission(), pplayerOld->SideID(), pplayerOld);
}
PlayerInfo* pplayer = FindPlayer(pfmSetMissionOwner->shipID);
ZAssert(pplayer->IsTeamLeader());
pplayer->SetMissionOwner(true);
MyMission()->SetSideLeader(pplayer);
m_pClientEventSource->OnPlayerStatusChange(MyMission(), pplayer->SideID(), pplayer);
}
break;
case FM_CS_QUIT_SIDE:
{
if (m_pMissionInfo)
{
CASTPFM(pfmQuitSide, CS, QUIT_SIDE, pfm);
PlayerInfo* pplayer = FindPlayer(pfmQuitSide->shipID);
RemovePlayerFromSide(pplayer, pfmQuitSide->reason, FM_VAR_REF(pfmQuitSide, szMessageParam));
}
}
break;
case FM_S_SQUAD_INFO:
case FM_S_SQUAD_DETAILS:
case FM_S_SQUAD_DETAILS_PLAYER:
case FM_S_SQUAD_LOG_INFO:
case FM_S_SQUAD_DELETED:
case FM_S_SQUAD_TEXT_MESSAGE:
case FM_S_SQUAD_CREATE_ACK:
{
ForwardSquadMessage(pfm); }
break;
case FM_S_CHARACTER_INFO_GENERAL:
case FM_S_CHARACTER_INFO_BY_CIV:
case FM_S_CHARACTER_INFO_MEDAL:
{
ForwardCharInfoMessage(pfm); }
break;
case FM_S_SQUAD_INFO_DUDEX:
{
ForwardSquadMessage(pfm);
ForwardCharInfoMessage(pfm);
}
break;
case FM_S_LEADER_BOARD_QUERY_FAIL:
case FM_S_LEADER_BOARD_LIST:
{
ForwardLeaderBoardMessage(pfm); }
break;
case FM_S_ENTER_GAME:
{
ClearLoadout ();
OnEnterGame();
}
break;
case FM_S_GAME_OVER:
{
m_bInGame = false;
m_bWaitingForGameRestart = true;
m_strBriefingText.SetEmpty();
m_bGenerateCivBriefing = false;
CASTPFM(pfmGameOver, S, GAME_OVER, pfm);
if (IsLockedDown())
EndLockDown(lockdownDonating | lockdownLoadout | lockdownTeleporting);
SetViewCluster(NULL);
GetShip()->SetCluster(NULL);
for (PlayerLink* ppl = GetPlayerList()->first();
(ppl != NULL);
ppl = ppl->next())
{
ppl->data().Reset(true);
}
for (SideID sid = 0; sid < MyMission()->NumSides(); sid++)
{
MyMission()->SetSideActive(sid, true);
GetCore()->GetSide(sid)->SetActiveF(true);
MyMission()->SetSideForceReady(sid, false);
MyMission()->SetSideReady(sid, true);
}
m_listBallots.SetEmpty();
for (SideLinkIGC* psl = GetCore()->GetSides()->first(); (psl != NULL); psl = psl->next())
psl->data()->Reset();
GetCore()->ResetMission();
}
break;
case FM_S_GAME_OVER_PLAYERS:
{
CASTPFM(pfmGameOverPlayers, S, GAME_OVER_PLAYERS, pfm);
int cPlayerEndgameInfo = pfmGameOverPlayers->cbrgPlayerInfo / sizeof(PlayerEndgameInfo);
PlayerEndgameInfo* vPlayerEndgameInfo
= (PlayerEndgameInfo*)FM_VAR_REF(pfmGameOverPlayers, rgPlayerInfo);
for (int i = 0; i < cPlayerEndgameInfo; i++)
{
PlayerInfo* pplayer = FindPlayer(vPlayerEndgameInfo[i].characterName);
if (pplayer)
pplayer->UpdateScore(vPlayerEndgameInfo[i].stats);
}
}
break;
case FM_S_GAIN_FLAG:
{
if (IsWaitingForGameRestart())
break;
CASTPFM(pfmGain, S, GAIN_FLAG, pfm);
IshipIGC* pship = m_pCoreIGC->GetShip(pfmGain->shipidRecipient);
assert (pship);
if (pfmGain->bIsTreasureDocked) {
if (pship->GetSide() != GetSide()) break;
IpartTypeIGC *ppartType = GetCore()->GetPartType(pfmGain->parttypeidDocked);
if (ppartType)
PostText(true, "%s has secured %s",
pship->GetName(),
ppartType->GetName()
);
}
else
{ assert ((pship->GetFlag() == NA) || (pfmGain->sideidFlag == NA));
pship->SetFlag(pfmGain->sideidFlag);
if (pfmGain->sideidFlag != NA)
{
if (pship->GetSide() == GetSide())
{
if (pfmGain->sideidFlag != SIDE_TEAMLOBBY)
{
PostText(true, "%s has stolen " START_COLOR_STRING "%s's" END_COLOR_STRING " flag.",
pship->GetName(),
(PCC) ConvertColorToString (GetCore()->GetSide(pfmGain->sideidFlag)->GetColor ()),
GetCore()->GetSide(pfmGain->sideidFlag)->GetName()
);
PlaySoundEffect(enemyFlagLostSound);
}
else
{
PostText(true, "%s has found an artifact.",
pship->GetName());
PlaySoundEffect(artifactFoundSound);
}
}
else if (pfmGain->sideidFlag > 0 && pfmGain->sideidFlag == GetSideID())
{
ZString color = ConvertColorToString (pship->GetSide()->GetColor ());
PostText(true, START_COLOR_STRING "%s" END_COLOR_STRING " of " START_COLOR_STRING "%s" END_COLOR_STRING " has stolen our flag.",
(PCC) color,
pship->GetName(),
(PCC) color,
pship->GetSide()->GetName()
);
PlaySoundEffect(flagLostSound);
}
}
} }
break;
case FM_S_BUY_LOADOUT_ACK:
{
CASTPFM(pfmBuyLoadoutAck, S, BUY_LOADOUT_ACK, pfm);
if (!pfmBuyLoadoutAck->fLaunch && IsLockedDown())
EndLockDown(lockdownLoadout);
m_ship->ProcessShipLoadout(pfmBuyLoadoutAck->cbloadout, (const ShipLoadout*)(FM_VAR_REF(pfmBuyLoadoutAck, loadout)), true);
SaveLoadout();
m_pClientEventSource->OnPurchaseCompleted(pfmBuyLoadoutAck->fBoughtEverything);
if (m_sidBoardAfterDisembark != NA)
{
IshipIGC* pshipNewParent = FindPlayer(m_sidBoardAfterDisembark)->GetShip();
if (pshipNewParent)
{
BoardShip(pshipNewParent);
}
m_sidBoardAfterDisembark = NA;
}
else if (m_sidTeleportAfterDisembark != NA)
{
IstationIGC* pstation = GetCore()->GetStation(m_sidTeleportAfterDisembark);
if (pstation != GetShip()->GetStation())
{
SetMessageType(BaseClient::c_mtGuaranteed);
BEGIN_PFM_CREATE(m_fm, pfmDocked, C, DOCKED)
END_PFM_CREATE
pfmDocked->stationID = m_sidTeleportAfterDisembark;
StartLockDown("Teleporting to " + ZString(pstation->GetName()) + "....", lockdownTeleporting);
}
m_sidTeleportAfterDisembark = NA;
}
}
break;
case FM_S_OBJECT_SPOTTED:
{
if (!IsInGame())
break;
CASTPFM(pfmObjectSpotted, S, OBJECT_SPOTTED, pfm);
ZString strSpotterName;
switch (pfmObjectSpotted->otSpotter)
{
case OT_station:
strSpotterName = ZString("Your ")
+ GetCore()->GetStation(pfmObjectSpotted->oidSpotter)->GetName()
+ " has";
break;
case OT_probe:
strSpotterName = "One of your team's probes has";
break;
case OT_ship:
if (pfmObjectSpotted->oidSpotter == GetShipID())
strSpotterName = "You've";
else
strSpotterName = GetCore()->GetShip(pfmObjectSpotted->oidSpotter)->GetName() + ZString(" has");
break;
default:
assert(false);
strSpotterName = "<bug> has";
break;
}
switch (pfmObjectSpotted->otObject)
{
case OT_station:
{
IstationIGC* pstation = GetCore()->GetStation(pfmObjectSpotted->oidObject);
assert(pstation);
PostText(GetShip()->GetWingID() == 0, strSpotterName + " discovered an enemy " + pstation->GetName() + " in sector " + pstation->GetCluster()->GetName());
}
break;
case OT_asteroid:
{
IasteroidIGC* pasteroid = GetCore()->GetAsteroid(pfmObjectSpotted->oidObject);
assert(pasteroid);
PostText(GetShip()->GetWingID() == 0, strSpotterName + " discovered a " + IasteroidIGC::GetTypeName(pasteroid->GetCapabilities()) + " asteroid in sector " + pasteroid->GetCluster()->GetName());
}
break;
case OT_warp:
{
IwarpIGC* paleph = GetCore()->GetWarp(pfmObjectSpotted->oidObject);
assert(paleph);
PostText(GetShip()->GetWingID() == 0, strSpotterName + " discovered an aleph from sector " + paleph->GetCluster()->GetName() + " to sector " + paleph->GetDestination()->GetCluster()->GetName());
}
break;
default:
assert(false);
break;
}
}
break;
case FM_S_DEV_COMPLETED:
{
CASTPFM(pfmDevelopmentCompleted, S, DEV_COMPLETED, pfm);
IdevelopmentIGC* pdevelopment = GetCore()->GetDevelopment(pfmDevelopmentCompleted->devId);
assert(pdevelopment);
PostText(true, "%s research completed", pdevelopment->GetName());
PlaySoundEffect(pdevelopment->GetCompletionSound());
}
break;
case FM_S_SET_BRIEFING_TEXT:
{
CASTPFM(pfmSetBriefingText, S, SET_BRIEFING_TEXT, pfm);
m_strBriefingText = FM_VAR_REF(pfmSetBriefingText, text);
m_bGenerateCivBriefing = pfmSetBriefingText->fGenerateCivBriefing;
}
break;
case FM_LS_SQUAD_MEMBERSHIPS:
{
CASTPFM(pfmSquadMemberships, LS, SQUAD_MEMBERSHIPS, pfm);
SquadMembership* vSquadMemberships
= (SquadMembership*)FM_VAR_REF(pfmSquadMemberships, squadMemberships);
m_squadmemberships.SetEmpty();
for (int iSquad = 0; iSquad < pfmSquadMemberships->cSquadMemberships; iSquad++)
{
m_squadmemberships.PushEnd(vSquadMemberships[iSquad]);
}
SaveSquadMemberships(m_szCharName);
m_mapMissions.GetSink()();
}
break;
case FM_S_STATIC_MAP_INFO:
{
CASTPFM(pfmStaticMapInfo, S, STATIC_MAP_INFO, pfm);
if (m_vStaticMapInfo)
delete [] m_vStaticMapInfo;
m_cStaticMapInfo = pfmStaticMapInfo->cbmaps / sizeof(StaticMapInfo);
if (m_cStaticMapInfo > 0)
{
m_vStaticMapInfo = new StaticMapInfo[m_cStaticMapInfo];
memcpy(m_vStaticMapInfo, FM_VAR_REF(pfmStaticMapInfo, maps), m_cStaticMapInfo * sizeof(StaticMapInfo));
}
else
m_vStaticMapInfo = NULL;
}
break;
case FM_S_RANK_INFO:
{
CASTPFM(pfmRankInfo, S, RANK_INFO, pfm);
if (m_vRankInfo)
delete [] m_vRankInfo;
m_cRankInfo = pfmRankInfo->cRanks;
m_vRankInfo = new RankInfo[m_cRankInfo];
memcpy(m_vRankInfo, FM_VAR_REF(pfmRankInfo, ranks), m_cRankInfo * sizeof(RankInfo));
}
break;
case FM_S_CLUB_RANK_INFO:
{
CASTPFM(pfmRankInfo, S, CLUB_RANK_INFO, pfm);
if (m_vRankInfo)
delete [] m_vRankInfo;
m_cRankInfo = pfmRankInfo->cRanks;
m_vRankInfo = new RankInfo[m_cRankInfo];
memcpy(m_vRankInfo, FM_VAR_REF(pfmRankInfo, ranks), m_cRankInfo * sizeof(RankInfo));
}
break;
case FM_L_AUTO_UPDATE_INFO:
{
if (m_pAutoDownload == NULL)
m_pAutoDownload = CreateAutoDownload();
IAutoUpdateSink * pAutoUpdateSink = OnBeginAutoUpdate(NULL, true);
assert(pAutoUpdateSink);
CASTPFM(pfmServerInfo, L, AUTO_UPDATE_INFO, pfm);
m_pAutoDownload->SetFTPSite(FM_VAR_REF(pfmServerInfo, FTPSite),
FM_VAR_REF(pfmServerInfo, FTPInitialDirectory),
FM_VAR_REF(pfmServerInfo, FTPAccount),
FM_VAR_REF(pfmServerInfo, FTPPassword));
m_pAutoDownload->SetOfficialFileListAttributes(pfmServerInfo->crcFileList,
pfmServerInfo->nFileListSize);
DisconnectLobby();
m_pAutoDownload->SetArtPath(GetArtPath());
m_pAutoDownload->BeginUpdate(pAutoUpdateSink, ShouldCheckFiles(), false);
}
break;
case FM_L_CREATE_MISSION_ACK:
{
CASTPFM(pfmCreateMissionAck, L, CREATE_MISSION_ACK, pfm);
m_dwCookieToJoin = pfmCreateMissionAck->dwCookie;
m_strPasswordToJoin[0] = '\0';
}
break;
case FM_LS_LOBBYMISSIONINFO:
{
if (!LoggedOnToLobby())
break;
CASTPFM(pfmLobbyMissionInfo, LS, LOBBYMISSIONINFO, pfm);
pfmLobbyMissionInfo->dwStartTime += m_lobbyServerOffset;
if (now - Time(pfmLobbyMissionInfo->dwStartTime) < 0 && !pfmLobbyMissionInfo->fCountdownStarted)
pfmLobbyMissionInfo->dwStartTime = now.clock();
MissionInfo * pMissionInfo = GetLobbyMission(pfmLobbyMissionInfo->dwCookie);
assert(pMissionInfo);
pMissionInfo->Update(pfmLobbyMissionInfo);
m_mapMissions.GetSink()();
m_pClientEventSource->OnAddMission(pMissionInfo);
break;
}
case FM_L_JOIN_MISSION:
{
CASTPFM(pfmJoinMission, L, JOIN_MISSION, pfm);
if (m_dwCookieToJoin = pfmJoinMission->dwCookie) {
m_ci.strServer = pfmJoinMission->szServer;
m_ci.dwPort = pfmJoinMission->dwPort; m_ci.guidSession = GUID_NULL;
ConnectToServer(m_ci, pfmJoinMission->dwCookie, now, m_strPasswordToJoin, false);
}
else
{
OnLogonAck(false, false, "<bug>: Received a spurious join request.");
}
break;
}
case FM_L_CREATE_MISSION_NACK:
{
OnLogonAck(false, false, "There are no available servers on which to create a game.");
}
break;
case FM_L_JOIN_GAME_NACK:
{
OnLogonAck(false, false, "There is no more room on this server.");
}
break;
case FM_LS_MISSION_GONE:
{
CASTPFM(pfmMissionGone, LS, MISSION_GONE, pfm);
MissionInfo * pMission = GetLobbyMission(pfmMissionGone->dwCookie);
if (m_pMissionInfo != NULL && pMission->GetCookie() == MyMission()->GetCookie())
{
if (GetSideID() != NA)
{
if (GetSideID() != SIDE_TEAMLOBBY)
RemovePlayerFromSide(m_pPlayerInfo, QSR_Quit);
RemovePlayerFromMission(m_pPlayerInfo, QSR_Quit);
}
else
{
delete m_pMissionInfo;
m_pMissionInfo = NULL;
}
}
m_pClientEventSource->OnDelMission(pMission);
m_mapMissions.Remove(pfmMissionGone->dwCookie);
delete pMission;
}
break;
case FM_L_LOGON_ACK:
{
CASTPFM(pfmLogonAck, L, LOGON_ACK, pfm);
m_fLoggedOnToLobby = true;
m_lobbyServerOffset = pfmLogonAck->dwTimeOffset;
OnLogonLobbyAck(true, false, NULL);
}
break;
case FM_L_LOGON_NACK:
{
CASTPFM(pfmLogonNack, L, LOGON_NACK, pfm);
OnLogonLobbyAck(false, pfmLogonNack->fRetry, FM_VAR_REF(pfmLogonNack, Reason));
assert(m_fLoggedOnToLobby == false);
m_szLobbyCharName[0] = '\0';
}
break;
case FM_S_LOGON_CLUB_ACK:
{
CASTPFM(pfmLogonAck, S, LOGON_CLUB_ACK, pfm);
SetZoneClubID(pfmLogonAck->nMemberID);
m_fLoggedOnToClub = true;
OnLogonClubAck(true, false, NULL);
}
break;
case FM_S_LOGON_CLUB_NACK:
{
CASTPFM(pfmLogonNack, S, LOGON_CLUB_NACK, pfm);
OnLogonClubAck(false, pfmLogonNack->fRetry, FM_VAR_REF(pfmLogonNack, Reason));
assert(m_fLoggedOnToClub == false);
m_szClubCharName[0] = '\0';
}
break;
case FM_L_FOUND_PLAYER:
{
CASTPFM(pfmFoundPlayer, L, FOUND_PLAYER, pfm);
MissionInfo* pMissionInfo;
if (pfmFoundPlayer->dwCookie == NA)
pMissionInfo = NULL;
else
pMissionInfo = GetLobbyMission(pfmFoundPlayer->dwCookie);
m_pClientEventSource->OnFoundPlayer(pMissionInfo);
}
break;
case FM_L_SERVERS_LIST:
{
CASTPFM(pfmServerList, L, SERVERS_LIST, pfm);
m_pClientEventSource->OnServersList(
pfmServerList->cCores,
FM_VAR_REF(pfmServerList,Cores),
pfmServerList->cServers,
FM_VAR_REF(pfmServerList,Servers)
);
}
break;
default:
{
hr = S_FALSE;
}
}
return (hr);
}