#include "pch.h"
#include <stddef.h>
#include "training.h"
#include "regkey.h"
#include <zreg.h>
#include "badwords.h"
class ClusterSiteImpl : public ClusterSite
{
public:
ClusterSiteImpl(Modeler* pmodeler, Number* ptime, Viewport* pviewport, IclusterIGC* pcluster)
:
m_pcluster(pcluster)
{
m_pGroupScene = GroupGeo::Create();
m_pposterImage = CreatePosterImage(pviewport);
m_pParticleGeo = CreateParticleGeo(pmodeler, ptime);
m_pGroupScene->AddGeo(m_pParticleGeo);
m_pbitsGeo = CreateBitsGeo(pmodeler, ptime);
m_pGroupScene->AddGeo(m_pbitsGeo);
m_pexplosionGeo = CreateExplosionGeo(GetWindow()->GetTime());
m_pGroupScene->AddGeo(m_pexplosionGeo);
m_pPulseGeo = CreatePulseGeo (pmodeler, ptime);
m_pGroupScene->AddGeo(m_pPulseGeo);
m_assetmask = 0;
m_assetmaskLastWarning = 0;
}
void Terminate(void)
{
{
ScannerLinkIGC* l;
while (l = m_scanners.first()) {
l->data()->Release();
delete l;
}
}
m_pGroupScene = NULL;
m_pposterImage = NULL;
m_pexplosionGeo = NULL;
}
void AddExplosion(
const Vector& vecPosition,
const Vector& vecForward,
const Vector& vecRight,
const Vector& vecVelocity,
float scale,
int type
) {
IclusterIGC* pcluster = trekClient.GetCluster();
if (pcluster &&
(pcluster->GetClusterSite() == this))
{
GenericSoundSource* psource = new GenericSoundSource(vecPosition, vecVelocity);
if (scale > 100.0f)
trekClient.StartSound(largeExplosionSound, psource);
else if (scale > 10.0f)
trekClient.StartSound(mediumExplosionSound, psource);
else
trekClient.StartSound(smallExplosionSound, psource);
}
TRef<Image> pimageShockWave;
Color color(Color::White());
float radiusWave = 0;
float radiusExplosion = scale;
int count = 0;
switch(type) {
case 1:
count = 4;
radiusWave = 50;
radiusExplosion = 25;
pimageShockWave = trekClient.m_pimageShockWave;
color = Color(154.0f / 255.0f, 130.0f / 255.0f, 190.0f / 255.0f);
break;
case 2:
count = 6;
radiusExplosion = 1; break;
case 3:
count = 12;
radiusWave = 70;
radiusExplosion = 35;
pimageShockWave = trekClient.m_pimageShockWave;
color = Color(200.0f / 255.0f, 130.0f / 255.0f, 50.0f / 255.0f);
break;
case 4:
count = 16;
radiusWave = 250;
radiusExplosion = 165;
pimageShockWave = trekClient.m_pimageShockWave;
color = Color(200.0f / 255.0f, 130.0f / 255.0f, 50.0f / 255.0f);
break;
case 5:
count = 16;
radiusWave = 800;
radiusExplosion = 100;
pimageShockWave = trekClient.m_pimageShockWave;
color = Color(220.0f / 255.0f, 130.0f / 255.0f, 50.0f / 255.0f);
break;
case 6:
count = 5;
radiusExplosion = 150;
break;
case 7:
count = 24;
radiusWave = 1000;
radiusExplosion = 350;
pimageShockWave = trekClient.m_pimageShockWave;
color = Color(200.0f / 255.0f, 130.0f / 255.0f, 50.0f / 255.0f);
break;
}
m_pexplosionGeo->AddExplosion(
vecPosition,
vecForward,
vecRight,
vecVelocity,
radiusExplosion,
radiusWave,
color,
count,
trekClient.m_vpimageExplosion[type],
pimageShockWave
);
}
void AddExplosion(ImodelIGC* pmodel, int type)
{
const Orientation& orient = pmodel->GetOrientation();
float scale = 2 * pmodel->GetThingSite()->GetRadius();
AddExplosion(
pmodel->GetPosition(),
orient.GetForward(),
orient.GetRight(),
pmodel->GetVelocity(),
scale,
type
);
}
void AddExplosion(
const Vector& vecPosition,
float scale,
int type
) {
AddExplosion(
vecPosition,
Vector(0, 1, 0),
Vector(1, 0, 0),
Vector(0, 0, 0),
scale,
type
);
}
void AddPulse (float fExplodeTime, const Vector& vecPosition, float fRadius, const Color& color)
{
}
void AddThingSite(ThingSite* pThingSite)
{
TRef<ThingGeo> pthing = pThingSite->GetThingGeo();
if (pthing)
{
assert (pthing->IsValid());
pthing->SetParticleGeo(m_pParticleGeo);
pthing->SetBitsGeo(m_pbitsGeo);
}
Geo* pgeo = pThingSite->GetGeo();
if (pgeo)
{
assert (pgeo->IsValid());
m_pGroupScene->AddGeo(pgeo);
}
}
void DeleteThingSite(ThingSite* pThingSite)
{
Geo* pgeo = pThingSite->GetGeo();
if (pgeo)
m_pGroupScene->RemoveGeo(pgeo);
}
HRESULT AddPoster(const char* textureName, const Vector& vec, float radius)
{
TRef<Image> pimage = GetWindow()->GetModeler()->LoadImage(textureName, true);
if (pimage) {
m_pposterImage->AddPoster(pimage, vec, radius);
return S_OK;
}
return E_FAIL;
}
void SetEnvironmentGeo(const char* pszName)
{
TRef<INameSpace> pns = GetModeler()->GetNameSpace(pszName);
if (pns) {
m_pgeoEnvironment = Geo::Cast(pns->FindMember("object"));
}
}
Geo* GetEnvironmentGeo()
{
if (m_pgeoEnvironment == NULL) {
return Geo::GetEmpty();
} else {
return m_pgeoEnvironment;
}
}
GroupGeo* GetGroupScene()
{
return m_pGroupScene;
}
PosterImage* GetPosterImage()
{
return m_pposterImage;
}
virtual void AddScanner(SideID sid, IscannerIGC* scannerNew)
{
assert (sid >= 0);
assert (sid < c_cSidesMax);
assert (scannerNew);
if (sid == trekClient.GetSideID())
AddIbaseIGC((BaseListIGC*)&(m_scanners), scannerNew);
}
virtual void DeleteScanner(SideID sid, IscannerIGC* scannerOld)
{
assert (sid >= 0);
assert (sid < c_cSidesMax);
assert (scannerOld);
if (sid == trekClient.GetSideID())
DeleteIbaseIGC((BaseListIGC*)&(m_scanners), scannerOld);
}
virtual const ScannerListIGC* GetScanners(SideID sid) const
{
assert (sid >= 0);
assert (sid < c_cSidesMax);
return &(m_scanners);
}
virtual AssetMask GetClusterAssetMask(void) { return m_assetmask; }
virtual void SetClusterAssetMask(AssetMask am)
{
m_assetmask=am;
if (!trekClient.IsInGame())
m_assetmaskLastWarning = m_assetmask;
};
void UpdateClusterWarnings()
{
if (m_assetmaskLastWarning == m_assetmask)
return; bool bInvulnerableStations = trekClient.MyMission()->GetMissionParams().bInvulnerableStations;
ClusterWarning cwOld = GetClusterWarning(m_assetmaskLastWarning, bInvulnerableStations);
ClusterWarning cwNew = GetClusterWarning(m_assetmask, bInvulnerableStations);
if ((cwNew != cwOld) && (cwNew > c_cwNoThreat))
{
static const SoundID c_vAlertSounds[c_cwMax] =
{
NA,
NA,
NA,
NA,
NA,
minerThreatenedSound,
constructorThreatenedSound,
carrierThreatenedSound,
bomberDetectedSound,
carrierDetectedSound,
capitalDetectedSound,
teleportDetectedSound,
transportDetectedSound,
stationThreatenedSound,
stationThreatenedSound,
stationThreatenedSound
};
if ((cwNew >= c_cwMinerThreatened) || (trekClient.GetShip()->GetWingID() == 0))
trekClient.PostText(cwNew > cwOld, "%s in %s", GetClusterWarningText(cwNew), m_pcluster->GetName());
if (c_vAlertSounds[cwNew] != NA)
trekClient.PlaySoundEffect(c_vAlertSounds[cwNew]);
}
if (trekClient.IsInGame())
{
bool bNewSectorSecured = (m_assetmask & c_amStation)
&& !(m_assetmask & c_amEnemyStation);
bool bOldSectorSecured = (m_assetmaskLastWarning & c_amStation)
&& !(m_assetmaskLastWarning & c_amEnemyStation);
if (bNewSectorSecured && !bOldSectorSecured)
{
trekClient.PostText(false, "%s secured.", m_pcluster->GetName());
trekClient.PlaySoundEffect(sectorSecuredSound);
}
else if (!(m_assetmask & c_amStation)
&& (m_assetmaskLastWarning & c_amStation))
{
trekClient.PostText(false, "%s lost.", m_pcluster->GetName());
trekClient.PlaySoundEffect(sectorLostSound);
}
}
m_assetmaskLastWarning = m_assetmask;
}
virtual void MoveShip(void)
{
SectorID sid = m_pcluster->GetObjectID();
IsideIGC* pside = trekClient.GetSide();
AssetMask am = m_assetmask;
am &= (c_amStation | c_amEnemyStation | c_amEnemyTeleport);
for (ShipLinkIGC* psl = trekClient.m_pCoreIGC->GetShips()->first();
(psl != NULL);
psl = psl->next())
{
IshipIGC* pship = psl->data();
PlayerInfo* ppi = (PlayerInfo*)(pship->GetPrivateData());
if (ppi)
{
const ShipStatus& ss = ppi->GetShipStatus();
if ((!ss.GetUnknown()) && (ss.GetSectorID() == sid) && (ss.GetState() == c_ssFlying))
{
IhullTypeIGC* pht = trekClient.m_pCoreIGC->GetHullType(ss.GetHullID());
assert (pht);
am |= GetAssetMask(pship, pht, pside == pship->GetSide());
}
}
}
SetClusterAssetMask(am);
}
virtual void MoveStation(void)
{
IsideIGC* pside = trekClient.GetSide();
AssetMask am = m_assetmask;
am &= ~(c_amStation | c_amEnemyStation);
for (StationLinkIGC* psl = m_pcluster->GetStations()->first();
(psl != NULL);
psl = psl->next())
{
am |= (psl->data()->GetSide() == pside)
? c_amStation
: c_amEnemyStation;
}
SetClusterAssetMask(am);
}
private:
TRef<GroupGeo> m_pGroupScene;
TRef<PosterImage> m_pposterImage;
TRef<ParticleGeo> m_pParticleGeo;
TRef<BitsGeo> m_pbitsGeo;
TRef<ExplosionGeo> m_pexplosionGeo;
TRef<PulseGeo> m_pPulseGeo;
ScannerListIGC m_scanners;
TRef<Geo> m_pgeoEnvironment;
AssetMask m_assetmask;
AssetMask m_assetmaskLastWarning;
IclusterIGC* m_pcluster;
};
class ModelPointSoundSource : public ISoundPositionSource
{
private:
ImodelIGC* m_pmodel;
Vector m_vectPosition;
Vector m_vectOrientation;
bool IsRelative()
{
return m_pmodel == trekClient.GetShip()
&& GetWindow()->GetCameraMode() == TrekWindow::cmCockpit;
}
public:
ModelPointSoundSource(ImodelIGC* pmodel,
const Vector& vectPosition = Vector(0,0,0),
const Vector& vectOrientation = Vector(0,0,-1)) :
m_pmodel(pmodel),
m_vectPosition(vectPosition),
m_vectOrientation(vectOrientation)
{
}
void Destroy()
{
m_pmodel = NULL;
}
virtual HRESULT GetPosition(Vector& vectPosition)
{
ZAssert(m_pmodel != NULL);
if (m_pmodel == NULL) return E_FAIL;
if (IsRelative())
{
vectPosition = m_vectPosition;
}
else
{
vectPosition = m_pmodel->GetPosition()
+ m_vectPosition * m_pmodel->GetOrientation();
}
return S_OK;
};
virtual HRESULT GetVelocity(Vector& vectVelocity)
{
ZAssert(m_pmodel != NULL);
if (m_pmodel == NULL) return E_FAIL;
if (IsRelative())
vectVelocity = Vector(0,0,0);
else
vectVelocity = m_pmodel->GetVelocity();
return S_OK;
};
virtual HRESULT GetOrientation(Vector& vectOrientation)
{
ZAssert(m_pmodel != NULL);
if (m_pmodel == NULL) return E_FAIL;
if (IsRelative())
vectOrientation = m_vectOrientation;
else
vectOrientation = m_vectOrientation * m_pmodel->GetOrientation();
return S_OK;
};
virtual HRESULT IsListenerRelative()
{
return IsRelative() ? S_OK : S_FALSE;
}
virtual HRESULT IsPlaying()
{
return (m_pmodel != NULL) ? S_OK : S_FALSE;
};
};
class SoundSite
{
private:
ImodelIGC* m_pmodel;
TRef<ModelPointSoundSource> m_psourceCenter;
class RegisteredModelPointSoundSource : public ModelPointSoundSource
{
SoundSite* m_pSite;
public:
RegisteredModelPointSoundSource(ImodelIGC* pmodel,
SoundSite* site,
const Vector& vectPosition = Vector(0,0,0),
const Vector& vectOrientation = Vector(0,0,-1)) :
ModelPointSoundSource(pmodel, vectPosition, vectOrientation),
m_pSite(site)
{
};
~RegisteredModelPointSoundSource()
{
if (m_pSite)
m_pSite->UnregisterSource(this);
};
void Destroy()
{
ModelPointSoundSource::Destroy();
m_pSite = NULL;
};
};
TList<RegisteredModelPointSoundSource*> m_listRegisteredSources;
TList<TRef<ISoundInstance> > m_listHitSounds;
public:
SoundSite(ImodelIGC* pmodel) :
m_pmodel(pmodel)
{
}
virtual ~SoundSite()
{
StopSounds();
};
virtual void UpdateSounds(DWORD dwElapsedTime) {};
virtual void AddHitSound(TRef<ISoundInstance> psound)
{
const int nMaxHitSounds = 3;
m_listHitSounds.PushFront(psound);
if (m_listHitSounds.GetCount() > nMaxHitSounds)
{
TRef<ISoundTweakable> ptweak = m_listHitSounds.PopEnd()->GetISoundTweakable();
if (ptweak)
ptweak->SetPriority(-10);
}
}
virtual void StopSounds()
{
while (!m_listHitSounds.IsEmpty())
{
m_listHitSounds.PopEnd()->Stop();
}
if (m_psourceCenter)
{
m_psourceCenter->Destroy();
m_psourceCenter = NULL;
}
if (!m_listRegisteredSources.IsEmpty())
{
TList<RegisteredModelPointSoundSource*>::Iterator iter(m_listRegisteredSources);
while (!iter.End()) {
iter.Value()->Destroy();
iter.Next();
}
m_listRegisteredSources.SetEmpty();
}
}
TRef<ISoundPositionSource> GetSoundSource()
{
if (!m_psourceCenter)
m_psourceCenter = new ModelPointSoundSource(m_pmodel);
return m_psourceCenter;
}
TRef<ISoundPositionSource> GetSoundSource(const Vector& vectOffset,
const Vector& vectOrientation = Vector(0, 0, -1))
{
TRef<RegisteredModelPointSoundSource> psource =
new RegisteredModelPointSoundSource(m_pmodel, this, vectOffset);
m_listRegisteredSources.PushFront(psource);
return psource;
}
virtual void UnregisterSource(RegisteredModelPointSoundSource* psource)
{
ZVerify(m_listRegisteredSources.Remove(psource));
}
};
class AmbientSoundSite : public SoundSite
{
private:
TRef<ISoundInstance> m_pAmbientSound;
SoundID m_idAmbientSound;
public:
AmbientSoundSite(ImodelIGC* pmodel, SoundID idAmbientSound) :
m_idAmbientSound(idAmbientSound),
SoundSite(pmodel)
{
}
void UpdateSounds(DWORD dwElapsedTime)
{
if (!m_pAmbientSound)
{
m_pAmbientSound = trekClient.StartSound(m_idAmbientSound, GetSoundSource());
}
};
void StopSounds()
{
SoundSite::StopSounds();
m_pAmbientSound = NULL;
};
};
class ShipSoundSite : public SoundSite
{
private:
IshipIGC* m_pship;
Mount m_mountLastTurret;
float m_fHullFraction;
float m_fAmmoFraction;
float m_fFuelFraction;
float m_fEnergyFraction;
bool m_bTryingToFireWeaponWithoutAmmo;
bool m_bTryingToUseAfterburnersWithoutFuel;
int m_nRipcordCountdown;
TRef<ISoundPositionSource> m_psourceEngine;
TRef<ISoundPositionSource> m_psounceWeaponMount[c_maxMountedWeapons];
TRef<ISoundInstance> m_pOutOfBoundsSound;
TRef<ISoundInstance> m_pRipcordingSound;
TRef<ISoundInstance> m_pMissileToneSound;
TRef<ISoundInstance> m_pPilotInteriorSound;
TRef<ISoundInstance> m_pGunnerInteriorSound;
TRef<ISoundInstance> m_pMainThrusterInteriorSound;
TRef<ISoundInstance> m_pTurnThrusterInteriorSound;
TRef<ISoundInstance> m_pAfterburnerInteriorSound;
TRef<ISoundInstance> m_pExteriorSound;
TRef<ISoundInstance> m_pMainThrusterExteriorSound;
TRef<ISoundInstance> m_pTurnThrusterExteriorSound;
TRef<ISoundInstance> m_pAfterburnerExteriorSound;
TRef<ISoundInstance> m_pMiningSound;
IpartTypeIGC* m_vpCurrentWeaponType[c_maxMountedWeapons];
TRef<ISoundInstance> m_vpBurstSound[c_maxMountedWeapons];
TRef<ISoundInstance> m_vpActiveSound[c_maxMountedWeapons];
TRef<ISoundInstance> m_vpTurretSound[c_maxMountedWeapons];
enum { wasSilent, wasPlaying } m_stateLast;
float m_fThrustSoundLevel;
float m_fTurnSoundLevel;
float ForwardThrustFraction()
{
const ControlData& controls = m_pship->GetControls();
return max(controls.jsValues[c_axisThrottle] * 0.5f + 0.5f,
(m_pship->GetStateM() & afterburnerButtonIGC) ? 1.0f : 0.0f);
}
float SidewaysThrustFraction()
{
const IhullTypeIGC* pht = m_pship->GetHullType();
float fThrust = m_pship->GetHullType()->GetThrust()
/ m_pship->GetHullType()->GetSideMultiplier();
float fForwardThrust = max(0, -1 * m_pship->GetEngineVector()
* m_pship->GetOrientation().GetBackward());
Vector vectSideThrust = m_pship->GetEngineVector() +
fForwardThrust * m_pship->GetOrientation().GetBackward();
return vectSideThrust.LengthSquared() / (fThrust * fThrust);
}
float TurnRate(IshipIGC* pship)
{
const ControlData& controls = pship->GetControls();
return (controls.jsValues[c_axisYaw] * controls.jsValues[c_axisYaw] +
controls.jsValues[c_axisPitch] * controls.jsValues[c_axisPitch] +
controls.jsValues[c_axisRoll] * controls.jsValues[c_axisRoll]);
}
float TurnRate()
{
return TurnRate(m_pship);
}
float AfterburnerPower()
{
IafterburnerIGC* pafterburner =
(IafterburnerIGC*)(m_pship->GetMountedPart(ET_Afterburner, 0));
return pafterburner ? pafterburner->GetPower() : 0.0f;
}
bool TryingToFireWeaponWithoutAmmo()
{
ZAssert(m_pship == trekClient.GetShip()->GetSourceShip());
Mount mount = trekClient.GetShip()->GetTurretID();
if (mount != NA)
{
const IweaponIGC* pweapon;
CastTo(pweapon, m_pship->GetMountedPart(ET_Weapon, mount));
return (pweapon && pweapon->fActive() && pweapon->GetMountedFraction() >= 1.0f
&& pweapon->GetAmmoPerShot() > m_pship->GetAmmo());
}
else
{
Mount maxFixedWeapons = m_pship->GetHullType()->GetMaxFixedWeapons();
for (mount = 0; mount < maxFixedWeapons; mount++)
{
const IweaponIGC* pweapon;
CastTo(pweapon, m_pship->GetMountedPart(ET_Weapon, mount));
if (pweapon && pweapon->fActive() && pweapon->GetMountedFraction() >= 1.0f
&& pweapon->GetAmmoPerShot() > m_pship->GetAmmo())
{
return true;
}
}
return false;
}
}
bool TryingToFireAfterburnersWithoutFuel()
{
IafterburnerIGC* pafterburner =
(IafterburnerIGC*)(m_pship->GetMountedPart(ET_Afterburner, 0));
return pafterburner
&& (m_pship->GetStateM() & afterburnerButtonIGC)
&& m_pship->GetFuel() <= 0.0f
&& pafterburner->GetMountedFraction() >= 1.0;;
}
bool HasMissileLock()
{
ZAssert(m_pship == trekClient.GetShip()->GetSourceShip());
ImagazineIGC* pmagazine = (ImagazineIGC*)trekClient.GetShip()->GetSourceShip()->GetMountedPart(ET_Magazine, 0);
return (pmagazine && pmagazine->GetLock() == 1.0f);
}
void SetInternalVolume(float fGain)
{
if (m_pPilotInteriorSound)
m_pPilotInteriorSound->GetISoundTweakable()->SetGain(fGain);
if (m_pGunnerInteriorSound)
m_pGunnerInteriorSound->GetISoundTweakable()->SetGain(fGain);
float fThrustVolumeFactor = (1 - m_fThrustSoundLevel);
fThrustVolumeFactor *= fThrustVolumeFactor;
fThrustVolumeFactor *= fThrustVolumeFactor;
fThrustVolumeFactor *= fThrustVolumeFactor;
fThrustVolumeFactor *= fThrustVolumeFactor;
fThrustVolumeFactor *= fThrustVolumeFactor;
fThrustVolumeFactor *= fThrustVolumeFactor;
if (m_pMainThrusterInteriorSound)
m_pMainThrusterInteriorSound->GetISoundTweakable()->SetGain(fGain +
fThrustVolumeFactor * -60);
float fTurnThrustVolumeFactor = (1 - m_fTurnSoundLevel);
fTurnThrustVolumeFactor *= fTurnThrustVolumeFactor;
if (m_pTurnThrusterInteriorSound)
m_pTurnThrusterInteriorSound->GetISoundTweakable()->SetGain(fGain +
fTurnThrustVolumeFactor * -60);
if (m_pAfterburnerInteriorSound)
m_pAfterburnerInteriorSound->GetISoundTweakable()->SetGain(fGain);
}
void SetExternalVolume(float fGain)
{
if (m_pExteriorSound)
m_pExteriorSound->GetISoundTweakable()->SetGain(fGain);
if (m_pMainThrusterExteriorSound)
m_pMainThrusterExteriorSound->GetISoundTweakable()->SetGain(fGain +
(1 - m_fThrustSoundLevel) * -40);
if (m_pTurnThrusterExteriorSound)
m_pTurnThrusterExteriorSound->GetISoundTweakable()->SetGain(fGain +
(1 - m_fTurnSoundLevel) * -40);
if (m_pAfterburnerExteriorSound)
m_pAfterburnerExteriorSound->GetISoundTweakable()->SetGain(fGain);
}
void PlaySoundIf(TRef<ISoundInstance>& pSound, SoundID id,
ISoundPositionSource* psource, bool bPlay)
{
if (bPlay)
{
if (!pSound)
{
pSound = trekClient.StartSound(id, psource);
}
}
else
{
if (pSound)
{
pSound->Stop();
pSound= NULL;
}
}
};
void PlayWeaponSounds()
{
Mount maxWeapons = m_pship->GetHullType()->GetMaxWeapons();
for (Mount mount = 0; mount < maxWeapons; mount++)
{
const IweaponIGC* pweapon;
CastTo(pweapon, m_pship->GetMountedPart(ET_Weapon, mount));
if (pweapon && pweapon->GetPartType() != m_vpCurrentWeaponType[mount])
{
if (m_vpBurstSound[mount])
m_vpBurstSound[mount]->Stop();
if (m_vpActiveSound[mount])
m_vpActiveSound[mount]->Stop();
m_vpBurstSound[mount] = NULL;
m_vpActiveSound[mount] = NULL;
m_vpCurrentWeaponType[mount] = pweapon->GetPartType();
}
PlaySoundIf(m_vpActiveSound[mount], pweapon ? pweapon->GetActivateSound() : NA,
m_psounceWeaponMount[mount], pweapon && pweapon->fActive());
PlaySoundIf(m_vpTurretSound[mount],
m_pship->GetHullType()->GetHardpointData(mount).turnSound,
m_psounceWeaponMount[mount],
pweapon && pweapon->GetGunner()
&& (pweapon->fActive()
|| pweapon->GetGunner() == trekClient.GetShip())
&& TurnRate(pweapon->GetGunner()) > 0.01);
bool bWasBurstFiring = m_vpBurstSound[mount] != NULL;
SoundID idBurstSound = pweapon ? pweapon->GetBurstSound() : NA;
PlaySoundIf(m_vpBurstSound[mount], idBurstSound,
m_psounceWeaponMount[mount],
pweapon && pweapon->fFiringBurst() && (idBurstSound != NA));
if (pweapon && pweapon->fFiringShot()
&& m_vpBurstSound[mount] == NULL && !bWasBurstFiring)
{
trekClient.StartSound(pweapon->GetSingleShotSound(),
m_psounceWeaponMount[mount]);
}
}
}
void UpdateRipcordCountdown()
{
if (!trekClient.GetShip()->GetSourceShip()->fRipcordActive())
{
m_nRipcordCountdown = 11;
}
else
{
int nRipcordCountdown = 1 + (int)trekClient.GetShip()->GetSourceShip()->GetRipcordTimeLeft();
if (nRipcordCountdown != m_nRipcordCountdown)
{
switch (nRipcordCountdown)
{
case 10:
trekClient.StartSound(ripcord10Sound, GetSoundSource());
break;
case 9:
trekClient.StartSound(ripcord9Sound, GetSoundSource());
break;
case 8:
trekClient.StartSound(ripcord8Sound, GetSoundSource());
break;
case 7:
trekClient.StartSound(ripcord7Sound, GetSoundSource());
break;
case 6:
trekClient.StartSound(ripcord6Sound, GetSoundSource());
break;
case 5:
trekClient.StartSound(ripcord5Sound, GetSoundSource());
break;
case 4:
trekClient.StartSound(ripcord4Sound, GetSoundSource());
break;
case 3:
trekClient.StartSound(ripcord3Sound, GetSoundSource());
break;
case 2:
trekClient.StartSound(ripcord2Sound, GetSoundSource());
break;
case 1:
trekClient.StartSound(ripcord1Sound, GetSoundSource());
break;
}
m_nRipcordCountdown = nRipcordCountdown;
}
}
}
void CreateSoundSources()
{
m_psourceEngine = GetSoundSource(
m_pship->GetThingSite()->GetChildModelOffset("trail"), Vector(0,0,1));
const IhullTypeIGC* pht = m_pship->GetHullType();
Mount maxWeapons = pht->GetMaxWeapons();
for (Mount mount = 0; mount < maxWeapons; mount++)
{
m_psounceWeaponMount[mount] = GetSoundSource(
pht->GetWeaponPosition(mount),
pht->GetWeaponOrientation(mount).GetForward()
);
}
}
SoundID GetGunnerInteriorSoundID()
{
if (trekClient.GetShip()->GetParentShip())
{
const IhullTypeIGC* pht = m_pship->GetHullType();
ZAssert(pht);
Mount mount = trekClient.GetShip()->GetTurretID();
if (mount != NA)
{
return pht->GetHardpointData(mount).interiorSound;
}
}
return NA;
}
SoundID GetAfterburnerSoundID(bool fInterior)
{
IafterburnerIGC* pafterburner =
(IafterburnerIGC*)(m_pship->GetMountedPart(ET_Afterburner, 0));
if (pafterburner)
{
if (fInterior)
return pafterburner->GetInteriorSound();
else
return pafterburner->GetExteriorSound();
}
else
{
return NA;
}
}
void UpdateEngineSoundLevels(DWORD dwElapsedTime)
{
float fNewThrustSoundLevel = ForwardThrustFraction();
float fNewTurnSoundLevel = min(1.0f, max(TurnRate() * 20, SidewaysThrustFraction()));
if (wasSilent != m_stateLast)
{
const float cfMaxThrustRateOfChange = 0.0005f;
const float cfMaxTurnRateOfChange = 0.002f;
fNewThrustSoundLevel = max(
m_fThrustSoundLevel - cfMaxThrustRateOfChange * dwElapsedTime,
min(
m_fThrustSoundLevel + cfMaxThrustRateOfChange * dwElapsedTime,
fNewThrustSoundLevel
));
fNewTurnSoundLevel = max(
m_fTurnSoundLevel - cfMaxTurnRateOfChange * dwElapsedTime,
min(
m_fTurnSoundLevel + cfMaxTurnRateOfChange * dwElapsedTime,
fNewTurnSoundLevel
));
}
m_fThrustSoundLevel = fNewThrustSoundLevel;
m_fTurnSoundLevel = fNewTurnSoundLevel;
if (m_pMainThrusterInteriorSound)
m_pMainThrusterInteriorSound->GetISoundTweakable()->SetPitch(
0.5f + m_fThrustSoundLevel/2);
if (m_pTurnThrusterInteriorSound)
m_pTurnThrusterInteriorSound->GetISoundTweakable()->SetPitch(
0.50f + m_fTurnSoundLevel/3);
if (m_pMainThrusterExteriorSound)
m_pMainThrusterExteriorSound->GetISoundTweakable()->SetPitch(
0.5f + m_fThrustSoundLevel/2);
if (m_pTurnThrusterExteriorSound)
m_pTurnThrusterExteriorSound->GetISoundTweakable()->SetPitch(
0.50f + m_fTurnSoundLevel/2);
}
public:
ShipSoundSite(IshipIGC* pship) :
m_pship(pship),
SoundSite(pship),
m_mountLastTurret(NA),
m_stateLast(wasSilent),
m_fHullFraction(1.0f),
m_fAmmoFraction(1.0f),
m_fFuelFraction(1.0f),
m_fEnergyFraction(1.0f),
m_bTryingToFireWeaponWithoutAmmo(false),
m_bTryingToUseAfterburnersWithoutFuel(false),
m_nRipcordCountdown(11)
{
for (Mount mount = 0; mount < c_maxMountedWeapons; mount++)
{
m_vpBurstSound[mount] = NULL;
};
}
void UpdateSounds(DWORD dwElapsedTime)
{
if (!m_pship->GetParentShip())
{
if (!m_psourceEngine)
{
CreateSoundSources();
};
const IhullTypeIGC* pht = m_pship->GetHullType();
ZAssert(pht);
bool bIsPlayersShip = trekClient.GetShip()->GetSourceShip() == m_pship;
bool bIsInterior = bIsPlayersShip
&& TrekWindow::InternalCamera(GetWindow()->GetCameraMode());
if (bIsPlayersShip && m_mountLastTurret != trekClient.GetShip()->GetTurretID())
{
if (m_pGunnerInteriorSound)
{
m_pGunnerInteriorSound->Stop();
m_pGunnerInteriorSound = NULL;
};
m_mountLastTurret = trekClient.GetShip()->GetTurretID();
}
bool bIsGunner = bIsPlayersShip && m_mountLastTurret != NA;
float fNewHullFraction = 1.0f;
float fNewAmmoFraction = 1.0f;
float fNewFuelFraction = 1.0f;
float fNewEnergyFraction = 1.0f;
bool fNewFiringWithoutAmmo = false;
bool fNewThrustingWithoutFuel = false;
if (bIsPlayersShip)
{
fNewHullFraction = m_pship->GetFraction();
fNewAmmoFraction = m_pship->GetAmmo()
/ (float)m_pship->GetHullType()->GetMaxAmmo();
if (m_pship->GetHullType()->GetMaxFuel() > 0)
{
fNewFuelFraction = m_pship->GetFuel()
/ m_pship->GetHullType()->GetMaxFuel();
}
if (m_pship->GetHullType()->GetMaxEnergy() > 0)
{
fNewEnergyFraction = m_pship->GetEnergy()
/ m_pship->GetHullType()->GetMaxEnergy();
}
fNewFiringWithoutAmmo = TryingToFireWeaponWithoutAmmo();
fNewThrustingWithoutFuel = TryingToFireAfterburnersWithoutFuel();
}
if (bIsPlayersShip && fNewHullFraction < 0.15f && m_fHullFraction >= 0.15f)
trekClient.StartSound(hullLowSound, GetSoundSource());
if (bIsPlayersShip && fNewAmmoFraction < 0.15f && m_fAmmoFraction >= 0.15f)
trekClient.StartSound(ammoLowSound, GetSoundSource());
if (bIsPlayersShip && fNewFuelFraction < 0.15f && m_fFuelFraction >= 0.15f)
trekClient.StartSound(fuelLowSound, GetSoundSource());
if (bIsPlayersShip && fNewEnergyFraction < 0.05f && m_fEnergyFraction >= 0.05f)
trekClient.StartSound(energyLowSound, GetSoundSource());
if (!m_bTryingToFireWeaponWithoutAmmo && fNewFiringWithoutAmmo)
trekClient.StartSound(salNoAmmoSound, GetSoundSource());
if (!m_bTryingToUseAfterburnersWithoutFuel && fNewThrustingWithoutFuel)
trekClient.StartSound(salNoFuelSound, GetSoundSource());
UpdateRipcordCountdown();
m_fHullFraction = fNewHullFraction;
m_fAmmoFraction = fNewAmmoFraction;
m_fFuelFraction = fNewFuelFraction;
m_fEnergyFraction = fNewEnergyFraction;
m_bTryingToFireWeaponWithoutAmmo = fNewFiringWithoutAmmo;
m_bTryingToUseAfterburnersWithoutFuel = fNewThrustingWithoutFuel;
PlaySoundIf(m_pOutOfBoundsSound, outOfBoundsLoopSound, GetSoundSource(),
(trekClient.GetShip()->GetWarningMask() & (c_wmOutOfBounds | c_wmCrowdedSector)) != 0);
PlaySoundIf(m_pRipcordingSound, ripcordOnLoopSound, GetSoundSource(),
bIsPlayersShip && m_pship->fRipcordActive());
PlaySoundIf(m_pMissileToneSound, missileToneSound, GetSoundSource(),
bIsPlayersShip && HasMissileLock());
PlaySoundIf(m_pMiningSound, miningSound, GetSoundSource(),
((m_pship->GetStateM() & miningMaskIGC) != 0) && trekClient.GetShip()->CanSee(m_pship)); PlayWeaponSounds();
if (bIsPlayersShip)
{
SoundID gunnerInteriorSoundID = GetGunnerInteriorSoundID();
PlaySoundIf(m_pGunnerInteriorSound, gunnerInteriorSoundID,
GetSoundSource(), bIsGunner);
PlaySoundIf(m_pPilotInteriorSound, pht->GetInteriorSound(),
GetSoundSource(), !bIsGunner);
PlaySoundIf(m_pMainThrusterInteriorSound,
pht->GetMainThrusterInteriorSound(),
m_psourceEngine, m_fThrustSoundLevel > 0.01f);
PlaySoundIf(m_pTurnThrusterInteriorSound,
pht->GetManuveringThrusterInteriorSound(), GetSoundSource(),
m_fTurnSoundLevel > 0.01f);
PlaySoundIf(m_pAfterburnerInteriorSound,
GetAfterburnerSoundID(true),
m_psourceEngine, AfterburnerPower() > 0.0f);
}
PlaySoundIf(m_pExteriorSound, pht->GetExteriorSound(), GetSoundSource(), true);
PlaySoundIf(m_pMainThrusterExteriorSound,
pht->GetMainThrusterExteriorSound(), m_psourceEngine,
m_fThrustSoundLevel > 0.01f);
PlaySoundIf(m_pTurnThrusterExteriorSound,
pht->GetManuveringThrusterExteriorSound(), GetSoundSource(),
m_fTurnSoundLevel > 0.01f);
PlaySoundIf(m_pAfterburnerExteriorSound,
GetAfterburnerSoundID(false),
m_psourceEngine,
AfterburnerPower() > 0.0f);
UpdateEngineSoundLevels(dwElapsedTime);
if (bIsInterior)
{
SetExternalVolume(-100);
SetInternalVolume(0);
}
else
{
SetExternalVolume(0);
SetInternalVolume(-100);
}
m_stateLast = wasPlaying;
}
};
void StopSounds()
{
SoundSite::StopSounds();
if (m_psourceEngine)
{
m_psourceEngine = NULL;
m_pOutOfBoundsSound = NULL;
m_pRipcordingSound = NULL;
m_pPilotInteriorSound = NULL;
m_pGunnerInteriorSound = NULL;
m_pMainThrusterInteriorSound = NULL;
m_pTurnThrusterInteriorSound = NULL;
m_pAfterburnerInteriorSound = NULL;
m_pExteriorSound = NULL;
m_pMainThrusterExteriorSound = NULL;
m_pTurnThrusterExteriorSound = NULL;
m_pAfterburnerExteriorSound = NULL;
Mount maxWeapons = m_pship->GetHullType()->GetMaxWeapons();
for (Mount mount = 0; mount < maxWeapons; mount++)
{
m_psounceWeaponMount[mount] = NULL;
m_vpBurstSound[mount] = NULL;
m_vpActiveSound[mount] = NULL;
m_vpTurretSound[mount] = NULL;
}
m_stateLast = wasSilent;
}
};
};
class ThingSiteImpl : public ThingSitePrivate
{
public:
ThingSiteImpl(ImodelIGC* pmodel)
:
m_bSideVisibility(false),
m_pmodel(pmodel),
m_mask(0),
m_bPlayedHitSoundThisFrame(false)
{
assert (pmodel);
switch (pmodel->GetObjectType())
{
case OT_asteroid:
m_pSoundSite = new AmbientSoundSite(pmodel, asteroidSound);
break;
case OT_warp:
m_pSoundSite = new AmbientSoundSite(pmodel, alephSound);
break;
case OT_buildingEffect:
m_pSoundSite = new AmbientSoundSite(pmodel, buildSound);
break;
case OT_probe:
m_pSoundSite = new AmbientSoundSite(pmodel,
((IprobeIGC*)pmodel)->GetAmbientSound());
break;
case OT_missile:
m_pSoundSite = new AmbientSoundSite(pmodel,
((ImissileIGC*)pmodel)->GetMissileType()->GetAmbientSound());
break;
case OT_projectile:
{
SoundID sound = ((IprojectileIGC*)pmodel)
->GetProjectileType()->GetAmbientSound();
if (sound = NA)
m_pSoundSite = NULL;
else
m_pSoundSite = new AmbientSoundSite(pmodel, sound);
}
break;
case OT_station:
m_pSoundSite = new AmbientSoundSite(pmodel,
((IstationIGC*)pmodel)->GetExteriorSound());
break;
case OT_ship:
m_pSoundSite = new ShipSoundSite((IshipIGC*)pmodel);
break;
default:
m_pSoundSite = NULL;
break;
}
}
~ThingSiteImpl(void)
{
if (m_pSoundSite)
delete m_pSoundSite;
}
void Purge(void)
{
if (m_pthing) {
assert (!m_pdecal);
m_pthingGeo->SetEmpty();
m_pthingGeo = NULL;
m_pthing = NULL;
}
else if (m_pdecal) {
m_pdecal->SetEmpty();
m_pdecal = NULL;
}
}
void Terminate(void)
{
if (m_pdecal)
{
m_pdecal->SetEmpty();
m_pdecal = NULL;
assert(m_pvisibleGeoBolt == NULL);
}
else
{
if (m_pthing)
{
assert (!m_pdecal);
m_pthingGeo->SetEmpty();
m_pthingGeo = NULL;
m_pthing = NULL;
if (m_pvisibleGeoBolt)
{
m_pvisibleGeoBolt->SetEmpty();
m_pvisibleGeoBolt = NULL;
}
}
else if (m_pbuildeffect)
{
m_pbuildeffect->SetEmpty();
m_pbuildeffect = NULL;
}
}
}
Vector GetChildModelOffset(const ZString& strFrame)
{
Vector vec(0, 0, 0);
if (!m_pthing->GetChildModelOffset(strFrame, vec))
return Vector(0,0,0);
return vec;
}
Vector GetChildOffset(const ZString& strFrame)
{
Vector vec(0, 0, 0);
ZVerify(m_pthing->GetChildOffset(strFrame, vec));
return vec;
}
void SetAfterburnerSmokeSize (float size)
{
m_pthing->SetAfterburnerSmokeSize (size);
}
void SetAfterburnerFireDuration (float duration)
{
m_pthing->SetAfterburnerFireDuration (duration);
}
void SetAfterburnerSmokeDuration (float duration)
{
m_pthing->SetAfterburnerSmokeDuration (duration);
}
void AddDamage (const Vector& vecDamagePosition, float fDamageFraction)
{
m_pthing->AddDamage (vecDamagePosition, fDamageFraction);
}
void RemoveDamage (float fDamageFraction)
{
m_pthing->RemoveDamage (fDamageFraction);
}
void SetTimeUntilRipcord (float fTimeUntilTeleport)
{
m_pthing->SetTimeUntilRipcord (fTimeUntilTeleport);
}
void SetTimeUntilAleph (float fTimeUntilTeleport)
{
m_pthing->SetTimeUntilAleph (fTimeUntilTeleport);
}
void AddExplosion(const Vector& vecPosition, float scale, int type)
{
IclusterIGC* pcluster = m_pmodel->GetCluster();
pcluster->GetClusterSite()->AddExplosion(
m_pmodel->GetPosition() + vecPosition * m_pmodel->GetOrientation(),
scale, type);
}
void AddPulse (float fExplodeTime, const Vector& vecPosition, float fRadius, const Color& color)
{
if ((m_pmodel->GetObjectType()) == OT_warp)
{
m_peventSourceAleph->Trigger(fExplodeTime);
}
}
void AddHullHit(const Vector& vecPosition, const Vector& vecNormal)
{
if (m_pthing)
m_pthing->AddHullHit(vecPosition, vecNormal);
}
void SetAfterburnerThrust(const Vector& thrust, float power)
{
if (m_pthing) {
m_pthing->SetAfterburnerThrust(thrust, power);
} else {
assert (m_pdecal);
}
}
void AddMuzzleFlare(const Vector& vecEmissionPoint, float duration)
{
if (this == trekClient.GetShip()->GetThingSite())
GetWindow()->AddMuzzleFlare(vecEmissionPoint, duration);
}
void AddFlare(Time timeArg, const Vector& vecPosition, int id,
const Vector* ellipseEquation)
{
if (m_pthing->GetFlareCount() < 4.0f)
{
TRef<Number> ptimeArg = GetWindow()->GetTime();
TRef<Number> ptime = Subtract(ptimeArg, ptimeArg->MakeConstant());
m_pthing->AddFlare(
new TextureGeo(
trekClient.m_pgeoFlares[id],
new AnimatedImage(
ptime,
trekClient.m_pimageFlare
)
),
ptime,
-vecPosition, ellipseEquation
);
}
}
void SetVisible(unsigned char render)
{
if (m_pthing)
{
bool vship = render == c_ucRenderAll;
m_pthing->SetVisible(render >= c_ucRenderTrail);
m_pthing->SetVisibleShip(vship);
if (m_pvisibleGeoBolt) {
m_pvisibleGeoBolt->SetVisible(vship);
}
}
}
ThingGeo* GetThingGeo()
{
return m_pthing;
}
Geo* GetGeo()
{
if (m_pthingGeo) {
return m_pthingGeo;
} else {
if (m_pdecal) {
return m_pdecal;
} else {
return m_pbuildeffect;
}
}
}
void SetPosition(const Vector& position)
{
if (m_pthing) {
m_pthing->SetPosition(position);
} else if (m_pdecal) {
m_pdecal->SetPosition(position);
}
else if (m_pbuildeffect)
m_pbuildeffect->SetPosition(position);
}
float GetRadius(void)
{
if (m_pthing)
{
return m_pthing->GetRadius();
}
else if (m_pdecal)
{
return sqrt2;
}
else if (m_pbuildeffect)
return m_pbuildeffect->GetRadius();
else
return 0.0f;
}
void SetRadius(float r)
{
m_radius = r;
if (m_pdecal)
{
if (m_pdecal->GetForward().IsZero())
m_pdecal->SetScale(r / sqrt2);
else
m_pdecal->SetForward(m_pdecal->GetForward().Normalize() * m_radius);
}
else if (m_pthing)
{
assert (m_pthing);
m_pthing->SetRadius(r);
}
else if (m_pbuildeffect)
{
m_pbuildeffect->SetRadius(r);
}
}
void SetColors(float aInner, float fInner, float fOuter)
{
assert (m_pbuildeffect);
m_pbuildeffect->SetColors(aInner, fInner, fOuter);
}
void SetOrientation(const Orientation& orientation)
{
if (m_pthing)
m_pthing->SetOrientation(orientation);
else if (m_pdecal)
{
if (!m_pdecal->GetForward().IsZero())
m_pdecal->SetForward(orientation.GetBackward() * -m_radius);
}
}
void Spin(float r)
{
if (m_pdecal)
{
assert (!m_pthing);
m_pdecal->SetAngle(m_pdecal->GetAngle() + r);
}
}
void SetTexture(const char* pszTextureName)
{
assert (m_pthing);
m_pthing->SetTexture(GetWindow()->GetModeler()->LoadImage(pszTextureName, false));
}
HRESULT LoadEffect(const Color& color)
{
m_pbuildeffect = CreateBuildEffectGeo(GetWindow()->GetModeler(),
GetWindow()->GetTime(),
color);
return S_OK;
}
HRESULT LoadDecal(const char* textureName, bool bDirectional, float width)
{
ZAssert(m_pthing == NULL && m_pdecal == NULL);
Number* ptime = GetWindow()->GetTime();
TRef<AnimatedImage> pimage =
GetWindow()->LoadAnimatedImage(
Divide(
Subtract(ptime, ptime->MakeConstant()),
new Number(2) ),
ZString(textureName) + "bmp"
);
if (pimage) {
m_pdecal =
new DecalGeo(
pimage,
Color::White(),
Vector::GetZero(),
Vector::GetZero(),
Vector::GetZero(),
width,
0
);
if (bDirectional) {
m_pdecal->SetForward(Vector(0, 0, -1));
}
return S_OK;
}
return E_FAIL;
}
HRESULT LoadModel(
int options,
const char* modelName,
const char* textureName
) {
HRESULT rc = S_OK;
ZAssert(m_pthing == NULL && m_pdecal == NULL);
if (modelName)
{
m_pthing =
ThingGeo::Create(
GetWindow()->GetModeler(),
GetWindow()->GetTime()
);
m_pthingGeo = m_pthing->GetGeo();
if (textureName && ((!isalpha(textureName[0])) || (strcmp(modelName, textureName) == 0))) {
textureName = NULL;
}
TRef<Image> pimageTexture;
if (textureName)
{
pimageTexture = GetModeler()->LoadImage(textureName, false);
}
TRef<INameSpace> pns = GetModeler()->GetNameSpace(modelName);
if (pns != NULL) {
rc = m_pthing->LoadMDL(options, pns, pimageTexture);
} else {
return E_FAIL;
}
#ifdef _DEBUG
{
bool bAnimation;
ZString str = ZString(modelName) + "_m.x";
TRef<Number> pnumber = new Number(0.0f);
TRef<Geo> pgeo = GetModeler()->LoadXFile(str, pnumber, bAnimation, false);
if (pgeo) {
m_pthing->SetBoundsGeo(
pgeo
);
}
}
#endif
}
return rc;
}
void SetTrailColor(const Color& color)
{
if (m_pthing)
m_pthing->SetTrailColor(color);
else
{
assert (m_pdecal);
}
}
HRESULT LoadAleph(const char* textureName)
{
ZAssert(m_pthing == NULL && m_pdecal == NULL);
m_pthing =
ThingGeo::Create(
GetWindow()->GetModeler(),
GetWindow()->GetTime()
);
m_pthingGeo = m_pthing->GetGeo();
TRef<Image> pimageAleph =
GetWindow()->GetModeler()->LoadImage(ZString(textureName) + "bmp", false);
if (pimageAleph) {
m_peventSourceAleph = new TEvent<float>::SourceImpl;
HRESULT hr =
m_pthing->Load(
0,
CreateAlephGeo(
GetWindow()->GetModeler(),
m_peventSourceAleph,
GetWindow()->GetTime()
),
pimageAleph
);
return hr;
}
return E_FAIL;
}
HRESULT LoadMine(const char* textureName, float strength, float radius)
{
ZAssert(m_pthing == NULL && m_pdecal == NULL);
m_pthing =
ThingGeo::Create(
GetWindow()->GetModeler(),
GetWindow()->GetTime()
);
m_pthingGeo = m_pthing->GetGeo();
TRef<Surface> psurface =
GetWindow()->GetModeler()->LoadSurface(ZString(textureName) + "bmp", true);
if (psurface) {
m_pmineFieldGeo = CreateMineFieldGeo(psurface, strength, radius);
HRESULT hr = m_pthing->Load(0, m_pmineFieldGeo, NULL);
return hr;
}
return E_FAIL;
}
void SetMineStrength(float strength)
{
m_pmineFieldGeo->SetStrength(strength);
}
void UpdateScreenPosition(
const Point& pointScreenPosition,
float fScreenRadius,
float distanceToEdge,
unsigned char ucRadarState
) {
m_pointScreenPosition = pointScreenPosition;
m_fScreenRadius = fScreenRadius;
m_distanceToEdge = distanceToEdge;
m_ucRadarState = ucRadarState;
}
const Point& GetScreenPosition(void) const
{
return m_pointScreenPosition;
}
float GetDistanceToEdge()
{
return m_distanceToEdge;
}
float GetScreenRadius()
{
return m_fScreenRadius;
}
unsigned char GetRadarState()
{
return m_ucRadarState;
}
void SetCluster(ImodelIGC* pmodel, IclusterIGC* pcluster)
{
ModelAttributes ma = pmodel->GetAttributes();
m_bSideVisibility = (ma & c_mtSeenBySide) != 0;
m_bIsShip = (pmodel->GetObjectType() == OT_ship);
if (pcluster)
{
if (((ma & c_mtPredictable) && trekClient.m_fm.IsConnected()) || !m_bSideVisibility)
{
m_sideVisibility.fVisible(true);
switch (pmodel->GetObjectType())
{
case OT_asteroid:
trekClient.GetClientEventSource()->
OnDiscoveredAsteroid((IasteroidIGC*)pmodel);
break;
case OT_station:
trekClient.GetClientEventSource()->
OnDiscoveredStation((IstationIGC*)pmodel);
break;
case OT_probe:
{
if ( ((IprobeIGC*)pmodel)->GetProbeType()->HasCapability(c_eabmRipcord) )
{
IsideIGC* pside = pmodel->GetSide();
if (pside != trekClient.GetSide())
{
assert (pside);
ClusterSite* pcs = pcluster->GetClusterSite();
pcs->SetClusterAssetMask(pcs->GetClusterAssetMask() | c_amEnemyTeleport);
trekClient.PostText(true, START_COLOR_STRING "%s %s" END_COLOR_STRING " spotted in %s",
(PCC) ConvertColorToString (pside->GetColor ()), pside->GetName(), GetModelName(pmodel), pcluster->GetName());
}
else
{
trekClient.PostText(true, "%s deployed in %s", GetModelName(pmodel), pcluster->GetName());
}
}
}
}
}
else
UpdateSideVisibility(pmodel, pcluster);
}
else
{
if (m_pSoundSite)
m_pSoundSite->StopSounds();
}
}
void UpdateSideVisibility(ImodelIGC* pmodel, IclusterIGC* pcluster)
{
if (m_bSideVisibility && trekClient.GetSide())
{
if (!(m_sideVisibility.fVisible() && (pmodel->GetAttributes() & c_mtPredictable)))
{
if ((trekClient.GetSide() == pmodel->GetSide()) ||
(m_sideVisibility.pLastSpotter() &&
m_sideVisibility.pLastSpotter()->InScannerRange(pmodel)))
{
if (!m_sideVisibility.fVisible())
{
if (m_bIsShip)
{
IsideIGC* pside = pmodel->GetSide();
if (pside != trekClient.GetSide())
{
trekClient.PlaySoundEffect(newShipSound, pmodel);
}
else
{
trekClient.PlaySoundEffect(newEnemySound, pmodel);
}
}
m_sideVisibility.fVisible(true);
}
}
else
{
m_sideVisibility.fVisible(false);
for (ScannerLinkIGC* l = pcluster->GetClusterSite()->GetScanners(0)->first();
(l != NULL);
l = l->next())
{
IscannerIGC* s = l->data();
assert (s->GetCluster() == pcluster);
if (s->InScannerRange(pmodel))
{
if (m_bIsShip)
trekClient.PlaySoundEffect(newShipSound, pmodel);
m_sideVisibility.fVisible(true);
m_sideVisibility.pLastSpotter(s);
break;
}
}
}
}
}
}
bool GetSideVisibility(IsideIGC* side)
{
assert (side);
if (Training::IsTraining ())
{
if ((trekClient.GetShip ()->GetSide () != side) && (Training::GetTrainingMissionID () != Training::c_TM_6_Practice_Arena))
return false;
}
return m_sideVisibility.fVisible();
}
void SetSideVisibility(IsideIGC* side, bool fVisible)
{
if (m_bSideVisibility && (side == trekClient.GetSide()))
m_sideVisibility.fVisible(fVisible);
if (fVisible)
{
switch (m_pmodel->GetObjectType())
{
case OT_asteroid:
trekClient.GetClientEventSource()->
OnDiscoveredAsteroid((IasteroidIGC*)m_pmodel);
break;
case OT_station:
trekClient.GetClientEventSource()->
OnDiscoveredStation((IstationIGC*)m_pmodel);
break;
}
}
}
virtual void ActivateBolt(void)
{
if (m_pmodel->GetVisibleF())
{
float r = 0.5f * m_pmodel->GetRadius();
Vector f = m_pmodel->GetOrientation().GetBackward();
Vector p1 = m_pmodel->GetPosition() - f * r; Vector p2 = p1 - (100.0f + r) * f;
if (m_pvisibleGeoBolt)
{
m_pvvBoltP1->SetValue(p1);
m_pvvBoltP2->SetValue(p2);
}
else
{
m_pvvBoltP1 = new ModifiableVectorValue(p1);
m_pvvBoltP2 = new ModifiableVectorValue(p2);
m_pvisibleGeoBolt =
new VisibleGeo(
CreateBoltGeo(
m_pvvBoltP1,
m_pvvBoltP2,
0.125f,
GetModeler()->LoadSurface("lightningbmp", true)
)
);
m_pmodel->GetCluster()->GetClusterSite()->GetGroupScene()->AddGeo(m_pvisibleGeoBolt);
}
}
}
virtual void DeactivateBolt(void)
{
if (m_pvisibleGeoBolt) {
m_pvisibleGeoBolt->SetEmpty();
m_pvisibleGeoBolt = NULL;
}
}
virtual int GetMask(void) const
{
return m_mask;
}
virtual void SetMask(int mask)
{
m_mask = mask;
}
virtual void OrMask(int mask)
{
m_mask |= mask;
}
virtual void AndMask(int mask)
{
m_mask &= mask;
}
virtual void XorMask(int mask)
{
m_mask ^= mask;
}
void UpdateSounds(DWORD dwElapsedTime)
{
if (m_pSoundSite)
m_pSoundSite->UpdateSounds(dwElapsedTime);
m_bPlayedHitSoundThisFrame = false;
};
void StopSounds()
{
if (m_pSoundSite)
m_pSoundSite->StopSounds();
};
TRef<ISoundPositionSource> GetSoundSource()
{
if (!m_pSoundSite)
m_pSoundSite = new SoundSite(m_pmodel);
return m_pSoundSite->GetSoundSource();
};
TRef<ISoundPositionSource> GetSoundSource(const Vector& vectOffset)
{
if (!m_pSoundSite)
m_pSoundSite = new SoundSite(m_pmodel);
return m_pSoundSite->GetSoundSource(vectOffset);
};
void RegisterHit(float fAmount, const Vector& vectOffset, bool bAbsorbedByShield = false)
{
assert(m_bIsShip);
if (!m_bPlayedHitSoundThisFrame)
{
m_bPlayedHitSoundThisFrame = true;
SoundID soundId;
if (m_pmodel == trekClient.GetShip()->GetSourceShip())
{
if (bAbsorbedByShield)
soundId = myShieldHitSound;
else
soundId = myHullHitSound;
}
else
{
if (bAbsorbedByShield)
soundId = otherShieldHitSound;
else
soundId = otherHullHitSound;
}
TRef<ISoundPositionSource> psource = GetSoundSource(vectOffset);
m_pSoundSite->AddHitSound(trekClient.StartSound(soundId, psource));
}
}
TRef<ClusterSite> GetClusterSite()
{
return m_pmodel->GetCluster()->GetClusterSite();
}
private:
TRef<BuildEffectGeo> m_pbuildEffectGeo;
TRef<TEvent<float>::SourceImpl> m_peventSourceAleph;
SideVisibility m_sideVisibility;
TRef<VisibleGeo> m_pvisibleGeoBolt;
TRef<ThingGeo> m_pthing;
TRef<Geo> m_pthingGeo;
TRef<DecalGeo> m_pdecal;
TRef<BuildEffectGeo> m_pbuildeffect;
TRef<MineFieldGeo> m_pmineFieldGeo;
ImodelIGC* m_pmodel;
Point m_pointScreenPosition;
TRef<ModifiableVectorValue> m_pvvBoltP1;
TRef<ModifiableVectorValue> m_pvvBoltP2;
float m_fScreenRadius;
float m_radius;
float m_distanceToEdge;
int m_mask;
bool m_bSideVisibility;
unsigned char m_ucRadarState;
bool m_bIsShip;
bool m_bPlayedHitSoundThisFrame;
SoundSite* m_pSoundSite;
};
const float c_fGrooveLevelDuration = 10.0f;
WinTrekClient::WinTrekClient(void)
:
mountSelected(-1),
fGroupFire(true),
wmOld(0),
bInitTrekThrottle (true),
joyThrottle(true),
trekThrottle(-1.0f),
fOldJoyThrottle (-1.0f),
m_sideidLastWinner(NA),
m_bWonLastGame(false),
m_bLostLastGame(false),
m_nNumEndgamePlayers(0),
m_nNumEndgameSides(0),
m_vplayerEndgameInfo(NULL),
m_nGrooveLevel(0),
m_bDisconnected(false),
m_strDisconnectReason(""),
m_bFilterChatsToAll(false),
m_bFilterQuickComms(false),
m_bFilterUnknownChats(true), m_dwFilterLobbyChats(3) {
HKEY hKey;
if (ERROR_SUCCESS == ::RegCreateKeyEx(HKEY_LOCAL_MACHINE,
ALLEGIANCE_REGISTRY_KEY_ROOT,
0, "", REG_OPTION_NON_VOLATILE, KEY_READ, NULL, &hKey, NULL))
{
DWORD dwSize = c_cbCDKey;
DWORD dwType;
char szCDKey[c_cbCDKey];
if (::RegQueryValueEx(hKey, "CDKey", NULL, &dwType,
(unsigned char*)szCDKey, &dwSize) == ERROR_SUCCESS
&& dwType == REG_SZ && dwSize != 0)
{
BaseClient::SetCDKey(szCDKey);
}
::RegCloseKey(hKey);
}
}
WinTrekClient::~WinTrekClient(void)
{
if (m_vplayerEndgameInfo)
delete m_vplayerEndgameInfo;
}
void WinTrekClient::Initialize(Time timeNow)
{
BaseClient::Initialize(timeNow);
GetShip()->CreateDamageTrack();
m_pwindow = GetWindow();
m_pengine = m_pwindow->GetEngine();
m_pmodeler = m_pwindow->GetModeler();
{
TRef<Surface> psurfaceFlare = m_pmodeler->LoadSurface(AWF_SHIELD_FLARE_TEXTURE, true);
ZAssert(psurfaceFlare);
m_pimageFlare = new AnimatedImage(m_pwindow->GetTime(), psurfaceFlare);
}
{
TRef<INameSpace> pns = m_pmodeler->GetNameSpace(AWF_SHIELD_FLARE);
if (pns) {
CastTo(m_pgeoFlares[0], pns->FindMember("lens30"));
CastTo(m_pgeoFlares[1], pns->FindMember("lens60"));
CastTo(m_pgeoFlares[2], pns->FindMember("lens90"));
}
}
m_pimageShockWave = GetModeler()->LoadImage(AWF_SHOCKWAVE, true);
m_vpimageExplosion[0].SetCount(5);
m_vpimageExplosion[0].Set(0, LoadExplosionImage(AWF_EXPLOSION_00));
m_vpimageExplosion[0].Set(1, LoadExplosionImage(AWF_EXPLOSION_01));
m_vpimageExplosion[0].Set(2, LoadExplosionImage(AWF_EXPLOSION_02));
m_vpimageExplosion[0].Set(3, LoadExplosionImage(AWF_EXPLOSION_03));
m_vpimageExplosion[0].Set(4, LoadExplosionImage(AWF_EXPLOSION_04));
m_vpimageExplosion[1].SetCount(1);
m_vpimageExplosion[1].Set(0, m_vpimageExplosion[0][3]);
m_vpimageExplosion[2].SetCount(1);
m_vpimageExplosion[2].Set(0, m_vpimageExplosion[0][0]);
m_vpimageExplosion[3].SetCount(2);
m_vpimageExplosion[3].Set(0, m_vpimageExplosion[0][4]);
m_vpimageExplosion[3].Set(1, m_vpimageExplosion[0][1]);
m_vpimageExplosion[4].SetCount(2);
m_vpimageExplosion[4].Set(0, m_vpimageExplosion[0][4]);
m_vpimageExplosion[4].Set(1, m_vpimageExplosion[0][1]);
m_vpimageExplosion[5].SetCount(2);
m_vpimageExplosion[5].Set(0, m_vpimageExplosion[0][4]);
m_vpimageExplosion[5].Set(1, m_vpimageExplosion[0][2]);
m_vpimageExplosion[6].SetCount(1);
m_vpimageExplosion[6].Set(0, m_vpimageExplosion[0][3]);
m_vpimageExplosion[7].SetCount(2);
m_vpimageExplosion[7].Set(0, m_vpimageExplosion[0][4]);
m_vpimageExplosion[7].Set(1, m_vpimageExplosion[0][2]);
}
TRef<AnimatedImage> WinTrekClient::LoadExplosionImage(const ZString& str)
{
return new AnimatedImage(new Number(0.0f), GetModeler()->LoadSurface(str, true));
}
void WinTrekClient::Terminate(void)
{
m_pgeoFlares[2] = NULL;
m_pgeoFlares[1] = NULL;
m_pgeoFlares[0] = NULL;
m_pimageFlare = NULL;
m_pmodeler = NULL;
m_pengine = NULL;
m_pwindow = NULL;
m_psoundAmbient = NULL;
m_psoundMissileWarning = NULL;
BaseClient::Terminate();
}
ImissionIGC* WinTrekClient::ResetStaticData (void)
{
Time now = m_pCoreIGC->GetLastUpdate ();
FlushGameState();
m_pCoreIGC = CreateMission();
Initialize(now);
m_pMissionInfo = new MissionInfo(static_cast<DWORD> (m_pCoreIGC->GetMissionID ()));
return m_pCoreIGC;
}
IpartIGC* WinTrekClient::GetCargoPart(void)
{
assert (mountSelected < 0 && mountSelected >= -c_maxCargo);
IpartIGC* ppart = GetShip()->GetMountedPart(NA, mountSelected);
if (mountSelected < -1) {
mountSelected++;
NextCargoPart();
ppart = GetShip()->GetSourceShip()->GetMountedPart(NA, mountSelected);
}
return ppart;
}
void WinTrekClient::NextCargoPart(void)
{
bool bFoundPart = false;
do
{
--mountSelected;
if (mountSelected < -c_maxCargo)
mountSelected = -1;
IpartIGC *ppart = GetShip()->GetSourceShip()->GetMountedPart(NA, mountSelected);
IpartTypeIGC *ppartType = ppart ? ppart->GetPartType() : NULL;
bFoundPart = true;
ObjectType ot = ppart ? ppart->GetObjectType() : NA;
if (ppart == NULL || ot == OT_pack || ot == OT_magazine || ot == OT_dispenser)
{
for (Mount mountPrev = mountSelected + 1; mountPrev < 0; ++mountPrev)
{
IpartIGC *ppartPrev = GetShip()->GetSourceShip()->GetMountedPart(NA, mountPrev);
IpartTypeIGC *ppartTypePrev = ppartPrev ? ppartPrev->GetPartType() : NULL;
if (ppartType == ppartTypePrev)
{
bFoundPart = false;
break;
}
}
}
}
while (!bFoundPart);
}
Mount WinTrekClient::GetSelectedCargoMount()
{
assert (mountSelected < 0 && mountSelected >= -c_maxCargo);
IpartIGC* ppart = GetShip()->GetSourceShip()->GetMountedPart(NA, mountSelected);
if (mountSelected < -1 && !ppart)
{
mountSelected++;
NextCargoPart();
}
return mountSelected;
}
void WinTrekClient::OnReload(IpartIGC* ppart, bool bConsumed)
{
if (bConsumed && ppart == GetCargoPart())
{
NextCargoPart();
GetCore()->GetIgcSite()->LoadoutChangeEvent(GetShip(), ppart, c_lcCargoSelectionChanged);
}
}
bool WinTrekClient::SelectCargoPartOfType(EquipmentType et, PartMask maxPartMask, IpartTypeIGC* pptNotThis)
{
IpartIGC* ppartStart = GetCargoPart();
if (ppartStart && (
(ppartStart->GetEquipmentType() != et) ||
((ppartStart->GetPartType()->GetPartMask() & ~maxPartMask) != 0) ||
(ppartStart->GetPartType() == pptNotThis))
|| (!ppartStart && !pptNotThis))
{
IpartIGC* ppart;
do
{
NextCargoPart();
ppart = GetCargoPart();
}
while (ppart != ppartStart
&& (
ppart && (
ppart->GetEquipmentType() != et
|| ((ppart->GetPartType()->GetPartMask() & ~maxPartMask) != 0)
|| ppart->GetPartType() == pptNotThis)
|| (!ppart && !pptNotThis)
)
);
if (ppart == ppartStart)
{
return false;
}
return true;
}
else
{
return true;
}
}
void WinTrekClient::LoadoutChangeEvent(IshipIGC* pship, IpartIGC* ppart, LoadoutChange lc)
{
if (pship == trekClient.GetShip())
{
if (lc == c_lcHullChange)
{
GetWindow()->ResetCameraFOV();
}
}
BaseClient::LoadoutChangeEvent(pship, ppart, lc);
}
IObject* WinTrekClient::LoadRadarIcon(const char* szName)
{
Surface* psurface;
if (szName && (szName[0] != '\0'))
{
psurface = GetModeler()->LoadSurface(ZString(szName) + "bmp", true);
assert (psurface);
}
else
psurface = NULL;
return psurface;
}
void WinTrekClient::ChangeCluster(IshipIGC* pship, IclusterIGC* pclusterOld, IclusterIGC* pclusterNew)
{
if (pship == GetShip())
{
if (pclusterOld && m_fm.IsConnected())
pclusterOld->SetActive(false);
BaseClient::ChangeCluster(pship, pclusterOld, pclusterNew);
if (pclusterNew && m_fm.IsConnected())
pclusterNew->SetActive(true);
if (pclusterOld && (pclusterOld != GetViewCluster()))
{
for (ModelLinkIGC* pml = pclusterOld->GetModels()->first(); (pml != NULL); pml = pml->next())
{
ImodelIGC* pmodel = pml->data();
ThingSite* pts = pmodel->GetThingSite();
if (pts)
{
((ThingSiteImpl*)pts)->StopSounds();
}
}
}
for (Command i = 0; i < c_cmdMax; i++)
{
ImodelIGC* ptarget = pship->GetCommandTarget(i);
if (ptarget && ptarget->GetObjectType() == OT_buoy
&& ((IbuoyIGC*)ptarget)->GetBuoyType() == c_buoyCluster
&& ((IbuoyIGC*)ptarget)->GetCluster() == pclusterNew)
{
pship->SetCommand(i, NULL, c_cidNone);
}
}
GetWindow()->SetCluster(pclusterNew);
GetWindow()->PositionCommandView(NULL, 0.0f);
trekClient.GetClientEventSource()->OnClusterChanged(pclusterNew);
}
}
void WinTrekClient::ChangeStation(IshipIGC* pship, IstationIGC* pstationOld, IstationIGC* pstationNew)
{
if (pship == GetShip() && trekClient.MyMission()->GetStage() == STAGE_STARTED)
{
if (pstationNew)
{
if (pstationOld == NULL)
{
ConsoleImage* pconsole = GetWindow()->GetConsoleImage();
if (pconsole)
{
pconsole->SetDisplayMDL(pstationNew->GetSide()->GetCivilization()->GetHUDName());
if ((trekClient.GetShip()->GetParentShip() == NULL) && !trekClient.GetShip()->IsGhost())
{
trekClient.RestoreLoadout(pstationNew);
}
}
if (GetWindow()->screen() == ScreenIDCombat)
{
trekClient.wmOld = 0;
if (GetWindow()->GetCameraMode() != TrekWindow::cmExternalOverride)
{
if ((!Training::IsTraining ()) || (Training::GetTrainingMissionID () != Training::c_TM_5_Command_View))
{
GetWindow()->SetViewMode(trekClient.GetShip()->IsGhost()
? TrekWindow::vmCommand : TrekWindow::vmHangar);
PlaySoundEffect(dockedSound);
PlaySoundEffect(salWelcomeHomeSound);
}
}
}
}
else
{
}
}
else
{
assert (pstationOld);
assert (pstationOld);
IshipIGC* pshipSource = trekClient.GetShip()->GetSourceShip();
assert (pshipSource);
IhullTypeIGC* pht = pshipSource->GetBaseHullType();
assert (pht);
pstationOld->RepairAndRefuel(pshipSource);
RequestViewCluster(NULL);
GetWindow()->OverrideCamera(trekClient.m_now, pstationOld, false);
OverrideThrottle (1.0f);
trekClient.GetShip()->SetStateBits(coastButtonIGC, 0);
}
}
}
void WinTrekClient::OverrideCamera(ImodelIGC* pmodel)
{
GetWindow()->OverrideCamera(trekClient.m_now, pmodel, false);
}
void WinTrekClient::TargetKilled(ImodelIGC* pmodel)
{
ImodelIGC* pmodelCurrent = trekClient.GetShip()->GetCommandTarget(c_cmdCurrent);
if (pmodel == pmodelCurrent)
{
IshipIGC* pshipSource = trekClient.GetShip()->GetSourceShip();
if (pshipSource->GetCluster())
{
extern int GetSimilarTargetMask(ImodelIGC* pmodel);
int mask = GetSimilarTargetMask(pmodel) | c_ttNearest;
int abm;
if (mask == (c_ttShip | c_ttEnemy | c_ttNearest))
abm = c_habmRescue;
else
abm = 0;
ImodelIGC* pmodelTarget = FindTarget(pshipSource,
mask,
pmodel, NULL, NULL, NULL, abm);
if ((pmodelTarget == NULL) && abm)
{
pmodelTarget = FindTarget(pshipSource,
mask,
pmodel, NULL, NULL, NULL, c_habmMiner | c_habmBuilder);
if (pmodelTarget == NULL)
pmodelTarget = FindTarget(pshipSource,
mask,
pmodel);
}
if (pmodelTarget == pmodel)
pmodelTarget = NULL;
GetWindow()->SetTarget(pmodelTarget, c_cidDefault);
if (trekClient.autoPilot() && (trekClient.GetShip()->GetCommandTarget(c_cmdPlan) == pmodel))
trekClient.SetAutoPilot(true);
}
}
}
void WinTrekClient::ShipWarped(IshipIGC* pship,
SectorID sidOld,
SectorID sidNew)
{
}
void WinTrekClient::PostNotificationText(ImodelIGC* pmodel, bool bCritical, const char* pszText, ...)
{
if (GetWindow()->GetConsoleImage() && pmodel == trekClient.GetShip())
{
assert (pszText);
const size_t size = 256;
char bfr[size];
va_list vl;
va_start(vl, pszText);
_vsnprintf(bfr, size, pszText, vl);
va_end(vl);
if (bCritical)
{
PlaySoundEffect(newCriticalMsgSound);
GetWindow()->GetConsoleImage()->GetConsoleData()->SetCriticalTipText(bfr);
}
else
{
PlaySoundEffect(newNonCriticalMsgSound);
GetWindow()->GetConsoleImage()->GetConsoleData()->SetTipText(bfr);
}
}
}
void WinTrekClient::ActivateTeleportProbe(IprobeIGC* pprobe)
{
IsideIGC* pside = pprobe->GetSide();
IclusterIGC* pcluster = pprobe->GetCluster();
if (pside != trekClient.GetSide())
{
assert (pside);
PostText(true, START_COLOR_STRING "%s %s" END_COLOR_STRING " active in %s",
(PCC) ConvertColorToString (pside->GetColor ()), pside->GetName(), GetModelName(pprobe), pcluster->GetName());
}
else
{
PostText(true, "%s active in %s", GetModelName(pprobe), pcluster->GetName());
}
}
void WinTrekClient::DestroyTeleportProbe(IprobeIGC* pprobe)
{
IsideIGC* pside = pprobe->GetSide();
IsideIGC* psideMe = trekClient.GetSide();
IclusterIGC* pcluster = pprobe->GetCluster();
if (pside != psideMe)
{
assert (pside);
ClusterSite* pcs = pcluster->GetClusterSite();
AssetMask am = pcs->GetClusterAssetMask() & ~c_amEnemyTeleport;
{
for (ProbeLinkIGC* ppl = pcluster->GetProbes()->first(); (ppl != NULL); ppl = ppl->next())
{
IprobeIGC* pp = ppl->data();
if ((pp != pprobe) && (pp->GetSide() != psideMe) && pp->GetProbeType()->HasCapability(c_eabmRipcord))
am |= c_amEnemyTeleport;
}
}
pcs->SetClusterAssetMask(am);
PostText(false, START_COLOR_STRING "%s %s" END_COLOR_STRING " in %s was destroyed",
(PCC) ConvertColorToString (pside->GetColor ()), pside->GetName(), GetModelName(pprobe), pcluster->GetName());
}
else
{
PostText(true, "%s in %s was destroyed", GetModelName(pprobe), pcluster->GetName());
}
}
void WinTrekClient::PostText(bool bCritical, const char* pszText, ...)
{
if (GetWindow()->GetConsoleImage())
{
assert (pszText);
const size_t size = 256;
char bfr[size];
va_list vl;
va_start(vl, pszText);
_vsnprintf(bfr, size, pszText, vl);
va_end(vl);
if (bCritical)
{
PlaySoundEffect(newCriticalMsgSound);
GetWindow()->GetConsoleImage()->GetConsoleData()->SetCriticalTipText(bfr);
}
else
{
PlaySoundEffect(newNonCriticalMsgSound);
GetWindow()->GetConsoleImage()->GetConsoleData()->SetTipText(bfr);
}
}
}
void WinTrekClient::EjectPlayer(ImodelIGC* pcredit)
{
GetWindow()->OverrideCamera(trekClient.m_now, pcredit, true);
GetWindow()->TriggerMusic(deathMusicSound);
}
ZString WinTrekClient::GetSavedCharacterName()
{
HKEY hKey;
DWORD dwType;
DWORD cbName = c_cbName;
char szName[c_cbName];
szName[0] = '\0';
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, ALLEGIANCE_REGISTRY_KEY_ROOT, 0, KEY_READ, &hKey))
{
RegQueryValueEx(hKey, "CharacterName", NULL, &dwType, (unsigned char*)&szName, &cbName);
RegCloseKey(hKey);
}
return szName;
}
void WinTrekClient::SaveCharacterName(ZString strName)
{
HKEY hKey;
DWORD cbName = c_cbName;
char szName[c_cbName];
szName[0] = '\0';
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, ALLEGIANCE_REGISTRY_KEY_ROOT, 0, KEY_WRITE, &hKey))
{
RegSetValueEx(hKey, "CharacterName", NULL, REG_SZ,
(const BYTE*)(const char*)strName, strName.GetLength() + 1);
RegCloseKey(hKey);
}
}
ZString WinTrekClient::CfgGetCoreName(const char *s)
{
char temp[c_cbName];
DWORD l = GetCfgInfo().GetCfgProfileString("Cores",s,s,temp,c_cbName);
return ZString(temp,(int)l);
}
bool WinTrekClient::CfgIsOfficialCore(const char *s)
{
char temp[c_cbName];
DWORD l = GetCfgInfo().GetCfgProfileString("OfficialCores",s,"false",temp,c_cbName);
return (_stricmp(temp,"true") == 0);
}
bool WinTrekClient::CfgIsOfficialServer(const char *name, const char *addr)
{
char temp[c_cbName];
DWORD l = GetCfgInfo().GetCfgProfileString("OfficialServers",name,"",temp,c_cbName);
return (_stricmp(temp,addr) == 0);
}
class AutoDownloadProgressDialogPopup :
public IPopup,
public EventTargetContainer<AutoDownloadProgressDialogPopup>,
public IIntegerEventSink,
public IAutoUpdateSink
{
private:
TRef<Pane> m_ppane;
TRef<ButtonPane> m_pbuttonAbort;
TRef<StringPane> m_pstrpaneCurrentFile;
TRef<StringPane> m_pstrpaneApproxMinutes;
TRef<ModifiableNumber> m_pModifiableNumberFileListPercent;
TRef<ModifiableNumber> m_pModifiableNumberVerifyPercent;
TRef<ModifiableNumber> m_pModifiableNumberDownloadPercent;
TRef<IMessageBox> m_pmsgBox;
unsigned long m_cGrandTotalBytes; int m_cFilesCompleted;
unsigned long m_cTotalFiles;
const char* m_szPrevCurrentFile; bool m_bAborted;
IAutoUpdateSink * m_pSink;
bool m_bConnectToLobby; public:
AutoDownloadProgressDialogPopup(IAutoUpdateSink * pSink, bool bConnectToLobby) :
m_cFilesCompleted(0),
m_bAborted(false),
m_pmsgBox(NULL),
m_szPrevCurrentFile(NULL),
m_bConnectToLobby(bConnectToLobby),
m_pSink(pSink)
{
TRef<INameSpace> pnsData = GetModeler()->CreateNameSpace("autodownloaddialogdata");
pnsData->AddMember("FileListPercentDone", m_pModifiableNumberFileListPercent = new ModifiableNumber(0.0f));
pnsData->AddMember("VerifyPercentDone", m_pModifiableNumberVerifyPercent = new ModifiableNumber(0.0f));
pnsData->AddMember("DownloadPercentDone", m_pModifiableNumberDownloadPercent = new ModifiableNumber(0.0f));
Modeler* pmodeler = GetModeler();
TRef<INameSpace> pns = pmodeler->GetNameSpace("autodownloaddialog");
CastTo(m_ppane, pns->FindMember("AutoDownloadDialog" ));
CastTo(m_pbuttonAbort, pns->FindMember("AutoDownloadAbortButton" ));
CastTo(m_pstrpaneCurrentFile, pns->FindMember("AutoDownloadCurrentFileStringPane" ));
CastTo(m_pstrpaneApproxMinutes, pns->FindMember("AutoDownloadApproxMinutes" ));
AddEventTarget(&AutoDownloadProgressDialogPopup::OnButtonAbort, m_pbuttonAbort->GetEventSource());
pmodeler->UnloadNameSpace(pns);
}
virtual ~AutoDownloadProgressDialogPopup()
{
}
Pane* GetPane()
{
return m_ppane;
}
bool OnButtonAbort()
{
if(trekClient.m_pAutoDownload)
trekClient.m_pAutoDownload->Abort();
return true;
}
void OnBeginDownloadProgressBar(unsigned cTotalBytes, int cFiles)
{
m_cGrandTotalBytes = cTotalBytes;
m_cTotalFiles = cFiles;
};
virtual void OnAutoUpdateSystemTermination(bool bErrorOccurred, bool bRestarting)
{
if(m_pSink)
m_pSink->OnAutoUpdateSystemTermination(bErrorOccurred, bRestarting);
trekClient.m_pAutoDownload = NULL;
if (!bErrorOccurred)
{
m_pModifiableNumberFileListPercent->SetValue(1.0f);
m_pModifiableNumberFileListPercent->Update();
m_pModifiableNumberVerifyPercent->SetValue(1.0f);
m_pModifiableNumberVerifyPercent->Update();
m_pModifiableNumberDownloadPercent->SetValue(1.0f);
m_pModifiableNumberDownloadPercent->Update();
if (bRestarting)
{
GetWindow()->SetWaitCursor();
m_pmsgBox = CreateMessageBox("Restarting to complete update...", NULL, false);
GetWindow()->GetPopupContainer()->OpenPopup(m_pmsgBox, false);
}
else
{
if(m_bConnectToLobby)
trekClient.ConnectToLobby(NULL);
GetWindow()->GetPopupContainer()->ClosePopup(m_pmsgBox);
GetWindow()->RestoreCursor();
}
}
}
virtual void OnUserAbort()
{
m_bAborted = true;
if(m_pmsgBox != NULL)
return;
m_pmsgBox = CreateMessageBox("AutoUpdate Aborted. ");
m_pmsgBox->GetEventSource()->AddSink(IIntegerEventSink::CreateDelegate(this));
Point point(c_PopupX, c_PopupY);
Rect rect(point, point);
GetWindow()->GetPopupContainer()->OpenPopup(m_pmsgBox, rect, false);
};
virtual void OnRetrievingFileListProgress(unsigned long nFileSize, unsigned long cCurrentBytes)
{
debugf("FileList.txt %d out of %d \n", cCurrentBytes, nFileSize);
m_pModifiableNumberFileListPercent->SetValue(float(cCurrentBytes)/float(nFileSize));
m_pModifiableNumberFileListPercent->Update();
}
virtual void OnAnalysisProgress(float fPercentDone)
{
debugf("Verify %3.3f%% \n", 100.0f*fPercentDone);
m_pModifiableNumberVerifyPercent->SetValue(float(fPercentDone));
m_pModifiableNumberVerifyPercent->Update();
}
bool ShouldFilterFile(const char * szFileName)
{
#ifdef DEBUG
if (_stricmp(szFileName, "AllegianceRetail.exe") == 0 ||
_stricmp(szFileName, "AllegianceRetail.pdb") == 0 ||
_stricmp(szFileName, "AllegianceRetail.map") == 0 ||
_stricmp(szFileName, "AllegianceRetail.sym") == 0)
return true;
#endif
#ifdef OPTIMIZED
if (_stricmp(szFileName, "AllegianceDebug.exe") == 0 ||
_stricmp(szFileName, "AllegianceDebug.pdb") == 0 ||
_stricmp(szFileName, "AllegianceDebug.map") == 0 ||
_stricmp(szFileName, "AllegianceDebug.sym") == 0)
return true;
#endif
#if !defined(OPTIMIZED) || !defined(DEBUG)
if (_stricmp(szFileName, "AllegianceTest.exe") == 0 ||
_stricmp(szFileName, "AllegianceTest.pdb") == 0 ||
_stricmp(szFileName, "AllegianceTest.map") == 0 ||
_stricmp(szFileName, "AllegianceTest.sym") == 0)
return true;
#endif
return false;
}
virtual void OnProgress(unsigned long cTotalBytes, const char* szCurrentFile, unsigned long cCurrentFileBytes, unsigned nEstimatedSecondsLeft)
{
#ifdef DEBUG
char sz[80];
sprintf(sz, "%2.2f%% %i %s %i\n", 100.0f*float(cTotalBytes)/float(m_cGrandTotalBytes), cTotalBytes, szCurrentFile, cCurrentFileBytes);
OutputDebugString(sz);
#endif
if (szCurrentFile != NULL && szCurrentFile != m_szPrevCurrentFile)
{
m_cFilesCompleted++;
char szBuffer[15];
sprintf(szBuffer, " (%i/%i)", m_cFilesCompleted, m_cTotalFiles);
m_pstrpaneCurrentFile->SetString(ZString(szCurrentFile) + ZString(szBuffer));
m_szPrevCurrentFile = szCurrentFile;
}
if (nEstimatedSecondsLeft != -1 &&
m_pstrpaneApproxMinutes) m_pstrpaneApproxMinutes->SetString(ZString("Min Left ") + ZString((((int)nEstimatedSecondsLeft-1)/60)+1));
m_pModifiableNumberDownloadPercent->SetValue(float(cTotalBytes)/float(m_cGrandTotalBytes));
m_pModifiableNumberDownloadPercent->Update();
}
virtual void OnError(char * szErrorMessage)
{
char * szBuffer = new char[strlen(szErrorMessage) + 100];
sprintf(szBuffer, "AutoUpdate Error \n%s ", szErrorMessage);
assert(m_pmsgBox == NULL);
m_pmsgBox = CreateMessageBox(szBuffer);
m_pmsgBox->GetEventSource()->AddSink(IIntegerEventSink::CreateDelegate(this));
Point point(150, 8); Rect rect(point, point);
GetWindow()->GetPopupContainer()->OpenPopup(m_pmsgBox, rect, false);
delete[] szBuffer;
}
bool OnEvent(IIntegerEventSource* pevent, int value)
{
assert(m_pmsgBox);
GetWindow()->GetPopupContainer()->ClosePopup(m_pmsgBox);
return false;
}
};
IAutoUpdateSink * WinTrekClient::OnBeginAutoUpdate(IAutoUpdateSink * pSink, bool bConnectToLobby)
{
if (!GetWindow()->GetPopupContainer()->IsEmpty())
GetWindow()->GetPopupContainer()->ClosePopup(NULL);
GetWindow()->RestoreCursor();
m_pAutoDownloadProgressDialogPopup = new AutoDownloadProgressDialogPopup(pSink, bConnectToLobby);
Point point(150, 8); Rect rect(point, point);
GetWindow()->GetPopupContainer()->OpenPopup(m_pAutoDownloadProgressDialogPopup, rect, false);
return m_pAutoDownloadProgressDialogPopup;
}
bool WinTrekClient::ShouldCheckFiles()
{
extern bool g_bCheckFiles;
bool bTemp = g_bCheckFiles;
g_bCheckFiles = false; return bTemp;
}
void WinTrekClient::CreateMissionReq()
{
GetWindow()->SetWaitCursor();
TRef<IMessageBox> pmsgBox = CreateMessageBox("Creating a game...", NULL, false);
GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, false);
BaseClient::CreateMissionReq();
}
void WinTrekClient::ServerListReq()
{
GetWindow()->SetWaitCursor();
TRef<IMessageBox> pmsgBox = CreateMessageBox("Asking about servers and cores...", NULL, false);
GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, false);
BaseClient::ServerListReq();
}
void WinTrekClient::CreateMissionReq(const char *szServer,const char *szAddr, const char *szIGCStaticFile, const char *szGameName)
{
GetWindow()->SetWaitCursor();
TRef<IMessageBox> pmsgBox = CreateMessageBox("Creating a game...", NULL, false);
GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, false);
BaseClient::CreateMissionReq(szServer,szAddr,szIGCStaticFile,szGameName);
}
void WinTrekClient::JoinMission(MissionInfo * pMission, const char* szMissionPassword)
{
GetWindow()->SetWaitCursor();
TRef<IMessageBox> pmsgBox = CreateMessageBox("Joining the game...", NULL, false);
GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, false);
BaseClient::JoinMission(pMission, szMissionPassword);
}
void WinTrekClient::OnLogonAck(bool fValidated, bool bRetry, LPCSTR szFailureReason)
{
if (GetWindow()->GetPopupContainer() && !GetWindow()->GetPopupContainer()->IsEmpty())
GetWindow()->GetPopupContainer()->ClosePopup(NULL);
GetWindow()->RestoreCursor();
if (fValidated)
{
GetClientEventSource()->OnLogonGameServer();
}
else
{
Disconnect();
GetClientEventSource()->OnLogonGameServerFailed(bRetry, szFailureReason);
g_bQuickstart = false;
}
}
void WinTrekClient::OnLogonLobbyAck(bool fValidated, bool bRetry, LPCSTR szFailureReason)
{
if (GetWindow()->GetPopupContainer() && !GetWindow()->GetPopupContainer()->IsEmpty())
GetWindow()->GetPopupContainer()->ClosePopup(NULL);
GetWindow()->RestoreCursor();
if (!fValidated)
{
DisconnectLobby();
GetClientEventSource()->OnLogonLobbyFailed(bRetry, szFailureReason);
g_bQuickstart = false;
}
else
{
GetClientEventSource()->OnLogonLobby();
}
}
void WinTrekClient::OnLogonClubAck(bool fValidated, bool bRetry, LPCSTR szFailureReason)
{
if (GetWindow()->GetPopupContainer() && !GetWindow()->GetPopupContainer()->IsEmpty())
GetWindow()->GetPopupContainer()->ClosePopup(NULL);
GetWindow()->RestoreCursor();
if (!fValidated)
{
DisconnectClub();
GetClientEventSource()->OnLogonClubFailed(bRetry, szFailureReason);
g_bQuickstart = false;
}
else
{
GetClientEventSource()->OnLogonClub();
}
}
void WinTrekClient::Disconnect(void)
{
BaseClient::Disconnect();
m_bDisconnected = true;
}
HRESULT WinTrekClient::OnSessionLost(char* szReason, FedMessaging * pthis)
{
m_strDisconnectReason = "";
BaseClient::OnSessionLost(szReason, pthis);
if (MyMission())
{
if (GetSide() && GetSideID() != SIDE_TEAMLOBBY)
RemovePlayerFromSide(MyPlayerInfo(), QSR_LinkDead);
}
if (pthis == &m_fm)
{
ZString strMsg = "Your connection to the game server was lost.\n"
"Reason: " + ZString(szReason) + ".\n";
if (trekClient.GetIsLobbied())
{
if (!m_fmLobby.IsConnected())
{
GetWindow()->screen(ScreenIDGameScreen);
m_strDisconnectReason = strMsg;
}
else
{
assert(GetWindow()->screen() == ScreenIDGameScreen);
if (GetWindow()->GetPopupContainer() && !GetWindow()->GetPopupContainer()->IsEmpty())
GetWindow()->GetPopupContainer()->ClosePopup(NULL);
GetWindow()->RestoreCursor();
TRef<IMessageBox> pmsgBox =
CreateMessageBox(
"Your connection to the game server was lost.\n"
"Reason: " + ZString(szReason) + ".\n"
);
GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, false);
}
}
else
{
if (GetWindow()->GetPopupContainer() && !GetWindow()->GetPopupContainer()->IsEmpty())
GetWindow()->GetPopupContainer()->ClosePopup(NULL);
GetWindow()->RestoreCursor();
if (Training::GetTrainingMissionID () == Training::c_TM_7_Live)
GetWindow()->screen(ScreenIDTrainScreen);
else
GetWindow()->screen(ScreenIDIntroScreen);
TRef<IMessageBox> pmsgBox = CreateMessageBox(strMsg);
GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, false);
}
}
else if (pthis == &m_fmClub)
{
if (GetWindow()->GetPopupContainer() && !GetWindow()->GetPopupContainer()->IsEmpty())
GetWindow()->GetPopupContainer()->ClosePopup(NULL);
GetWindow()->RestoreCursor();
GetWindow()->screen(ScreenIDZoneClubScreen);
TRef<IMessageBox> pmsgBox =
CreateMessageBox(
"Your connection to the Club server was lost.\n"
"Reason: " + ZString(szReason) + ".\n"
);
GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, false);
}
else if (pthis == &m_fmLobby)
{
if (GetWindow()->GetPopupContainer() && !GetWindow()->GetPopupContainer()->IsEmpty())
GetWindow()->GetPopupContainer()->ClosePopup(NULL);
GetWindow()->RestoreCursor();
GetWindow()->screen(ScreenIDZoneClubScreen);
TRef<IMessageBox> pmsgBox =
CreateMessageBox(
"Your connection to the lobby server was lost.\n"
"Reason: " + ZString(szReason) + ".\n"
);
GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, false);
Disconnect();
}
else
assert(false);
if (MyMission())
{
RemovePlayerFromMission(MyPlayerInfo(), QSR_LinkDead);
}
return S_OK;
}
void WinTrekClient::FlushSessionLostMessage()
{
if (!m_strDisconnectReason.IsEmpty())
{
TRef<IMessageBox> pmsgBox = CreateMessageBox(m_strDisconnectReason);
m_strDisconnectReason = "";
GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, false);
}
}
bool WinTrekClient::OnEvent(IIntegerEventSource* pevent, int value)
{
Win32App::Exit(value);
return true;
}
#ifndef NO_MSG_CRC
void WinTrekClient::OnBadCRC(FedMessaging * pthis, CFMConnection & cnxn, BYTE * pMsg, DWORD cbMsg)
{
debugf("ACK! Bad crc *from* the %s!!\n", pthis == &m_fmLobby ? "Lobby" : "Server");
assert(0);
}
#endif
HRESULT WinTrekClient::OnAppMessage(FedMessaging * pthis, CFMConnection & cnxnFrom, FEDMESSAGE * pfm)
{
HRESULT hr = E_FAIL;
FEDMSGID fmid = pfm->fmid;
ZAssert(0 != fmid);
if (m_bDisconnected && pthis == &m_fm)
{
debugf("Client is disconnected - message ignored.\n");
hr = S_FALSE;
}
else
{
if (pfm->fmid == FM_S_MISSIONDEF)
{
CASTPFM(pfmMissionDef, S, MISSIONDEF, pfm);
char szAddr[16];
pthis->GetIPAddress(cnxnFrom, szAddr); strcpy_s(pfmMissionDef->szServerAddr,16,szAddr);
}
hr = HandleMsg(pfm, m_lastUpdate, m_now);
bool bWasHandled = hr == S_OK;
if (SUCCEEDED(hr) && m_fm.IsConnected())
{
hr = GetWindow()->HandleMsg(pfm, m_lastUpdate, m_now);
assert(bWasHandled || hr == S_OK);
}
}
return(hr);
}
void WinTrekClient::OverrideThrottle (float fDesiredThrottle)
{
bInitTrekThrottle = true;
trekThrottle = fDesiredThrottle;
}
void WinTrekClient::DevelopmentCompleted(IbucketIGC* b, IdevelopmentIGC* d, Time now)
{
assert (b);
IsideIGC* pside = b->GetSide();
assert (pside);
if (!m_fm.IsConnected())
{
pside->ApplyDevelopmentTechs(d->GetEffectTechs());
pside->ApplyGlobalAttributeSet(d->GetGlobalAttributeSet());
}
else if ((!d->GetTechOnly()) && d->GetEffectTechs().GetAllZero())
{
trekClient.SideDevelopmentTechChange(pside);
}
}
void WinTrekClient::StationTypeCompleted(IbucketIGC * pbucket, IstationIGC* pstation, IstationTypeIGC * pstationtype, Time now)
{
if (!m_fm.IsConnected())
{
IsideIGC * pside = pbucket->GetSide();
assert (pside);
{
IdroneTypeIGC* dt = pstationtype->GetConstructionDroneType();
IshipIGC* pship = CreateDrone(m_pCoreIGC,
trekClient.GetCore()->GenerateNewShipID(),
dt->GetPilotType(),
dt->GetName(),
dt->GetHullTypeID(),
pstation->GetSide(),
0,
dt->GetShootSkill(),
dt->GetMoveSkill(),
dt->GetBravery());
if (pship)
{
pship->SetBaseData(pstationtype);
pship->SetStation(pstation);
pstation->Launch(pship);
}
}
}
}
void WinTrekClient::BuildStation(IasteroidIGC* pasteroid, IsideIGC* pside, IstationTypeIGC* pstationtype, Time now)
{
DataStationIGC ds;
strcpy(ds.name, pstationtype->GetName());
ds.clusterID = pasteroid->GetCluster()->GetObjectID();
ds.position = pasteroid->GetPosition();
ds.forward = pasteroid->GetOrientation ().GetForward ();
ds.up = pasteroid->GetOrientation ().GetUp ();
ds.rotation.axis(ds.forward);
ds.rotation.angle(0.0f);
ds.sideID = pside->GetObjectID();
ds.stationID = m_pCoreIGC->GenerateNewStationID();
ds.stationTypeID = pstationtype->GetObjectID();
ds.bpHull = pasteroid->GetFraction();
ds.bpShield = 0.0f;
pasteroid->Terminate();
IstationIGC * pstationNew = (IstationIGC *) (m_pCoreIGC->CreateObject(now, OT_station, &ds, sizeof(ds)));
assert (pstationNew);
pstationNew->Release();
}
void WinTrekClient::LayExpendable(Time now, IexpendableTypeIGC* pet, IshipIGC* pshipLayer)
{
assert (pet);
assert (pshipLayer);
ObjectType type = pet->GetObjectType();
const Vector& position = pshipLayer->GetPosition();
IclusterIGC* pcluster = pshipLayer->GetCluster();
IsideIGC* pside = pshipLayer->GetSide();
if (type == OT_mineType)
{
DataMineIGC dm;
dm.pshipLauncher = pshipLayer;
dm.psideLauncher = pside;
dm.mineID = m_pCoreIGC->GenerateNewMineID();
dm.time0 = now;
dm.p0 = position;
dm.pminetype = (ImineTypeIGC*)pet;
assert (dm.pminetype);
dm.pcluster = pcluster;
dm.exportF = false;
ImineIGC * m = (ImineIGC*)(m_pCoreIGC->CreateObject(now, OT_mine, &dm, sizeof(dm)));
assert (m);
m->Release();
}
else
{
assert (type == OT_probeType);
DataProbeIGC dp;
dp.pside = pside;
dp.pship = NULL;
dp.pmodelTarget = NULL;
dp.probeID = m_pCoreIGC->GenerateNewProbeID();
dp.time0 = now;
dp.p0 = position;
dp.pprobetype = (IprobeTypeIGC*)pet;
assert (dp.pprobetype);
dp.pcluster = pcluster;
dp.exportF = false;
IprobeIGC * p = (IprobeIGC*)(m_pCoreIGC->CreateObject(now, OT_probe, &dp, sizeof(dp)));
assert (p);
p->Release();
}
{
const PartListIGC* parts = pshipLayer->GetParts();
PartLinkIGC* plink;
while (plink = parts->first()) plink->data()->Terminate();
}
pshipLayer->SetAmmo(0);
pshipLayer->SetFuel(0.0f);
KillShipEvent(now, pshipLayer, NULL, 0.0f, position, Vector::GetZero());
}
void WinTrekClient::DroneTypeCompleted(IbucketIGC* b, IstationIGC* pstation, IdroneTypeIGC* dt, Time now)
{
if (!m_fm.IsConnected())
{
IshipIGC* pship = CreateDrone(m_pCoreIGC,
trekClient.GetCore()->GenerateNewShipID(),
dt->GetPilotType(),
dt->GetName(),
dt->GetHullTypeID(),
pstation->GetSide(),
c_aabmMineHe3, dt->GetShootSkill(),
dt->GetMoveSkill(),
dt->GetBravery());
if (pship)
{
pship->SetStation(pstation);
pstation->Launch(pship);
}
}
}
bool WinTrekClient::ContinueRipcord(IshipIGC* pship, ImodelIGC* pmodel)
{
return true;
}
bool WinTrekClient::UseRipcord(IshipIGC* pship, ImodelIGC* pmodel)
{
assert (pmodel);
if (!m_fm.IsConnected())
{
if (pmodel->GetObjectType() == OT_station)
((IstationIGC*)pmodel)->Launch(pship);
else
{
float r = pmodel->GetRadius() + pship->GetRadius() + 25.0f;
Vector v = Vector::RandomDirection();
Orientation o(v);
IclusterIGC* pcluster = pmodel->GetCluster();
Time lastUpdate = pcluster->GetLastUpdate();
pship->SetPosition(pmodel->GetPosition() + v * r);
pship->SetVelocity(v * trekClient.m_pCoreIGC->GetFloatConstant(c_fcidExitStationSpeed));
pship->SetOrientation(o);
pship->SetCurrentTurnRate(c_axisYaw, 0.0f);
pship->SetCurrentTurnRate(c_axisPitch, 0.0f);
pship->SetCurrentTurnRate(c_axisRoll, 0.0f);
pship->SetLastUpdate(lastUpdate);
pship->SetBB(lastUpdate, lastUpdate, 0.0f);
pship->SetCluster(pcluster);
}
return true;
}
return false;
}
void WinTrekClient::SetViewCluster(IclusterIGC* pcluster, const Vector* pposition)
{
IclusterIGC* pclusterOld = trekClient.GetViewCluster();
if (pclusterOld != pcluster)
{
if (pclusterOld)
{
const ShipListIGC* ships = m_pCoreIGC->GetShips();
assert (ships);
if (m_fm.IsConnected ())
{
for (ShipLinkIGC* l = ships->first();
(l != NULL);
l = l->next())
{
ImodelIGC* m = l->data();
m->SetCluster(NULL);
}
}
for (ModelLinkIGC* pml = pclusterOld->GetModels()->first(); (pml != NULL); pml = pml->next())
{
ImodelIGC* pmodel = pml->data();
ThingSite* pts = pmodel->GetThingSite();
if (pts)
{
((ThingSiteImpl*)pts)->StopSounds();
}
}
if (m_fm.IsConnected())
pclusterOld->SetActive(false);
}
BaseClient::SetViewCluster(pcluster);
GetWindow()->SetCluster(pcluster);
GetWindow()->PositionCommandView(pposition, 0.0f);
trekClient.GetClientEventSource()->OnClusterChanged(pcluster);
if (m_fm.IsConnected() && pcluster)
pcluster->SetActive(true);
}
else
{
GetWindow()->PositionCommandView(pposition, 0.0f);
}
}
void WinTrekClient::RequestViewCluster(IclusterIGC* pcluster, ImodelIGC* pmodelTarget)
{
if (m_fm.IsConnected() && (trekClient.GetCluster() != pcluster))
{
if (pcluster == NULL)
SetViewCluster(pcluster);
trekClient.SetMessageType(BaseClient::c_mtGuaranteed);
BEGIN_PFM_CREATE(trekClient.m_fm, pfmViewCluster, C, VIEW_CLUSTER)
END_PFM_CREATE
pfmViewCluster->clusterID = pcluster ? pcluster->GetObjectID() : NA;
if (pmodelTarget)
{
pfmViewCluster->otTarget = pmodelTarget->GetObjectType();
pfmViewCluster->oidTarget = pmodelTarget->GetObjectID();
}
else
{
pfmViewCluster->otTarget = NA;
pfmViewCluster->oidTarget = NA;
}
}
else
{
SetViewCluster(pcluster, pmodelTarget && pmodelTarget->SeenBySide(trekClient.GetSide()) ? &(pmodelTarget->GetPosition()) : NULL);
}
}
void WinTrekClient::TerminateModelEvent(ImodelIGC* pmodel)
{
TargetKilled(pmodel);
BaseClient::TerminateModelEvent(pmodel);
}
bool WinTrekClient::DockWithStationEvent(IshipIGC* pShip, IstationIGC* pStation)
{
if (!m_fm.IsConnected())
{
pStation->RepairAndRefuel (pShip);
if ((pShip != GetShip ()) || Training::ShipLanded ())
{
IstationIGC* pOldStation = pShip->GetStation ();
pShip->SetStation (pStation);
pShip->SetStation (pOldStation);
pStation->Launch (pShip);
}
}
return true;
}
void WinTrekClient::KillShipEvent(Time now, IshipIGC* pShip, ImodelIGC* pLauncher, float flAmount, const Vector& p1, const Vector& p2)
{
if (Training::IsTraining ())
{
if (pShip->GetPilotType () != c_ptLayer)
pShip->GetCluster()->GetClusterSite()->AddExplosion(pShip, c_etSmallShip);
if (pShip == GetShip())
Training::ShipDied (pLauncher);
else
BaseClient::KillShipEvent (now, pShip, pLauncher, flAmount, p1, p2);
}
}
void WinTrekClient::DamageShipEvent(Time now,
IshipIGC * pShip,
ImodelIGC * pcredit,
DamageTypeID type,
float flAmount,
float flLeakage,
const Vector& p1,
const Vector& p2)
{
if (pcredit)
{
if (pShip == trekClient.GetShip()->GetSourceShip() && flAmount > 0.0f)
{
GetWindow()->SetTimeDamaged(now);
if (flAmount > 0.0f)
{
if (pcredit->GetSide() && pcredit->GetSide() != GetSide())
{
m_nGrooveLevel = max(m_nGrooveLevel, 2);
m_vtimeGrooveDrops[2] = Time::Now() + c_fGrooveLevelDuration;
}
}
const Vector& vRight = pShip->GetOrientation().GetRight();
const Vector& vBackward = pShip->GetOrientation().GetBackward();
Vector vDeltaP = p2 - p1;
float dotBackward = vBackward*vDeltaP;
float dotRight = vRight*vDeltaP;
long direction = ((long)DegreesFromRadians(atan2(dotBackward, dotRight)) + 90);
GetWindow()->PlayFFEffect(effectBounce, direction);
}
if (pShip->GetCluster() == trekClient.GetCluster())
{
ThingSiteImpl* pts = ((ThingSiteImpl*)pShip->GetThingSite());
if (pts)
{
pts->RegisterHit(
flAmount,
pShip->GetOrientation().TimesInverse(p2 - p1),
flLeakage == 0.0f
);
}
}
}
}
void WinTrekClient::HitWarpEvent(IshipIGC* ship, IwarpIGC* warp)
{
if (!m_fm.IsConnected())
{
IwarpIGC* destination = warp->GetDestination();
if (destination)
{
IclusterIGC* cluster = destination->GetCluster();
assert (cluster);
ship->SetCluster(cluster);
{
Orientation alephOrientation = destination->GetOrientation();
const Vector& v = ship->GetVelocity();
float speed2 = v.LengthSquared();
float speed = float(sqrt(speed2));
float error;
{
Vector dp = warp->GetPosition() - ship->GetPosition();
float t = (dp * v) / v.LengthSquared();
float d = (dp - t * v).LengthSquared();
float r = warp->GetRadius();
error = d / (r*r) + 0.125f; }
alephOrientation.Pitch(random(-error, error));
alephOrientation.Yaw(random(-error, error));
ship->SetCurrentTurnRate(c_axisRoll,
ship->GetCurrentTurnRate(c_axisRoll) +
random(pi * 0.5f * error, pi * 2.0f * error));
const Vector& backward = alephOrientation.GetBackward();
ship->SetOrientation(alephOrientation);
speed = -(speed + trekClient.m_pCoreIGC->GetFloatConstant(c_fcidExitWarpSpeed));
ship->SetVelocity(backward * speed);
ship->SetPosition(destination->GetPosition() +
(alephOrientation.GetUp() * random(2.0f, 5.0f)) +
(alephOrientation.GetRight() * random(2.0f, 5.0f)) -
(ship->GetRadius() + 5.0f) * backward);
{
Time t = ship->GetLastUpdate();
ship->SetBB(t, t, 0.0f);
}
}
}
}
}
bool WinTrekClient::HitTreasureEvent(Time now, IshipIGC* ship, ItreasureIGC* treasure)
{
if (!m_fm.IsConnected())
{
ship->HitTreasure(treasure->GetTreasureCode(), treasure->GetBuyable()->GetObjectID(), treasure->GetAmount());
return true;
}
else
return false;
}
void WinTrekClient::PaydayEvent(IsideIGC* pside, float money)
{
}
void WinTrekClient::GetMoneyRequest(IshipIGC* pshipSender, Money amount, HullID hidFor)
{
GetWindow()->SetQueuedCommand(pshipSender, amount, hidFor);
}
void WinTrekClient::ReceiveChat(IshipIGC* pshipSender,
ChatTarget ctRecipient,
ObjectID oidRecipient,
SoundID idSonicChat,
const char* pszText,
CommandID cid,
ObjectType otTarget,
ObjectID oidTarget,
ImodelIGC* pmodelTarget,
bool bObjectModel)
{
assert (ctRecipient != CHAT_GROUP_NOECHO);
bool bIsLeader = false;
if (pshipSender)
{
bool bPrivilegedUserPM = false;
PlayerInfo* ppi = (PlayerInfo*)(pshipSender->GetPrivateData());
if((ctRecipient == CHAT_INDIVIDUAL) && (ppi->PrivilegedUser()))
{
bPrivilegedUserPM = true;
}
if (ppi->GetMute()
|| (m_bFilterChatsToAll && ctRecipient == CHAT_EVERYONE && trekClient.IsInGame())
|| ((((m_dwFilterLobbyChats == 1) && (ctRecipient != CHAT_INDIVIDUAL)) || (m_dwFilterLobbyChats == 2)) && (ppi->SideID() == SIDE_TEAMLOBBY) && (trekClient.IsInGame()) && (!bPrivilegedUserPM)) || (m_bFilterUnknownChats && (ppi->IsHuman()) && (pszText == NULL) && (idSonicChat != NA) && (GetWindow()->GetSonicChatText(idSonicChat, 0) == "Unknown chat"))) return;
bIsLeader = ppi->IsTeamLeader();
}
else if (ctRecipient == CHAT_ADMIN)
bIsLeader = true;
if ((cid != c_cidNone) &&
((trekClient.m_pCoreIGC->GetMissionStage() != STAGE_STARTED) ||
(trekClient.GetSideID() < 0)))
return;
bool bIsSonicChat = false;
if (idSonicChat != NA)
{
if (pszText == NULL)
{
pszText = GetWindow()->GetSonicChatText(idSonicChat, 0);
bIsSonicChat = true;
if (m_bFilterQuickComms && pshipSender
&& ((PlayerInfo*)(pshipSender->GetPrivateData()))->IsHuman())
idSonicChat = NA;
}
}
if (ctRecipient == CHAT_INDIVIDUAL
|| GetWindow()->screen() == ScreenIDCombat
|| GetWindow()->GetLobbyChatTarget() == ctRecipient)
{
if (bIsSonicChat && idSonicChat != NA)
{
GetWindow()->PlaySonicChat(idSonicChat, 0);
}
else if (idSonicChat != NA)
{
PlaySoundEffect(idSonicChat);
}
else if ((cid != c_cidNone) && (ctRecipient != CHAT_INDIVIDUAL_ECHO))
{
PlaySoundEffect(newCommandMsgSound);
}
else if (CHAT_INDIVIDUAL == ctRecipient
&& ((NA == oidRecipient) || (trekClient.GetShipID() == oidRecipient)))
{
PlaySoundEffect(newPersonalMsgSound);
}
else
{
if (m_fm.IsConnected())
{
if (bIsLeader && (pshipSender != trekClient.GetShip()))
PlaySoundEffect(newChatMsgFromCommanderSound);
else
PlaySoundEffect(newChatMsgSound);
}
else
PlaySoundEffect(newOfflineChatMsgSound);
}
}
if (pmodelTarget == NULL)
pmodelTarget = trekClient.m_pCoreIGC->GetModel(otTarget, oidTarget);
if (Training::IsTraining ())
{
if (pshipSender && (oidRecipient == pshipSender->GetObjectID ()))
pmodelTarget = NULL;
Training::RecordChat (ctRecipient);
}
bool bForMe;
ZString strSender;
ZString strRecipient;
ZString strOrder;
{
Color color;
switch (ctRecipient)
{
case CHAT_NOSELECTION:
{
static const ZString c_strNone = "none";
strRecipient = c_strNone;
bForMe = false;
}
break;
case CHAT_EVERYONE:
{
static const ZString c_strEveryone = "all";
strRecipient = c_strEveryone;
bForMe = true;
}
break;
case CHAT_LEADERS:
{
static const ZString c_strLeaders = "leaders";
strRecipient = c_strLeaders;
bForMe = false; }
break;
case CHAT_GROUP:
{
static const ZString c_strGroup = "group";
strRecipient = c_strGroup;
bForMe = oidRecipient == trekClient.GetShipID();
}
break;
case CHAT_SHIP:
{
static const ZString c_strShip = "ship";
strRecipient = c_strShip;
bForMe = true;
}
break;
case CHAT_TEAM:
{
IsideIGC* pside = trekClient.GetShip()->GetSide();
if ((oidRecipient == NA) || (oidRecipient == pside->GetObjectID()))
{
strRecipient = pside->GetName();
bForMe = true;
}
else
{
strRecipient = trekClient.m_pCoreIGC->GetSide(oidRecipient)->GetName();
bForMe = false;
}
}
break;
case CHAT_ALL_SECTOR:
{
}
case CHAT_FRIENDLY_SECTOR:
{
IclusterIGC* pcluster = trekClient.GetChatCluster();
if (!pcluster)
{
strRecipient = "<unknown>";
bForMe = false;
}
else if ((oidRecipient == NA) || (oidRecipient == pcluster->GetObjectID()))
{
assert (pcluster);
strRecipient = pcluster->GetName();
bForMe = true;
}
else
{
strRecipient = trekClient.m_pCoreIGC->GetCluster(oidRecipient)->GetName();
bForMe = false;
}
}
break;
case CHAT_ADMIN:
{
static const ZString c_strAdmin = "admin";
strRecipient = c_strAdmin;
bForMe = false;
}
break;
case CHAT_WING:
{
WingID wid = trekClient.GetShip()->GetWingID();
if ((oidRecipient == NA) || (oidRecipient == wid))
{
bForMe = true;
}
else
{
wid = oidRecipient;
bForMe = false;
}
strRecipient = c_pszWingName[wid];
}
break;
case CHAT_INDIVIDUAL_ECHO:
case CHAT_INDIVIDUAL:
{
ShipID sid = trekClient.GetShipID();
IshipIGC* pshipRecipient;
if ((oidRecipient == NA) || (oidRecipient == sid))
{
strRecipient = trekClient.GetShip()->GetName();
bForMe = true;
if ((cid == c_cidDefault) && pmodelTarget)
cid = trekClient.GetShip()->GetDefaultOrder(pmodelTarget);
}
else
{
pshipRecipient = trekClient.m_pCoreIGC->GetShip(oidRecipient);
strRecipient = pshipRecipient->GetName();
bForMe = false;
if ((cid == c_cidDefault) && pmodelTarget)
cid = pshipRecipient->GetDefaultOrder(pmodelTarget);
}
}
break;
}
if (pshipSender)
{
strSender = pshipSender->GetName();
color = pshipSender->GetSide()->GetColor();
if ((pshipSender == trekClient.GetShip()) && !bForMe)
color = color * 0.75f;
else if (cid == c_cidNone)
color = color * 0.85f;
}
else
{
color = trekClient.GetSide()->GetColor();
static const ZString c_strHQ = "HQ";
strSender = c_strHQ;
bForMe = true;
}
if (pszText)
{
strOrder = pszText;
}
else
{
assert (cid >= 0);
strOrder += c_cdAllCommands[cid].szVerb;
if (pmodelTarget)
{
const char* modelname = GetModelName (pmodelTarget);
strOrder += " ";
strOrder += modelname;
ObjectType type = pmodelTarget->GetObjectType();
if ((type != OT_buoy) || (((IbuoyIGC*)pmodelTarget)->GetBuoyType() != c_buoyCluster))
{
IclusterIGC* pcluster = trekClient.GetCluster(trekClient.GetShip(), pmodelTarget);
if (pcluster)
{
strOrder += " in ";
strOrder += pcluster->GetName();
}
}
}
if (ctRecipient == CHAT_INDIVIDUAL_ECHO)
{
assert (!bForMe);
cid = c_cidNone;
pmodelTarget = NULL;
}
}
if ((cid == c_cidNone) ||
(ctRecipient == CHAT_INDIVIDUAL_ECHO) ||
((bForMe && (ctRecipient == CHAT_INDIVIDUAL)) == (pshipSender != trekClient.GetShip())))
{
int nMaxChats = 600;
while (trekClient.GetChatList()->n() >= nMaxChats)
{
assert(trekClient.GetChatList()->n() == nMaxChats);
ChatLink* lOldestChat = trekClient.GetChatList()->first();
trekClient.GetClientEventSource()->OnDeleteChatMessage(&lOldestChat->data());
delete lOldestChat;
}
bool bFromPlayer = pshipSender
&& (!pshipSender->GetPrivateData()
|| ((PlayerInfo*)pshipSender->GetPrivateData())->IsHuman());
ChatLink* l = new ChatLink;
assert (l);
static const ZString c_str1(" (");
static const ZString c_str2("): ");
l->data().SetChat(ctRecipient, strSender + c_str1 + strRecipient + c_str2 + strOrder,
c_cidNone, pmodelTarget, color, bFromPlayer, bObjectModel, bIsLeader);
trekClient.GetChatList()->last(l);
BaseClient::ReceiveChat(pshipSender,
ctRecipient, oidRecipient,
idSonicChat, pszText,
cid, otTarget, oidTarget, pmodelTarget);
}
}
if (bForMe)
{
if (pmodelTarget && trekClient.GetShip()->LegalCommand(cid, pmodelTarget))
{
Command cmd = (ctRecipient == CHAT_INDIVIDUAL) && (pshipSender == trekClient.GetShip())
? c_cmdAccepted
: c_cmdQueued;
if (cmd == c_cmdAccepted)
{
GetWindow()->SetAccepted(pmodelTarget, cid);
GetWindow()->SetTarget(pmodelTarget, cid);
if (trekClient.GetShip()->GetCluster() &&
(trekClient.GetShip()->GetParentShip() == NULL) &&
trekClient.GetCluster(trekClient.GetShip(), pmodelTarget))
{
trekClient.SetAutoPilot(true);
trekClient.bInitTrekJoyStick = true;
PlaySoundEffect(salAutopilotEngageSound);
}
}
else
{
GetWindow()->SetQueuedCommand(pshipSender, cid, pmodelTarget);
if (pshipSender != trekClient.GetShip())
{
if ((cid == c_cidPickup) && (pmodelTarget == pshipSender) &&
pshipSender->GetBaseHullType()->HasCapability(c_habmRescue))
{
trekClient.PostText(true, "New orders from %s: prepare for recovery. Press [insert] to accept.",
(const char*)strSender);
}
else
trekClient.PostText(true, "New orders from %s to %s: %s. Press [insert] to accept.",
(const char*)strSender, (const char*)strRecipient, (const char*)strOrder);
}
}
}
}
}
void WinTrekClient::Preload(const char* pszModelName,
const char* pszTextureName)
{
if (pszModelName)
GetModeler()->GetNameSpace(pszModelName);
if (pszTextureName)
{
char bfr[c_cbFileName + 4];
strcpy(bfr, pszTextureName);
strcat(bfr, "bmp");
GetModeler()->GetNameSpace(bfr);
}
}
void WinTrekClient::SetCDKey(const ZString& strCDKey)
{
HKEY hKey;
BaseClient::SetCDKey(strCDKey);
}
TRef<ThingSite> WinTrekClient::CreateThingSite(ImodelIGC* pModel)
{
return new ThingSiteImpl(pModel);
}
TRef<ClusterSite> WinTrekClient::CreateClusterSite(IclusterIGC* pCluster)
{
return
new ClusterSiteImpl(
GetWindow()->GetModeler(),
GetWindow()->GetTime(),
GetWindow()->GetPosterViewport(),
pCluster
);
}
void WinTrekClient::PlaySoundEffect(SoundID soundID, ImodelIGC* model)
{
if (!model || (model->GetCluster() && model->GetCluster() == GetCluster()))
{
TRef<ISoundPositionSource> psource = model ?
((ThingSiteImpl*)model->GetThingSite())->GetSoundSource() : NULL;
StartSound(soundID, psource);
}
}
void WinTrekClient::PlaySoundEffect(SoundID soundID, ImodelIGC* model, const Vector& vectOffset)
{
if (!model || (model->GetCluster() && model->GetCluster() == GetCluster()))
{
TRef<ISoundPositionSource> psource = model ?
((ThingSiteImpl*)model->GetThingSite())->GetSoundSource(vectOffset) : NULL;
StartSound(soundID, psource);
}
}
void WinTrekClient::PlayNotificationSound(SoundID soundID, ImodelIGC* model)
{
if (model == GetShip() || model == GetShip()->GetSourceShip())
{
TRef<ISoundPositionSource> psource = model ?
((ThingSiteImpl*)model->GetThingSite())->GetSoundSource() : NULL;
StartSound(soundID, psource);
}
}
void WinTrekClient::PlayFFEffect(ForceEffectID effectID, ImodelIGC* model, LONG lDirection)
{
if ((model == NULL) || (model == GetShip())) {
GetWindow()->PlayFFEffect(effectID, lDirection);
}
}
void WinTrekClient::PlayVisualEffect(VisualEffectID effectID, ImodelIGC* model, float fIntensity)
{
if ((model == NULL) || (model == GetShip()))
{
switch (effectID)
{
case effectJiggle:
GetWindow()->SetJiggle(fIntensity);
break;
}
}
}
void WinTrekClient::UpdateAmbientSounds(DWORD dwElapsedTime)
{
for (ClusterLinkIGC* cLink = GetCore()->GetClusters()->first(); cLink != NULL; cLink = cLink->next())
{
IclusterIGC* pCluster = cLink->data();
((ClusterSiteImpl*)pCluster->GetClusterSite())->UpdateClusterWarnings();
}
if (GetCluster())
{
if (m_psoundAmbient)
{
m_psoundAmbient->Stop();
m_psoundAmbient = NULL;
}
bool bPlayMissileWarning = false;
float fBestLock = 0.0f;
IclusterIGC* pcluster = GetCluster();
for (ModelLinkIGC* pml = pcluster->GetModels()->first(); (pml != NULL); pml = pml->next())
{
ImodelIGC* pmodel = pml->data();
ThingSite* pts = pmodel->GetThingSite();
if (pts)
{
((ThingSiteImpl*)pts)->UpdateSounds(dwElapsedTime);
if (pmodel->GetObjectType() == OT_missile)
{
ImissileIGC* pmissile = (ImissileIGC*)(pmodel);
if (pmissile->GetTarget() == trekClient.GetShip()->GetSourceShip())
{
bPlayMissileWarning = true;
if (pmissile->GetLock() > fBestLock)
fBestLock = pmissile->GetLock();
}
}
}
}
if (bPlayMissileWarning && trekClient.GetShip()->GetCluster())
{
if (!m_psoundMissileWarning)
{
ThingSite* pts = trekClient.GetShip()->GetThingSite();
if (pts)
{
m_psoundMissileWarning = StartSound(missileLockSound, ((ThingSiteImpl*)pts)->GetSoundSource());
}
}
m_psoundMissileWarning->GetISoundTweakable()->SetPitch(0.75 + fBestLock/2);
}
else if (m_psoundMissileWarning)
{
m_psoundMissileWarning->Stop();
m_psoundMissileWarning = NULL;
}
}
else if (trekClient.GetShip()->GetStation()
&& GetWindow()->screen() == ScreenIDCombat)
{
SoundID newAmbientSound = trekClient.GetShip()->GetStation()->GetInteriorSound();
if (!m_psoundAmbient || m_idAmbient != newAmbientSound)
{
m_idAmbient = newAmbientSound;
if (m_psoundAmbient)
m_psoundAmbient->Stop();
m_psoundAmbient = StartSound(m_idAmbient, NULL);
}
if (m_psoundMissileWarning)
{
m_psoundMissileWarning->Stop();
m_psoundMissileWarning = NULL;
}
}
else
{
if (m_psoundAmbient)
{
m_psoundAmbient->Stop();
m_psoundAmbient = NULL;
}
if (m_psoundMissileWarning)
{
m_psoundMissileWarning->Stop();
m_psoundMissileWarning = NULL;
}
}
}
void WinTrekClient::ResetSound()
{
if (m_psoundAmbient)
{
m_psoundAmbient->Stop();
m_psoundAmbient = NULL;
}
if (GetCluster())
{
IclusterIGC* pcluster = GetCluster();
for (ModelLinkIGC* pml = pcluster->GetModels()->first(); (pml != NULL); pml = pml->next())
{
ImodelIGC* pmodel = pml->data();
ThingSite* pts = pmodel->GetThingSite();
if (pts)
{
((ThingSiteImpl*)pts)->StopSounds();
}
}
}
}
HRESULT WinTrekClient::ConnectToServer(BaseClient::ConnectInfo & ci, DWORD dwCookie, Time now, const char* szPassword, bool bStandalonePrivate)
{
HRESULT hr = BaseClient::ConnectToServer(ci, dwCookie, now, szPassword, bStandalonePrivate);
if (!GetWindow()->GetPopupContainer()->IsEmpty())
GetWindow()->GetPopupContainer()->ClosePopup(NULL);
GetWindow()->RestoreCursor();
if (!m_fm.IsConnected())
{
TRef<IMessageBox> pmsgBox = CreateMessageBox("Failed to connect to the server.");
GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, false);
g_bQuickstart = false;
}
else
{
GetWindow()->SetWaitCursor();
TRef<IMessageBox> pmsgBox = CreateMessageBox("Logging in...", NULL, false);
GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, false);
m_bDisconnected = false;
}
return hr;
}
HRESULT WinTrekClient::ConnectToLobby(BaseClient::ConnectInfo * pci)
{
HRESULT hr = E_FAIL;
if (m_fmLobby.IsConnected())
return S_OK;
hr = BaseClient::ConnectToLobby(pci);
if (!GetWindow()->GetPopupContainer()->IsEmpty())
GetWindow()->GetPopupContainer()->ClosePopup(NULL);
GetWindow()->RestoreCursor();
if (!m_fmLobby.IsConnected())
{
TRef<IMessageBox> pmsgBox = CreateMessageBox("Failed to connect to the lobby.");
Point point(c_PopupX, c_PopupY);
Rect rect(point, point);
GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, rect, false);
g_bQuickstart = false;
}
else
{
GetWindow()->SetWaitCursor();
TRef<IMessageBox> pmsgBox = CreateMessageBox("Logging into lobby...", NULL, false);
Point point(c_PopupX, c_PopupY);
Rect rect(point, point);
GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, rect, false);
}
return hr;
}
HRESULT WinTrekClient::ConnectToClub(BaseClient::ConnectInfo * pci)
{
HRESULT hr = E_FAIL;
if (m_fmClub.IsConnected())
return S_OK;
if (pci)
pci->strServer = GetCfgInfo().strClub;
hr = BaseClient::ConnectToClub(pci);
if (!GetWindow()->GetPopupContainer()->IsEmpty())
GetWindow()->GetPopupContainer()->ClosePopup(NULL);
GetWindow()->RestoreCursor();
if (!m_fmClub.IsConnected())
{
TRef<IMessageBox> pmsgBox = CreateMessageBox("Failed to connect to the Allegiance Zone.");
Point point(c_PopupX, c_PopupY);
Rect rect(point, point);
GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, rect, false);
g_bQuickstart = false;
}
else
{
GetWindow()->SetWaitCursor();
TRef<IMessageBox> pmsgBox = CreateMessageBox("Logging into the Allegiance Zone...", NULL, false);
Point point(c_PopupX, c_PopupY);
Rect rect(point, point);
GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, rect, false);
}
return hr;
}
void WinTrekClient::OnQuitMission(QuitSideReason reason, const char* szMessageParam)
{
m_sideidLastWinner = NA;
m_bWonLastGame = false;
m_bLostLastGame = false;
m_nNumEndgamePlayers = 0;
m_nNumEndgameSides = 0;
if (m_fm.IsConnected ())
{
if (Training::GetTrainingMissionID () == Training::c_TM_7_Live)
{
Training::EndMission ();
GetWindow()->screen(ScreenIDTrainScreen);
}
else
GetWindow()->screen(trekClient.GetIsLobbied() ? ScreenIDGameScreen : ScreenIDIntroScreen);
ZString strMessage;
switch (reason)
{
case QSR_LeaderBooted:
strMessage = "You have been booted by your team leader!";
break;
case QSR_OwnerBooted:
strMessage = "You have been booted by the mission owner!";
break;
case QSR_AdminBooted:
strMessage = "You have been booted by a server administrator!";
break;
case QSR_ServerShutdown:
strMessage = "The game has been shut down by an administrator.";
break;
case QSR_SquadChange:
case QSR_SideDestroyed:
case QSR_TeamSizeLimits:
assert(false); break;
case QSR_Quit:
break;
case QSR_LinkDead:
break;
case QSR_DuplicateRemoteLogon:
strMessage = "Someone used your zone account to log into another game.";
break;
case QSR_DuplicateLocalLogon:
strMessage = "Someone used your zone account to log into the game you were playing.";
break;
case QSR_DuplicateCDKey:
assert(szMessageParam);
strMessage = ZString(szMessageParam ? szMessageParam : "someone")
+ " used your CD Key to log into a game!";
break;
case QSR_SwitchingSides:
case QSR_RandomizeSides:
assert(false); break;
}
if (!strMessage.IsEmpty())
{
if (trekClient.GetIsLobbied())
{
m_strDisconnectReason = strMessage;
}
else
{
TRef<IMessageBox> pmsgBox = CreateMessageBox(strMessage);
GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, false);
}
}
}
BaseClient::OnQuitMission(reason, szMessageParam);
}
void WinTrekClient::SetGameoverInfo(FMD_S_GAME_OVER* pfmGameOver)
{
m_sideidLastWinner = pfmGameOver->iSideWinner;
m_bWonLastGame = pfmGameOver->iSideWinner == GetSideID();
m_bLostLastGame = !m_bWonLastGame && (GetSideID() != SIDE_TEAMLOBBY) && pfmGameOver->iSideWinner != NA;
m_strGameOverMessage = FM_VAR_REF(pfmGameOver, szGameoverMessage);
m_nNumEndgamePlayers = 0;
m_nNumEndgameSides = pfmGameOver->nNumSides;
if (m_vplayerEndgameInfo)
delete []m_vplayerEndgameInfo;
m_vplayerEndgameInfo = NULL;
memcpy(m_vsideEndgameInfo, pfmGameOver->rgSides, sizeof(SideEndgameInfo) * c_cSidesMax);
m_bEndgameEjectPods = pfmGameOver->bEjectPods;
m_bGameCounted = true; m_bScoresCounted = MyMission()->GetMissionParams().bScoresCount;
trekClient.GetClientEventSource()->OnGameoverStats();
trekClient.GetClientEventSource()->OnGameoverPlayers();
}
void WinTrekClient::AddGameoverPlayers(PlayerEndgameInfo* vEndgamePlayerInfo, int nCount)
{
PlayerEndgameInfo* vnewInfo = new PlayerEndgameInfo[m_nNumEndgamePlayers + nCount];
if (m_nNumEndgamePlayers > 0)
memcpy(vnewInfo, m_vplayerEndgameInfo, sizeof(PlayerEndgameInfo) * m_nNumEndgamePlayers);
memcpy(vnewInfo + m_nNumEndgamePlayers, vEndgamePlayerInfo, sizeof(PlayerEndgameInfo) * nCount);
if (m_vplayerEndgameInfo)
delete []m_vplayerEndgameInfo;
m_nNumEndgamePlayers += nCount;
m_vplayerEndgameInfo = vnewInfo;
for (int iPlayerIndex = m_nNumEndgamePlayers - nCount; iPlayerIndex < nCount; iPlayerIndex++)
{
if (strcmp(m_vplayerEndgameInfo[iPlayerIndex].characterName, GetShip()->GetName()) == 0)
{
m_bGameCounted = m_vplayerEndgameInfo[iPlayerIndex].scoring.GetGameCounted();
break;
}
}
trekClient.GetClientEventSource()->OnGameoverPlayers();
}
ZString WinTrekClient::GetGameoverMessage()
{
return m_strGameOverMessage;
};
PlayerEndgameInfo* WinTrekClient::GetEndgamePlayerInfo(int nIndex)
{
assert(nIndex < m_nNumEndgamePlayers);
return &(m_vplayerEndgameInfo[nIndex]);
};
int WinTrekClient::GetNumEndgamePlayers()
{
return m_nNumEndgamePlayers;
};
SideEndgameInfo* WinTrekClient::GetSideEndgameInfo(SideID sideId)
{
assert(sideId >= 0 && sideId < m_nNumEndgameSides);
return &(m_vsideEndgameInfo[sideId]);
}
int WinTrekClient::GetNumEndgameSides()
{
return m_nNumEndgameSides;
}
Color WinTrekClient::GetEndgameSideColor(SideID sideId)
{
if (sideId < 0)
return 0.75 * Color::White();
assert(sideId >= 0 && sideId < m_nNumEndgameSides);
return m_vsideEndgameInfo[sideId].color;
};
void WinTrekClient::SaveSquadMemberships(const char* szCharacterName)
{
DWORD dwMembershipSize = m_squadmemberships.GetCount() * sizeof(SquadID);
SquadID* vsquadIDs = (SquadID*)_alloca(dwMembershipSize);
int iSquad = 0;
for (TList<SquadMembership>::Iterator iterSquad(m_squadmemberships);
!iterSquad.End(); iterSquad.Next())
{
vsquadIDs[iSquad] = iterSquad.Value().GetID();
++iSquad;
}
HKEY hKey;
if (ERROR_SUCCESS == ::RegCreateKeyEx(HKEY_LOCAL_MACHINE,
ALLEGIANCE_REGISTRY_KEY_ROOT "\\SquadMemberships",
0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL))
{
::RegSetValueEx(hKey, szCharacterName, NULL, REG_BINARY,
(const unsigned char*)vsquadIDs, dwMembershipSize);
::RegCloseKey(hKey);
}
}
void WinTrekClient::RestoreSquadMemberships(const char* szCharacterName)
{
m_squadmemberships.SetEmpty();
HKEY hKey;
if (ERROR_SUCCESS == ::RegCreateKeyEx(HKEY_LOCAL_MACHINE,
ALLEGIANCE_REGISTRY_KEY_ROOT "\\SquadMemberships",
0, "", REG_OPTION_NON_VOLATILE, KEY_READ, NULL, &hKey, NULL))
{
DWORD dwSize = 0;
DWORD dwType;
if (::RegQueryValueEx(hKey, szCharacterName, NULL, &dwType, NULL, &dwSize) == ERROR_SUCCESS
&& dwType == REG_BINARY && dwSize != 0)
{
SquadID* vsquadIDs = (SquadID*)_alloca(dwSize);
int numSquads = dwSize / sizeof(SquadID);
::RegQueryValueEx(hKey, szCharacterName, NULL, NULL,
(unsigned char*)vsquadIDs, &dwSize);
for (int iSquad = 0; iSquad < numSquads; iSquad++)
{
m_squadmemberships.PushEnd(SquadMembership(vsquadIDs[iSquad], "<bug>", false, false));
}
}
::RegCloseKey(hKey);
}
}
CivID WinTrekClient::GetEndgameSideCiv(SideID sideId)
{
if (sideId == SIDE_TEAMLOBBY)
return NA;
assert(sideId >= 0 && sideId < m_nNumEndgameSides);
return m_vsideEndgameInfo[sideId].civID;
};
int WinTrekClient::GetGrooveLevel()
{
int nCurrentGrooveLevel = 0;
bool bEnemiesSighted = false;
bool bEnemiesInRange = false;
bool bEnemiesInRangeShootingAtMe = false;
float fMaximumRange = 0;
bool bFiring = false;
IhullTypeIGC* pht = GetShip()->GetSourceShip()->GetBaseHullType();
if (pht)
{
Mount maxFixedWeapons = pht->GetMaxWeapons();
for (Mount mount = 0; mount < maxFixedWeapons; mount++)
{
const IweaponIGC* pweapon;
CastTo(pweapon, GetShip()->GetMountedPart(ET_Weapon, mount));
if (pweapon)
{
if (pweapon->fActive())
bFiring = true;
IprojectileTypeIGC* ppt = pweapon->GetProjectileType();
fMaximumRange = max(fMaximumRange, ppt->GetSpeed() * pweapon->GetLifespan());
}
}
const ImagazineIGC* pmagazine;
CastTo(pmagazine, GetShip()->GetSourceShip()->GetMountedPart(ET_Magazine, 0));
if (pmagazine)
{
if (pmagazine->fActive() && (GetShip()->GetSourceShip()->GetStateM() & missileFireIGC))
bFiring = true;
ImissileTypeIGC* pmt = pmagazine->GetMissileType();
fMaximumRange = max(fMaximumRange,
pmt->GetLifespan()*(pmt->GetInitialSpeed()+0.5f*pmt->GetLifespan()*pmt->GetAcceleration()));
}
}
if (GetCluster())
{
for (ShipLinkIGC* psl = GetCluster()->GetShips()->first();
(psl != NULL);
psl = psl->next())
{
IshipIGC* pship = psl->data();
if (pship->GetSide() != GetSide()
&& pship->SeenBySide(GetSide()))
{
bEnemiesSighted = true;
if (GetShip()->GetSourceShip()->GetCluster())
{
float c_fFudgeFactor = 2.0f; bEnemiesInRange =
(GetShip()->GetSourceShip()->GetPosition()
- pship->GetSourceShip()->GetPosition()).LengthSquared()
< fMaximumRange * fMaximumRange * c_fFudgeFactor;
bEnemiesInRangeShootingAtMe = bEnemiesInRange
&& (pship->GetCommandTarget(c_cmdCurrent) == GetShip()->GetSourceShip())
&& (pship->GetStateM() & (missileFireIGC | chaffFireIGC | weaponsMaskIGC));
}
}
}
}
if (bEnemiesSighted || MyPlayerInfo()->GetShipStatus().GetDetected())
{
m_nGrooveLevel = max(m_nGrooveLevel, 1);
m_vtimeGrooveDrops[1] = Time::Now() + c_fGrooveLevelDuration;
}
for (ClusterLinkIGC* cLink = GetCore()->GetClusters()->first(); cLink != NULL; cLink = cLink->next())
{
IclusterIGC* pCluster = cLink->data();
ClusterWarning warn =
GetClusterWarning(pCluster->GetClusterSite()->GetClusterAssetMask(),
trekClient.MyMission()->GetMissionParams().bInvulnerableStations);
switch (warn)
{
case c_cwMinerThreatened:
case c_cwBuilderThreatened:
case c_cwStationThreatened:
m_nGrooveLevel = max(m_nGrooveLevel, 1);
m_vtimeGrooveDrops[1] = Time::Now() + c_fGrooveLevelDuration;
break;
}
}
if (bEnemiesInRange && bFiring
|| bEnemiesInRangeShootingAtMe)
{
m_nGrooveLevel = max(m_nGrooveLevel, 2);
m_vtimeGrooveDrops[2] = Time::Now() + c_fGrooveLevelDuration;
}
while (Time::Now() > m_vtimeGrooveDrops[m_nGrooveLevel]
&& m_nGrooveLevel > 0)
{
--m_nGrooveLevel;
}
return m_nGrooveLevel;
}
void WinTrekClient::StartLockDown(const ZString& strReason, LockdownCriteria criteria)
{
GetWindow()->StartLockDown(strReason);
BaseClient::StartLockDown(strReason, criteria);
}
void WinTrekClient::EndLockDown(LockdownCriteria criteria)
{
BaseClient::EndLockDown(criteria);
GetWindow()->EndLockDown();
}
WinTrekClient trekClient;