123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491 |
- #include "pch.h"
- #include "probeIGC.h"
- const float c_deceleration = 10.0f;
- CprobeIGC::CprobeIGC(void)
- :
- m_probeType(NULL),
- m_fraction(1.0f),
- m_projectileType(NULL),
- m_bCreateNow (false)
- {
- }
- CprobeIGC::~CprobeIGC(void)
- {
- assert (m_projectileType == NULL);
- }
- HRESULT CprobeIGC::Initialize(ImissionIGC* pMission, Time now, const void* data, int dataSize)
- {
- assert (pMission);
- m_pMission = pMission;
- ZRetailAssert (data && (dataSize > sizeof(DataProbeBase)));
- {
- DataProbeBase* dataProbeBase = (DataProbeBase*)data;
- if ((dataProbeBase->exportF) &&
- ((DataProbeExport*)dataProbeBase)->createNow)
- {
- m_time0 = now;
- }
- else
- {
- m_time0 = pMission->GetIgcSite()->ClientTimeFromServerTime(dataProbeBase->time0);
- }
- TmodelIGC<IprobeIGC>::Initialize(pMission, now, data, dataSize);
- IshipIGC* pshipLauncher;
- IsideIGC* pside;
- IclusterIGC* pcluster;
- if (dataProbeBase->exportF)
- {
- assert (dataSize == sizeof(DataProbeExport));
- DataProbeExport* dataProbeExport = (DataProbeExport*)dataProbeBase;
- m_probeType = (IprobeTypeIGC*)(pMission->GetExpendableType(dataProbeExport->probetypeID));
- pside = pMission->GetSide(dataProbeExport->sideID);
- pcluster = pMission->GetCluster(dataProbeExport->clusterID);
- pshipLauncher = pside->GetShip(dataProbeExport->shipID);
- if (m_probeType->HasCapability(c_eabmShootOnlyTarget))
- m_target = pMission->GetModel(dataProbeExport->otTarget, dataProbeExport->oidTarget);
- }
- else
- {
- assert (dataSize == sizeof(DataProbeIGC));
- DataProbeIGC* dataProbe = (DataProbeIGC*)dataProbeBase;
- m_probeType = dataProbe->pprobetype;
- pside = dataProbe->pside;
- pcluster = dataProbe->pcluster;
- pshipLauncher = dataProbe->pship;
- if (m_probeType->HasCapability(c_eabmShootOnlyTarget))
- m_target = dataProbe->pmodelTarget;
- }
- assert (m_probeType);
- assert (m_probeType->GetObjectType() == OT_probeType);
- m_probeType->AddRef();
- m_ammo = m_probeType->GetAmmo();
- DataProbeTypeIGC* dataProbeType = (DataProbeTypeIGC*)(m_probeType->GetData());
- m_projectileType = m_probeType->GetProjectileType();
- if (m_projectileType)
- {
- m_projectileType->AddRef();
- m_bSeenByAll = false;
- if (pshipLauncher && (dataProbeType->launcherDef.price == 0))
- m_launcher = pshipLauncher;
- }
- assert (pcluster);
-
- assert (iswalpha(dataProbeType->modelName[0]));
- HRESULT hr = Load(0, dataProbeType->modelName,
- dataProbeType->textureName,
- dataProbeType->iconName,
- c_mtDamagable | c_mtHitable | c_mtStatic | c_mtSeenBySide | c_mtPredictable | c_mtScanner);
- assert (SUCCEEDED(hr));
- SetRadius(dataProbeType->radius);
- SetSignature(dataProbeType->signature);
- SetSide(pside);
- SetSecondaryName(dataProbeType->launcherDef.name);
- {
-
- Vector v = Vector::RandomDirection();
- Orientation o(v);
- SetOrientation(o);
- }
-
- assert (dataProbeType->lifespan > 0.0f);
- m_timeExpire = m_time0 + dataProbeType->lifespan;
- assert (m_timeExpire != m_time0);
- m_nextFire = m_time0 + (m_probeType->HasCapability(c_eabmQuickReady)
- ? 5.0f
- : 30.0f);
- assert (GetSide());
- SetMass(0.0f);
- m_probeID = dataProbeBase->probeID;
- SetPosition(dataProbeBase->p0);
- SetCluster(pcluster);
- pMission->AddProbe(this);
- if ((dataProbeType->dtRipcord >= 0.0f) && ((GetMyLastUpdate() - m_time0) >= dataProbeType->dtRipcord))
- {
- pMission->GetIgcSite()->ActivateTeleportProbe(this);
- }
- }
- return S_OK;
- }
- void CprobeIGC::Terminate(void)
- {
- AddRef();
- DataProbeTypeIGC* dataProbeType = (DataProbeTypeIGC*)(m_probeType->GetData());
- if (dataProbeType->dtRipcord >= 0.0f)
- {
- GetMyMission()->GetIgcSite()->DestroyTeleportProbe(this);
- }
- if (m_projectileType)
- {
- m_projectileType->Release();
- m_projectileType = NULL;
- }
- m_launcher = NULL;
- m_target = NULL;
- GetCluster()->GetClusterSite()->AddExplosion(GetPosition(), GetRadius(), c_etProbe);
- GetMyMission()->DeleteProbe(this);
- TmodelIGC<IprobeIGC>::Terminate();
- if (m_probeType)
- {
- m_probeType->Release();
- m_probeType = NULL;
- }
- Release();
- }
- inline void CprobeIGC::ValidTarget(ImodelIGC* pmodel,
- IsideIGC* pside,
- const Vector& myPosition,
- float dtUpdate,
- float accuracy,
- float speed,
- float lifespan,
- ObjectType type,
- ImodelIGC** ppmodelMin,
- float* pdistance2Min,
- Vector* pdirectionMin)
- {
-
- if (pmodel->GetSide() != pside)
- {
- ModelAttributes ma = pmodel->GetAttributes();
- if ((((ma & c_mtStatic) && pmodel->SeenBySide(pside)) || InScannerRange(pmodel)) &&
- (ma & c_mtDamagable) &&
- ((type != OT_ship) || !((IshipIGC*)pmodel)->GetBaseHullType()->HasCapability(c_habmLifepod)))
- {
-
- const Vector& hisVelocity = pmodel->GetVelocity();
- Vector dp = pmodel->GetPosition() -
- myPosition +
- (hisVelocity * dtUpdate);
- float distance2 = dp.LengthSquared();
- if (distance2 < *pdistance2Min)
- {
- Vector direction;
- float t = solveForImpact(dp,
- accuracy * hisVelocity,
- speed, pmodel->GetRadius(),
- &direction);
- if (t <= lifespan)
- {
- *ppmodelMin = pmodel;
- *pdistance2Min = distance2;
- *pdirectionMin = direction;
- }
- }
- }
- }
- }
- inline void CprobeIGC::GetTarget(const ModelListIGC* models,
- IsideIGC* pside,
- const Vector& myPosition,
- float dtUpdate,
- float accuracy,
- float speed,
- float lifespan,
- ObjectType type,
- ImodelIGC** ppmodelMin,
- float* pdistance2Min,
- Vector* pdirectionMin)
- {
- for (ModelLinkIGC* l = models->first(); (l != NULL); l = l->next())
- {
- ImodelIGC* pmodel = l->data();
- assert (pmodel->GetObjectType() == type);
- ValidTarget(pmodel,
- pside,
- myPosition,
- dtUpdate,
- accuracy,
- speed,
- lifespan,
- type,
- ppmodelMin,
- pdistance2Min,
- pdirectionMin);
- }
- }
-
- void CprobeIGC::Update(Time now)
- {
- if (now >= m_timeExpire)
- GetMyMission()->GetIgcSite()->KillProbeEvent(this);
- else
- {
- {
- float dt = m_probeType->GetRipcordDelay();
- if (dt >= 0.0f)
- {
- Time timeActivate = m_time0 + dt;
- if ((GetMyLastUpdate() < timeActivate) &&
- (now >= timeActivate))
- {
- GetMyMission()->GetIgcSite()->ActivateTeleportProbe(this);
- }
- }
- }
- if (m_projectileType)
- {
- if (m_nextFire < now)
- {
- IclusterIGC* pcluster = GetCluster();
- assert (pcluster);
-
- float lifespan = GetProjectileLifespan();
- IsideIGC* pside = GetSide();
- const Vector& myPosition = GetPosition();
- float speed = m_projectileType->GetSpeed();
- if (m_ammo != 0)
- speed *= GetSide()->GetGlobalAttributeSet().GetAttribute(c_gaSpeedAmmo);
- float accuracy = GetAccuracy();
- float dtimeBurst = GetDtBurst();
- float dispersion = m_probeType->GetDispersion();
- Time lastUpdate = GetMyLastUpdate();
- if (m_nextFire < lastUpdate)
- m_nextFire = lastUpdate;
- assert (m_nextFire <= now);
- TmodelIGC<IprobeIGC>::Update(now);
- float dtUpdate = m_nextFire - lastUpdate;
-
- ExpendableAbilityBitMask eabm = m_probeType->GetCapabilities();
- float distance2Min = speed * lifespan / 1.2f;
- distance2Min *= distance2Min;
- Vector directionMin;
- ImodelIGC* pmodelTarget = NULL;
- if (eabm & c_eabmShootOnlyTarget)
- {
- if (m_target && (m_target->GetCluster() == pcluster))
- {
- ObjectType type = m_target->GetObjectType();
- ValidTarget((type == OT_ship) ? ((IshipIGC*)(ImodelIGC*)m_target)->GetSourceShip() : m_target,
- pside, myPosition, dtUpdate, accuracy, speed, lifespan, type,
- &pmodelTarget, &distance2Min, &directionMin);
- }
- }
- else
- {
- if (eabm & c_eabmShootShips)
- {
-
- GetTarget((const ModelListIGC*)(pcluster->GetShips()),
- pside, myPosition, dtUpdate, accuracy, speed, lifespan, OT_ship,
- &pmodelTarget, &distance2Min, &directionMin);
- }
- if (eabm & c_eabmShootMissiles)
- {
- GetTarget((const ModelListIGC*)(pcluster->GetMissiles()),
- pside, myPosition, dtUpdate, accuracy, speed, lifespan, OT_missile,
- &pmodelTarget, &distance2Min, &directionMin);
- }
- if (eabm & c_eabmShootStations)
- {
- GetTarget((const ModelListIGC*)(pcluster->GetStations()),
- pside, myPosition, dtUpdate, accuracy, speed, lifespan, OT_station,
- &pmodelTarget, &distance2Min, &directionMin);
- }
- }
- if (pmodelTarget)
- {
- if (m_launcher && (m_launcher->GetMission() != GetMyMission()))
- m_launcher = NULL;
-
- if (!m_bSeenByAll)
- {
- m_bSeenByAll = true;
- for (SideLinkIGC* psl = m_pMission->GetSides()->first();
- (psl != NULL);
- psl = psl->next())
- {
- IsideIGC* psideOther = psl->data();
- if (!SeenBySide(psideOther))
- {
-
- ClusterSite* pcs = pcluster->GetClusterSite();
- const ScannerListIGC* psl = pcs->GetScanners(psideOther->GetObjectID());
- if (psl->n() != 0)
- SetSideVisibility(psideOther, true);
- else
- m_bSeenByAll = false;
- }
- }
- }
-
- Orientation o = GetOrientation();
- o.TurnTo(directionMin);
- SetOrientation(o);
- Vector position = myPosition + m_probeType->GetEmissionPt() * o;
- DataProjectileIGC dataProjectile;
- dataProjectile.projectileTypeID = m_projectileType->GetObjectID();
- short nShots = 0;
- do
- {
-
- dataProjectile.forward = directionMin;
- if (dispersion != 0.0f)
- {
- float r = random(0.0f, dispersion);
- float a = random(0.0f, 2.0f * pi);
- dataProjectile.forward += (r * cos(a)) * o.GetRight();
- dataProjectile.forward += (r * sin(a)) * o.GetUp();
- dataProjectile.forward.SetNormalize();
- }
-
- dataProjectile.velocity = speed * dataProjectile.forward;
- dataProjectile.lifespan = lifespan;
- IprojectileIGC* p = (IprojectileIGC*)(m_pMission->CreateObject(m_nextFire, OT_projectile,
- &dataProjectile, sizeof(dataProjectile)));
- assert (p);
- {
- p->SetLauncher(m_launcher ? ((ImodelIGC*)m_launcher) : ((ImodelIGC*)this));
- p->SetPosition(position);
- p->SetCluster(pcluster);
- p->Release();
- }
- nShots++;
- m_nextFire += dtimeBurst;
- }
- while (m_nextFire < now);
- if (m_ammo > 0)
- {
- m_ammo -= nShots;
- if (m_ammo <= 0)
- {
- m_ammo = 0;
- GetMyMission()->GetIgcSite()->KillProbeEvent(this);
- }
- }
- }
- else
- {
-
- m_nextFire = now;
- }
- }
- }
- TmodelIGC<IprobeIGC>::Update(now);
- }
- }
- int CprobeIGC::Export(void* data) const
- {
- if (data)
- {
- DataProbeExport* pdme = (DataProbeExport*)data;
- pdme->p0 = GetPosition();
- pdme->time0 = m_time0;
- pdme->probeID = GetObjectID();
- pdme->exportF = true;
- pdme->clusterID = GetCluster()->GetObjectID();
- pdme->probetypeID = m_probeType->GetObjectID();
- pdme->sideID = GetSide()->GetObjectID();
- pdme->shipID = m_launcher ? m_launcher->GetObjectID() : NA;
- if (m_target)
- {
- pdme->otTarget = m_target->GetObjectType();
- pdme->oidTarget = m_target->GetObjectID();
- }
- else
- {
- pdme->otTarget = NA;
- pdme->oidTarget = NA;
- }
- pdme->createNow = m_bCreateNow;
- }
- return sizeof(DataProbeExport);
- }
|