#include "pch.h"
CFSShip * CFSShip::m_rgpfsShip[c_cShipsMax] = {0};
short CFSShip::m_shipidNext = 0;
int CFSShip::m_cShips = 0;
int CFSPlayer::m_latencyMax = 0;
int CFSPlayer::m_latencyTotal = 0;
int CFSPlayer::m_cUpdates = 0;
char CFSDrone::m_rgfsDrone[c_cDronesMax * sizeof(CFSDrone)];
int CFSDrone::m_ifsdNext = 0;
int CFSDrone::m_cDrones = 0;
CFSShip::CFSShip(TRef<IshipIGC> pShip, bool fIsPlayer)
:
m_plrscore(fIsPlayer)
{
assert(pShip);
assert(m_cShips < c_cShipsMax);
ImissionIGC* pmission = pShip->GetMission();
m_pfsMission = (CFSMission *)(pmission->GetPrivateData());
while (m_rgpfsShip[m_shipidNext]) {
m_shipidNext++;
if (m_shipidNext == c_cShipsMax - 1)
m_shipidNext = 0;
}
pShip->SetObjectID(m_shipidNext);
m_pShip = pShip;
m_fIsPlayer = fIsPlayer;
m_money = 0;
m_rgpfsShip[m_shipidNext] = this;
m_pShip->SetPrivateData((DWORD) this);
m_bHasUpdate = false;
m_warpState = warpReady;
debugf("New ship (%s): Name=%s, ShipID=%d, PilotType=%d\n", fIsPlayer ? "player" : "drone",
pShip->GetName(), pShip->GetObjectID(), pShip->GetPilotType());
}
CFSShip::~CFSShip()
{
debugf("Destroying %s, id=%d\n", GetName(), GetShipID());
AnnounceExit(NULL, SDR_LOGGEDOFF);
m_cShips--;
m_rgpfsShip[GetShipID()] = NULL;
m_pShip->Terminate();
}
void CFSShip::HitWarp(IwarpIGC * pwarp)
{
if (m_warpState == warpReady)
{
if (IsPlayer())
{
m_warpState = warpNoUpdate;
}
IwarpIGC * pwarpDest = pwarp->GetDestination();
assert (pwarpDest);
IclusterIGC * pclusterDest = pwarpDest->GetCluster();
ShipStatusWarped(pwarp);
Orientation alephOrientation = pwarpDest->GetOrientation();
const Vector& v = m_pShip->GetVelocity();
float speed2 = v.LengthSquared();
float speed = float(sqrt(speed2));
if (speed2 > 0)
{
float error;
{
Vector dp = pwarp->GetPosition() - m_pShip->GetPosition();
float t = (dp * v) / speed2;
float d = (dp - t * v).LengthSquared();
float r = pwarp->GetRadius();
error = (d / (r*r)) + 0.125f; if(m_pShip->GetMass() > 300.0f)
{
error = error * (300.0f / m_pShip->GetMass()); }
}
alephOrientation.Pitch(random(-error, error));
alephOrientation.Yaw(random(-error, error));
m_pShip->SetCurrentTurnRate(c_axisRoll,
m_pShip->GetCurrentTurnRate(c_axisRoll) +
random(pi * 0.5f * error, pi * 1.5f * error)); }
m_pShip->SetOrientation(alephOrientation);
const Vector& backward = alephOrientation.GetBackward();
speed = -(speed + pwarp->GetMission()->GetFloatConstant(c_fcidExitWarpSpeed));
m_pShip->SetVelocity(backward * speed);
m_pShip->SetPosition(pwarpDest->GetPosition() +
(alephOrientation.GetUp() * random(2.0f, 5.0f)) +
(alephOrientation.GetRight() * random(2.0f, 5.0f)) -
(m_pShip->GetRadius() + 5.0f) * backward);
GetIGCShip()->SetCluster(pclusterDest);
}
}
void CFSShip::SetSide(CFSMission * pfsMission, IsideIGC * pside)
{
assert (IMPLIES(pfsMission, !m_pfsMission) || pfsMission == m_pfsMission);
assert (IMPLIES(pside, pfsMission));
m_pfsMission = pfsMission;
GetIGCShip()->SetMission(m_pfsMission ? m_pfsMission->GetIGCMission() : g.trekCore);
GetIGCShip()->SetSide(pside);
if (pside && (pside->GetObjectID() >= 0))
{
GetIGCShip()->SetBaseHullType(pside->GetCivilization()->GetLifepod());
}
}
void CFSShip::Reset(bool bFull)
{
GetIGCShip()->Reset(bFull);
ShipStatusExit();
}
void CFSShip::Launch(IstationIGC* pstation)
{
assert (pstation);
assert (m_pShip->GetBaseHullType());
pstation->Launch(m_pShip);
ShipStatusLaunched();
}
void CFSShip::AnnounceExit(IclusterIGC* pclusterOld, ShipDeleteReason sdr)
{
if ((SDR_DOCKED == sdr || SDR_LEFTSECTOR == sdr) && (m_pShip->GetParentShip() != NULL))
return;
BEGIN_PFM_CREATE(g.fm, pfmShipDelete, S, SHIP_DELETE)
END_PFM_CREATE
pfmShipDelete->shipID = GetShipID();
pfmShipDelete->sdr = sdr;
CFMRecipient * prcp = NULL;
if (SDR_DOCKED == sdr || SDR_LEFTSECTOR == sdr)
{
assert (pclusterOld);
prcp = GetGroupSectorFlying(pclusterOld);
}
else
{
ImissionIGC* pm = GetIGCShip()->GetMission();
if (pm && pm->GetPrivateData())
{
CFSMission * pfsMission = (CFSMission *)(pm->GetPrivateData());
prcp = pfsMission->GetGroupMission();
}
}
if (prcp)
g.fm.SendMessages(prcp, FM_GUARANTEED, FM_FLUSH);
else
g.fm.PurgeOutBox();
}
void CFSPlayer::ForceLoadoutChange(void)
{
assert(0 == g.fm.CbUsedSpaceInOutbox());
QueueLoadoutChange(true);
g.fm.SendMessages(GetPlayer()->GetConnection(), FM_GUARANTEED, FM_FLUSH);
}
void CFSShip::ShipStatusSpotted(IsideIGC* pside)
{
SideID sideID = pside->GetObjectID();
SectorID sectorID;
{
IclusterIGC* pcluster = GetIGCShip()->GetCluster();
if (pcluster == NULL)
{
IstationIGC* pstation = GetIGCShip()->GetStation();
assert (pstation);
pcluster = pstation->GetCluster();
}
sectorID = pcluster->GetObjectID();
}
ShipStatus* pss = &m_rgShipStatus[sideID];
pss->SetState(c_ssFlying);
pss->SetParentID(NA);
pss->SetHullID(GetIGCShip()->GetHullType()->GetObjectID());
pss->SetSectorID(sectorID);
IsideIGC* mySide = GetSide();
SideID mySideID = mySide->GetObjectID();
if (mySide != pside)
m_rgShipStatus[mySideID].SetDetected(true);
{
for (ShipLinkIGC* psl = GetIGCShip()->GetChildShips()->first();
(psl != NULL);
psl = psl->next())
{
IshipIGC* pship = psl->data();
CFSShip* pfsship = ((CFSShip*)(pship->GetPrivateData()));
ShipStatus* pss = pfsship->GetShipStatus(sideID);
pss->SetState((pship->GetTurretID() == NA) ? c_ssObserver : c_ssTurret);
pss->SetHullID(NA);
pss->SetSectorID(sectorID);
pss->SetParentID(GetShipID());
if (mySide != pside)
pfsship->GetShipStatus(mySideID)->SetDetected(true);
}
}
}
void CFSShip::ShipStatusHidden(IsideIGC* pside)
{
SideID sideID = pside->GetObjectID();
m_rgShipStatus[sideID].SetUnknown();
IsideIGC* mySide = GetSide();
SideID mySideID = mySide->GetObjectID();
bool detectedF = false;
{
CFSMission* pmission = this->GetMission();
if (pmission)
{
for (SideLinkIGC* psl = pmission->GetIGCMission()->GetSides()->first();
(psl != NULL);
psl = psl->next())
{
if (psl->data() != mySide)
{
ShipStatus* pss = GetShipStatus(psl->data()->GetObjectID());
if (!pss->GetUnknown())
{
detectedF = true;
break;
}
}
}
}
}
m_rgShipStatus[mySideID].SetDetected(detectedF);
{
for (ShipLinkIGC* psl = GetIGCShip()->GetChildShips()->first();
(psl != NULL);
psl = psl->next())
{
IshipIGC* pship = psl->data();
CFSShip* pfsShip = ((CFSShip*)(pship->GetPrivateData()));
ShipStatus* pss = pfsShip->GetShipStatus(sideID);
pss->SetUnknown();
pfsShip->GetShipStatus(mySideID)->SetDetected(detectedF);
}
}
}
void CFSShip::ShipStatusHullChange(IhullTypeIGC* pht)
{
IsideIGC* psideMe = GetIGCShip()->GetSide();
HullID hid = pht->GetObjectID();
for (SideLinkIGC* psl = GetMission()->GetIGCMission()->GetSides()->first();
(psl != NULL);
psl = psl->next())
{
IsideIGC* pside = psl->data();
if ((psideMe == pside) || GetIGCShip()->SeenBySide(pside))
{
m_rgShipStatus[pside->GetObjectID()].SetHullID(hid);
}
}
}
void CFSShip::ShipStatusDocked(IstationIGC* pstation)
{
StationID stationID = pstation->GetObjectID();
SectorID sectorID = pstation->GetCluster()->GetObjectID();
HullID hullID;
{
IhullTypeIGC* pht = GetIGCShip()->GetBaseHullType();
hullID = pht ? pht->GetObjectID() : NA;
}
IsideIGC* psideMe = GetIGCShip()->GetSide();
for (SideLinkIGC* psl = GetMission()->GetIGCMission()->GetSides()->first();
(psl != NULL);
psl = psl->next())
{
IsideIGC* pside = psl->data();
if ((pside == psideMe) ||
((GetIGCShip()->SeenBySide(pside)) && (pstation->SeenBySide(pside))))
{
SideID sideID = pside->GetObjectID();
ShipStatus* pss = &(m_rgShipStatus[sideID]);
pss->SetState(c_ssDocked);
pss->SetParentID(NA);
pss->SetStationID(stationID);
pss->SetSectorID(sectorID);
pss->SetHullID(hullID);
{
for (ShipLinkIGC* psl = GetIGCShip()->GetChildShips()->first();
(psl != NULL);
psl = psl->next())
{
IshipIGC* pship = psl->data();
ShipStatus* pss = ((CFSShip*)(pship->GetPrivateData()))->GetShipStatus(sideID);
assert ((pship->GetTurretID() == NA)
? (pss->GetState() == c_ssObserver)
: (pss->GetState() == c_ssTurret));
assert (pss->GetParentID() == GetIGCShip()->GetObjectID());
assert (pss->GetHullID() == NA);
pss->SetStationID(stationID);
pss->SetSectorID(sectorID);
}
}
}
}
}
void CFSShip::ShipStatusRecalculate(void)
{
IsideIGC* psideMe = GetIGCShip()->GetSide();
IclusterIGC* pcluster = GetIGCShip()->GetCluster();
if (pcluster)
{
for (SideLinkIGC* psl = GetMission()->GetIGCMission()->GetSides()->first();
(psl != NULL);
psl = psl->next())
{
IsideIGC* pside = psl->data();
SideID sid = pside->GetObjectID();
if ((pside == psideMe) || (m_rgShipStatus[sid].GetState() >= c_ssFlying))
ShipStatusSpotted(pside);
}
}
else
{
ShipStatusSpotted(psideMe);
}
}
void CFSShip::ShipStatusLaunched(void)
{
SideID sideID = GetIGCShip()->GetSide()->GetObjectID();
m_rgShipStatus[sideID].SetState(c_ssFlying);
m_rgShipStatus[sideID].SetParentID(NA);
assert (m_rgShipStatus[sideID].GetSectorID() == GetIGCShip()->GetCluster()->GetObjectID());
}
void CFSShip::ShipStatusStart(IstationIGC* pstation)
{
SideID sideID = GetIGCShip()->GetSide()->GetObjectID();
m_rgShipStatus[sideID].SetState(pstation ? c_ssDocked : c_ssDead);
m_rgShipStatus[sideID].SetParentID(NA);
m_rgShipStatus[sideID].SetStationID(pstation ? pstation->GetObjectID() : NA);
m_rgShipStatus[sideID].SetSectorID(pstation ? pstation->GetCluster()->GetObjectID() : NA);
m_rgShipStatus[sideID].SetHullID(GetIGCShip()->GetHullType()->GetObjectID());
}
void CFSShip::ShipStatusExit(void)
{
for (SideID i = 0; (i < c_cSidesMax); i++)
{
m_rgShipStatus[i].SetState(c_ssDead);
m_rgShipStatus[i].SetParentID(NA);
m_rgShipStatus[i].SetHullID(NA);
m_rgShipStatus[i].SetSectorID(NA);
m_rgShipStatus[i].SetStationID(NA);
m_rgShipStatus[i].SetUnknown();
}
}
void CFSShip::ShipStatusRestart(IstationIGC* pstation)
{
IsideIGC* psideShip = GetIGCShip()->GetSide();
for (SideLinkIGC* psl = GetMission()->GetIGCMission()->GetSides()->first();
(psl != NULL);
psl = psl->next())
{
IsideIGC* pside = psl->data();
if ((pside == psideShip) || (GetIGCShip()->SeenBySide(pside)))
{
ShipStatus* pss = &(m_rgShipStatus[pside->GetObjectID()]);
pss->SetState(c_ssDead);
pss->SetParentID(NA);
pss->SetHullID(NA);
pss->SetSectorID(NA);
}
}
}
void CFSShip::ShipStatusWarped(IwarpIGC* pwarp)
{
SectorID sectorID = pwarp->GetDestination()->GetCluster()->GetObjectID();
for (SideLinkIGC* psl = GetMission()->GetIGCMission()->GetSides()->first();
(psl != NULL);
psl = psl->next())
{
IsideIGC* pside = psl->data();
if ((GetIGCShip()->SeenBySide(pside)) && (pwarp->SeenBySide(pside)))
{
SideID sideID = pside->GetObjectID();
m_rgShipStatus[sideID].SetSectorID(sectorID);
{
for (ShipLinkIGC* psl = GetIGCShip()->GetChildShips()->first();
(psl != NULL);
psl = psl->next())
{
IshipIGC* pship = psl->data();
ShipStatus* pss = ((CFSShip*)(pship->GetPrivateData()))->GetShipStatus(sideID);
pss->SetSectorID(sectorID);
}
}
}
}
}
void CFSShip::SetCluster(IclusterIGC * pcluster, bool bViewOnly)
{
if (pcluster)
{
IshipIGC* pshipParent = m_pShip->GetParentShip();
if ((pshipParent == NULL) && !bViewOnly)
{
QueueLoadoutChange();
BEGIN_PFM_CREATE(g.fm, pfmSSU, S, SINGLE_SHIP_UPDATE)
END_PFM_CREATE
m_pShip->ExportShipUpdate(&(pfmSSU->shipupdate));
{
ImodelIGC* pmodelTarget = m_pShip->GetCommandTarget(c_cmdCurrent);
if (pmodelTarget)
{
pfmSSU->otTarget = pmodelTarget->GetObjectType();
pfmSSU->oidTarget = pmodelTarget->GetObjectID();
}
else
{
pfmSSU->otTarget = NA;
pfmSSU->oidTarget = NA;
}
}
pfmSSU->bIsRipcording = m_pShip->fRipcordActive();
g.fm.SendMessages(GetGroupSectorFlying(pcluster), FM_GUARANTEED, FM_FLUSH);
SetDeviation(0.0f);
}
if (!IsPlayer())
{
for (Command i = 0; i < c_cmdMax; i++)
{
ImodelIGC* ptarget = m_pShip->GetCommandTarget(i);
if (ptarget && ptarget->GetObjectType() == OT_buoy
&& ((IbuoyIGC*)ptarget)->GetBuoyType() == c_buoyCluster
&& ((IbuoyIGC*)ptarget)->GetCluster() == pcluster)
{
m_pShip->SetCommand(i, NULL, c_cidNone);
}
}
}
}
}
void CFSShip::CaptureStation(IstationIGC * pstation)
{
{
pstation->SetFraction(pstation->GetFraction() * 0.5f);
pstation->SetShieldFraction(0.8f); }
{
GetPlayerScoreObject()->CaptureBase(true);
for (ShipLinkIGC* psl = GetIGCShip()->GetChildShips()->first();
(psl != NULL);
psl = psl->next())
{
CFSShip* ps = (CFSShip*)(psl->data()->GetPrivateData());
ps->GetPlayerScoreObject()->CaptureBase(false);
}
}
IsideIGC * pside = GetSide();
pside->AddBaseCapture();
SideID iSide = pside->GetObjectID();
IsideIGC* psideOld = pstation->GetSide();
StationID stationID = pstation->GetObjectID();
BEGIN_PFM_CREATE(g.fm, pfmStationCapture, S, STATION_CAPTURE)
END_PFM_CREATE
pfmStationCapture->stationID = stationID;
pfmStationCapture->sidOld = psideOld->GetObjectID();
pfmStationCapture->sidNew = iSide;
pfmStationCapture->shipIDCredit = GetIGCShip()->GetObjectID();
g.fm.SendMessages(GetMission()->GetGroupRealSides(), FM_GUARANTEED, FM_FLUSH);
pstation->SetSide(pside);
CFSMission * pfsMission = this->GetMission();
LPCSTR pszContext = pfsMission->GetIGCMission() ? pfsMission->GetIGCMission()->GetContextName() : NULL;
_AGCModule.TriggerContextEvent(NULL, EventID_StationChangesSides, pszContext,
GetName(), GetShipID(), pside->GetUniqueID(), -1, 4,
"GameID" , VT_I4 , pfsMission->GetMissionID(),
"OldTeam" , VT_I4 , psideOld->GetUniqueID(),
"OldTeamName", VT_LPSTR, psideOld->GetName(),
"StationName", VT_LPSTR, pstation->GetName());
#if 0
ZString pszPlayerList = ""; if(m_pfsMission->GetIGCMission() && m_pfsMission->GetIGCMission()->GetShips())
{
ShipLinkIGC * pShiplink = m_pfsMission->GetIGCMission()->GetShips()->first();
while (pShiplink)
{
CFSShip * pfsShip = (CFSShip *) pShiplink->data()->GetPrivateData();
if (pfsShip && pfsShip->IsPlayer())
{
if(pfsShip->GetSide() && pfsShip->GetSide()->GetObjectID() == iSide && pfsShip->GetPlayer()->GetIGCShip()->GetObjectID() == GetIGCShip()->GetObjectID() || pfsShip->GetCluster() && pstation->GetCluster() && pfsShip->GetCluster()->GetObjectID() == pstation->GetCluster()->GetObjectID()) {
pszPlayerList = pszPlayerList + ";" + ZString(pfsShip->GetPlayer()->GetName()); if(pfsShip->GetPlayer()->GetIGCShip() )
{
pszPlayerList = pszPlayerList + ":" + ZString( (pstation->GetPosition() - pfsShip->GetPlayer()->GetIGCShip()->GetPosition()).Length()); }
}
}
pShiplink = pShiplink->next();
}
}
_AGCModule.TriggerContextEvent(NULL, EventID_StationChangesSides, pszContext,
GetName(), GetShipID(), pside->GetUniqueID(), -1, 4,
"GameID" , VT_I4 , pfsMission->GetMissionID(),
"OldTeam" , VT_I4 , psideOld->GetUniqueID(),
"OldTeamName", VT_LPSTR, psideOld->GetName(),
"zPlayerList", VT_LPSTR, pszPlayerList); #endif
IsideIGC* psideWin = m_pfsMission->CheckForVictoryByStationCapture(pside, psideOld);
if (psideWin)
{
static char szReason[100]; sprintf(szReason, "%s won because %s captured %s", psideWin->GetName(), GetIGCShip()->GetName(), pstation->GetName());
m_pfsMission->GameOver(psideWin, szReason);
}
else if (psideOld->GetActiveF())
m_pfsMission->VacateStation(pstation);
}
void CFSShip::QueueLoadoutChange(bool bForce)
{
const PartListIGC* pplist = GetIGCShip()->GetParts();
const ShipListIGC* pslist = GetIGCShip()->GetChildShips();
BEGIN_PFM_CREATE(g.fm, pfmLoadoutChange, S, LOADOUT_CHANGE)
FM_VAR_PARM(NULL, GetIGCShip()->ExportShipLoadout(NULL))
FM_VAR_PARM(NULL, pslist->n() * sizeof(PassengerData))
END_PFM_CREATE
GetIGCShip()->ExportShipLoadout((ShipLoadout*)(FM_VAR_REF(pfmLoadoutChange, loadout)));
pfmLoadoutChange->sidShip = bForce ? NA : GetIGCShip()->GetObjectID();
{
PassengerData* pd = (PassengerData*)(FM_VAR_REF(pfmLoadoutChange, rgPassengers));
for (ShipLinkIGC* psl = pslist->first();
(psl != NULL);
psl = psl->next())
{
pd->shipID = psl->data()->GetObjectID();
pd->turretID = psl->data()->GetTurretID();
pd++;
}
}
}
void CFSPlayer::SetCluster(IclusterIGC* pcluster, bool bViewOnly)
{
CFSShip::SetCluster(pcluster, bViewOnly);
if (pcluster)
{
SetDPGroup((CFSCluster*)(pcluster->GetPrivateData()), true);
IshipIGC* pshipParent = GetIGCShip()->GetParentShip();
if ((pshipParent == NULL) || bViewOnly)
{
ShipID shipID = GetIGCShip()->GetObjectID();
assert(0 == g.fm.CbUsedSpaceInOutbox());
if (!bViewOnly)
{
BEGIN_PFM_CREATE(g.fm, pfmSetCluster, S, SET_CLUSTER)
END_PFM_CREATE
pfmSetCluster->sectorID = pcluster->GetObjectID();
IshipIGC* pshipSource = pshipParent ? pshipParent : GetIGCShip();
pshipSource->ExportShipUpdate(&(pfmSetCluster->shipupdate));
pfmSetCluster->cookie = NewCookie();
}
{
for (ShipLinkIGC* pshiplink = pcluster->GetShips()->first(); pshiplink; pshiplink = pshiplink->next())
{
IshipIGC * pshipExist = pshiplink->data();
if ((pshipExist != GetIGCShip()) && (pshipExist != pshipParent))
{
IshipIGC* pshipExistParent = pshipExist->GetParentShip();
if (pshipExistParent == NULL)
{
CFSShip * pfsShipExist = (CFSShip *) pshipExist->GetPrivateData();
pfsShipExist->QueueLoadoutChange();
BEGIN_PFM_CREATE(g.fm, pfmSSU, S, SINGLE_SHIP_UPDATE)
END_PFM_CREATE
pshipExist->ExportShipUpdate(&(pfmSSU->shipupdate));
{
ImodelIGC* pmodelTarget = pshipExist->GetCommandTarget(c_cmdCurrent);
if (pmodelTarget)
{
pfmSSU->otTarget = pmodelTarget->GetObjectType();
pfmSSU->oidTarget = pmodelTarget->GetObjectID();
}
else
{
pfmSSU->otTarget = NA;
pfmSSU->oidTarget = NA;
}
}
pfmSSU->bIsRipcording = pshipExist->fRipcordActive();
}
}
}
}
{
IsideIGC* pside = GetIGCShip()->GetSide();
{
const StationListIGC * pstnlist = pcluster->GetStations();
int nStations = 0;
{
for (StationLinkIGC* pstnlink = pstnlist->first(); pstnlink; pstnlink = pstnlink->next())
{
IstationIGC* pstation = pstnlink->data();
if (pstation->SeenBySide(pside))
nStations++;
}
}
if (nStations != 0)
{
BEGIN_PFM_CREATE(g.fm, pfmStationsUpdate, S, STATIONS_UPDATE)
FM_VAR_PARM(NULL, nStations * sizeof(StationState))
END_PFM_CREATE
StationState* pss = (StationState*)(FM_VAR_REF(pfmStationsUpdate, rgStationStates));
for (StationLinkIGC* pstnlink = pstnlist->first(); pstnlink; pstnlink = pstnlink->next())
{
IstationIGC * pstation = pstnlink->data();
if (pstation->SeenBySide(pside))
{
pss->stationID = pstation->GetObjectID();
pss->bpHullFraction = pstation->GetFraction();
(pss++)->bpShieldFraction = pstation->GetShieldFraction();
}
}
}
}
{
const ProbeListIGC * pprblist = pcluster->GetProbes();
int nProbes = 0;
{
for (ProbeLinkIGC* pprblink = pprblist->first(); pprblink; pprblink = pprblink->next())
{
if (pprblink->data()->SeenBySide(pside))
nProbes++;
}
}
if (nProbes != 0)
{
BEGIN_PFM_CREATE(g.fm, pfmProbesUpdate, S, PROBES_UPDATE)
FM_VAR_PARM(NULL, nProbes * sizeof(ProbeState))
END_PFM_CREATE
ProbeState* pps = (ProbeState*)(FM_VAR_REF(pfmProbesUpdate, rgProbeStates));
for (ProbeLinkIGC* pprblink = pprblist->first(); pprblink; pprblink = pprblink->next())
{
IprobeIGC * pprobe = pprblink->data();
if (pprobe->SeenBySide(pside))
{
pps->probeID = pprobe->GetObjectID();
(pps++)->bpFraction = pprobe->GetFraction();
}
}
}
}
{
const AsteroidListIGC * pastlist = pcluster->GetAsteroids();
int nAsteroids = 0;
{
for (AsteroidLinkIGC* pastlink = pastlist->first(); pastlink; pastlink = pastlink->next())
{
if (pastlink->data()->SeenBySide(pside))
nAsteroids++;
}
}
if (nAsteroids != 0)
{
BEGIN_PFM_CREATE(g.fm, pfmAsteroidsUpdate, S, ASTEROIDS_UPDATE)
FM_VAR_PARM(NULL, nAsteroids * sizeof(AsteroidState))
END_PFM_CREATE
AsteroidState* pas = (AsteroidState*)(FM_VAR_REF(pfmAsteroidsUpdate, rgAsteroidStates));
for (AsteroidLinkIGC* pastlink = pastlist->first(); pastlink; pastlink = pastlink->next())
{
IasteroidIGC * pasteroid = pastlink->data();
if (pasteroid->SeenBySide(pside))
{
pas->asteroidID = pasteroid->GetObjectID();
pas->ore = short(pasteroid->GetOre());
pas->co.Set(pasteroid->GetOrientation());
(pas++)->bpFraction = pasteroid->GetFraction();
}
}
}
}
}
{
for (ShipLinkIGC* psl = GetIGCShip()->GetChildShips()->first(); (psl != NULL); psl = psl->next())
{
CFSShip* pfsShip = (CFSShip*)(psl->data()->GetPrivateData());
assert (pfsShip->IsPlayer());
pfsShip->GetPlayer()->ResetLastUpdate();
g.fm.SendMessages(pfsShip->GetPlayer()->GetConnection(), FM_GUARANTEED, FM_DONT_FLUSH);
}
}
g.fm.SendMessages(GetConnection(), FM_GUARANTEED, FM_FLUSH);
}
}
else if (bViewOnly)
{
IstationIGC* pstation = GetIGCShip()->GetStation();
assert (pstation);
CFSCluster* pfsCluster = (CFSCluster*)(pstation->GetCluster()->GetPrivateData());
SetDPGroup(pfsCluster, false);
}
else
SetDPGroup(NULL, false);
}
CFSPlayer::CFSPlayer(CFMConnection * pcnxn, int characterID, const char * szCDKey,
TRef<IshipIGC> pShip, bool fCanCheat) :
CFSShip(pShip, true), m_fReady(true),
m_characterId(characterID),
m_fCanCheat(fCanCheat),
m_pcnxn(pcnxn),
m_pgrp(NULL),
m_ucLastUpdate(c_ucNone),
m_pfsClusterFlying(NULL),
m_pclusterLifepod(NULL),
m_bannedSideMask(0),
m_lastSide(SIDE_TEAMLOBBY),
m_chatBudget(c_chatBudgetMax),
m_strCDKey(szCDKey)
{
m_pcnxn->SetPrivateData((DWORD) this); m_dwStartTime = m_timeUpdate = g.timeNow;
ShipID shipID = pShip->GetObjectID();
LPCSTR pszContext = pShip->GetMission()->GetContextName();
_AGCModule.TriggerContextEvent(NULL, EventID_LoginServer, pszContext,
pShip->GetName(), GetConnection()->GetID(), -1, -1, 1,
"User", VT_I4, GetConnection()->GetID());
}
CFSPlayer::~CFSPlayer()
{
m_pcnxn->SetPrivateData(0); LPCSTR pszContext = GetIGCShip() ? GetIGCShip()->GetMission()->GetContextName() : NULL;
_AGCModule.TriggerContextEvent(NULL, EventID_LogoutServer, pszContext,
GetName(), GetConnection()->GetID(), -1, -1, 1,
"User", VT_I4, GetConnection()->GetID());
ShipID shipID = GetShipID();
if (NULL != g.pServerCounters)
g.pServerCounters->cPlayersOnline--;
if (GetMission())
GetMission()->RemovePlayerFromMission(this, QSR_LinkDead);
PersistPlayerScoreObjectLink * pperplrscoLink = NULL;
while (pperplrscoLink = m_perplrscoreList.first())
{
delete pperplrscoLink->data();
delete pperplrscoLink;
}
}
void CFSPlayer::Launch(IstationIGC* pstation)
{
assert (GetIGCShip()->GetBaseHullType() != NULL);
SetWarpState();
CFSShip::Launch(pstation);
}
void CFSPlayer::Dock(IstationIGC * pstation)
{
IshipIGC * pship = GetIGCShip();
CFSCluster* pfsCluster = (CFSCluster*)(pstation->GetCluster()->GetPrivateData());
SetDPGroup(pfsCluster, false);
ShipStatus* pss = GetShipStatus(pship->GetSide()->GetObjectID());
pss->SetStationID(pstation->GetObjectID());
pss->SetSectorID(pstation->GetCluster()->GetObjectID());
BEGIN_PFM_CREATE(g.fm, pfmDocked, S, DOCKED)
END_PFM_CREATE
pfmDocked->stationID = pstation->GetObjectID();
g.fm.SendMessages(GetConnection(), FM_GUARANTEED, FM_FLUSH);
}
void CFSPlayer::SetSide(CFSMission * pfsMission, IsideIGC * pside)
{
CFSMission * pfsmOld = GetMission();
IsideIGC* psideOld = GetSide();
CFSShip::SetSide(pfsMission, pside);
if (pside)
{
PlayerScoreObject* ppso = GetPlayerScoreObject();
ppso->SetPersist(GetPersistPlayerScore(pside->GetCivilization()->GetObjectID()));
memset(m_ptDesiredLoadout, 0, sizeof(m_ptDesiredLoadout));
}
if (pside != psideOld)
{
if (pfsmOld)
g.fm.DeleteConnectionFromGroup(CFSSide::FromIGC(psideOld)->GetGroup(), GetConnection());
if (pfsMission)
{
bool fLobbySide = SIDE_TEAMLOBBY == pside->GetObjectID();
CFMGroup * pgrp = CFSSide::FromIGC(pside)->GetGroup();
g.fm.AddConnectionToGroup(pgrp, GetConnection());
if (fLobbySide)
g.fm.DeleteConnectionFromGroup(pfsMission->GetGroupRealSides(), GetConnection());
else
g.fm.AddConnectionToGroup(pfsMission->GetGroupRealSides(), GetConnection());
}
}
else
assert (pfsmOld == pfsMission);
if (!pside && m_pgrp)
{
g.fm.DeleteConnectionFromGroup(m_pgrp, GetConnection());
m_pgrp = NULL;
}
if (pfsmOld != pfsMission)
{
if (pfsmOld) {
const char * szName = pfsmOld->GetIGCMission() && pfsmOld->GetIGCMission()->GetMissionParams() ? pfsmOld->GetIGCMission()->GetMissionParams()->strGameName : "?" ;
int id = pfsmOld->GetIGCMission() ? pfsmOld->GetIGCMission()->GetMissionID() : -1;
long idShip = (AGC_AdminUser << 16) | CAdminUser::DetermineID(this->GetPlayer());
LPCSTR pszContext = pfsmOld->GetIGCMission() ? pfsmOld->GetIGCMission()->GetContextName() : NULL;
_AGCModule.TriggerContextEvent(NULL, EventID_LogoutGame, pszContext,
GetName(), idShip, -1, -1, 2,
"GameID", VT_I4, id,
"GameName", VT_LPSTR, szName);
}
if (pfsMission) {
const char * szName = pfsMission->GetIGCMission() && pfsMission->GetIGCMission()->GetMissionParams() ? pfsMission->GetIGCMission()->GetMissionParams()->strGameName : "?" ;
int id = pfsMission->GetIGCMission() ? pfsMission->GetIGCMission()->GetMissionID() : -1;
long idShip = (AGC_AdminUser << 16) | CAdminUser::DetermineID(this->GetPlayer());
LPCSTR pszContext = pfsMission->GetIGCMission() ? pfsMission->GetIGCMission()->GetContextName() : NULL;
_AGCModule.TriggerContextEvent(NULL, EventID_LoginGame, pszContext,
GetName(), idShip, -1, -1, 2,
"GameID", VT_I4, id,
"GameName", VT_LPSTR, szName);
}
}
if (psideOld != pside)
{
long idShip = (AGC_AdminUser << 16) | CAdminUser::DetermineID(this->GetPlayer());
if (psideOld ) {
LPCSTR pszContext = GetIGCShip()->GetMission() ? GetIGCShip()->GetMission()->GetContextName() : NULL;
_AGCModule.TriggerContextEvent(NULL, EventID_LeaveTeam, pszContext,
GetName(), idShip, psideOld->GetUniqueID(), -1, 3, "MissionID", VT_I4 , psideOld->GetMission()->GetMissionID(), "Team" , VT_I4 , psideOld->GetObjectID(), "TeamName", VT_LPSTR, psideOld->GetName());
}
if (pside) {
_AGCModule.TriggerEvent(NULL, EventID_JoinTeam, GetName(), idShip,
pside->GetUniqueID(), -1, 3, "MissionID", VT_I4 , pfsMission->GetMissionID(), "Team" , VT_I4 , pside->GetObjectID(), "TeamName", VT_LPSTR, pside->GetName());
}
}
}
void CFSPlayer::SetShipUpdate(const ClientShipUpdate& su)
{
if (su.time > m_timeUpdate)
{
ShipUpdateStatus sus = GetIGCShip()->ProcessShipUpdate(su);
if (sus == c_susAccepted)
{
m_ucLastUpdate = c_ucShipUpdate;
m_su = su;
m_timeUpdate = su.time;
if (m_warpState == warpNoUpdate)
{
m_warpState = warpWaiting;
m_timeNextWarp = g.timeNow + 2.0f; }
else if ((m_warpState == warpWaiting) && (g.timeNow >= m_timeNextWarp))
m_warpState = warpReady;
}
else if (sus == c_susRejected)
{
BEGIN_PFM_CREATE(g.fm, pfmSR, S, SHIP_RESET)
END_PFM_CREATE
GetIGCShip()->ExportShipUpdate(&(pfmSR->shipupdate));
pfmSR->cookie = NewCookie();
g.fm.SendMessages(GetConnection(), FM_GUARANTEED, FM_FLUSH);
}
}
}
void CFSPlayer::SetActiveTurretUpdate(const ClientActiveTurretUpdate& atu)
{
if (atu.time > m_timeUpdate)
{
ShipUpdateStatus sus = GetIGCShip()->ProcessShipUpdate(atu);
if (sus == c_susAccepted)
{
m_ucLastUpdate = c_ucActiveTurretUpdate;
m_atu = atu;
m_timeUpdate = atu.time;
}
}
}
void CFSPlayer::SetInactiveTurretUpdate(void)
{
m_ucLastUpdate = c_ucInactiveTurretUpdate;
GetIGCShip()->SetStateM(0);
}
void CFSPlayer::SetDPGroup(CFSCluster* pfsCluster, bool bFlying)
{
if (m_pfsClusterFlying)
{
m_pfsClusterFlying->RemoveFlyingPlayer(this);
}
CFMGroup* pgrp;
if (pfsCluster)
{
if (bFlying)
{
pgrp = pfsCluster->GetClusterGroups()->pgrpClusterFlying;
m_pfsClusterFlying = pfsCluster;
pfsCluster->AddFlyingPlayer(this);
}
else
{
pgrp = pfsCluster->GetClusterGroups()->pgrpClusterDocked;
m_pfsClusterFlying = NULL;
}
}
else
{
pgrp = NULL;
m_pfsClusterFlying = NULL;
}
if (m_pgrp)
{
#ifdef DEBUG
debugf("Removing %s(%u) from group %s(%u)\n", GetName(), GetConnection()->GetID(),
m_pgrp->GetName(), m_pgrp->GetID());
#endif
g.fm.DeleteConnectionFromGroup(m_pgrp, GetConnection());
}
m_pgrp = pgrp;
if (m_pgrp)
g.fm.AddConnectionToGroup(m_pgrp, GetConnection());
}
bool CFSPlayer::IsMissionOwner()
{
return this == GetMission()->GetOwner();
}
void CFSPlayer::SetReady(bool fReady)
{
m_fReady = fReady;
GetMission()->PlayerReadyChange(this);
}
void CFSPlayer::SetAutoDonate(CFSPlayer* pplayer, Money amount, bool bSend)
{
assert (pplayer != this);
ShipID sidDonateBy = GetShipID();
ShipID sidDonateTo;
IshipIGC* pship;
if (pplayer)
{
pship = pplayer->GetIGCShip()->GetAutoDonate();
if (pship == NULL)
pship = pplayer->GetIGCShip();
else
{
assert (pship->GetAutoDonate() == NULL);
CFSPlayer* pplayerNew = ((CFSShip*)(pship->GetPrivateData()))->GetPlayer();
if (pplayerNew == this)
{
pplayer->SetAutoDonate(NULL, 0, false);
pship = pplayer->GetIGCShip();
}
else
{
pplayer = pplayerNew;
}
}
assert (pship->GetAutoDonate() == NULL);
assert (pplayer->GetIGCShip() == pship);
sidDonateTo = pship->GetObjectID();
if (amount != 0)
{
TrapHack(GetMoney() >= amount);
pplayer->SetMoney(amount + pplayer->GetMoney());
SetMoney(GetMoney() - amount);
}
}
else
{
pship = NULL;
sidDonateTo = NA;
}
GetIGCShip()->SetAutoDonate(pship);
BEGIN_PFM_CREATE(g.fm, pfmAD, S, AUTODONATE)
END_PFM_CREATE
pfmAD->sidDonateBy = sidDonateBy;
pfmAD->sidDonateTo = sidDonateTo;
pfmAD->amount = amount;
if (bSend)
g.fm.SendMessages(CFSSide::FromIGC(GetSide())->GetGroup(), FM_GUARANTEED, FM_FLUSH);
}
bool CFSPlayer::GetIsMemberOfSquad(SquadID squadID)
{
if (squadID == NA)
return true;
for (SquadMembershipLink* pSquadLink = GetSquadMembershipList()->first();
pSquadLink != NULL; pSquadLink = pSquadLink->next())
{
if (pSquadLink->data()->GetID() == squadID)
return true;
}
return false;
}
bool CFSPlayer::GetCanLeadSquad(SquadID squadID)
{
if (squadID == NA)
return true;
for (SquadMembershipLink* pSquadLink = GetSquadMembershipList()->first();
pSquadLink != NULL; pSquadLink = pSquadLink->next())
{
SquadMembership* psquad = pSquadLink->data();
if (psquad->GetID() == squadID)
return psquad->GetIsAssistantLeader() || psquad->GetIsLeader();
}
return false;
}
SquadID CFSPlayer::GetPreferredSquadToLead()
{
SquadMembershipLink* pSquadLink;
for (pSquadLink = GetSquadMembershipList()->first();
pSquadLink != NULL; pSquadLink = pSquadLink->next())
{
SquadMembership* psquad = pSquadLink->data();
if (psquad->GetIsLeader())
return psquad->GetID();
}
for (pSquadLink = GetSquadMembershipList()->first();
pSquadLink != NULL; pSquadLink = pSquadLink->next())
{
SquadMembership* psquad = pSquadLink->data();
if (psquad->GetIsAssistantLeader())
return psquad->GetID();
}
return NA;
}
CFSDrone::CFSDrone(IshipIGC* pship) :
CFSShip(pship, false)
{
if (GetMission()->GetStage() == STAGE_STARTED)
{
IsideIGC* pside = pship->GetSide();
assert (pside);
CFSSide* pfsside = CFSSide::FromIGC(pside);
assert (pfsside);
GetPlayerScoreObject()->Connect(g.timeNow);
}
}
CFSDrone::~CFSDrone()
{
}
void CFSDrone::Launch(IstationIGC* pstation)
{
CFSShip::Launch(pstation);
}
void CFSDrone::Dock(IstationIGC * pstation)
{
}