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); } }
//This should only be called from the ChangeCluster() callback. void CFSShip::SetCluster(IclusterIGC * pcluster, bool bViewOnly) { if (pcluster) { IshipIGC* pshipParent = m_pShip->GetParentShip(); if ((pshipParent == NULL) && !bViewOnly) { //Everyone already in the sector now knows about the player's ship //(assuming the player is not in a turret) QueueLoadoutChange(); BEGIN_PFM_CREATE(g.fm, pfmSSU, S, SINGLE_SHIP_UPDATE) END_PFM_CREATE m_pShip->ExportShipUpdate(&(pfmSSU->shipupdate)); { ImodelIGC* pmodelTarget = m_pShip->GetCommandTarget(c_cmdCurrent); if (pmodelTarget) { pfmSSU->otTarget = pmodelTarget->GetObjectType(); pfmSSU->oidTarget = pmodelTarget->GetObjectID(); } else { pfmSSU->otTarget = NA; pfmSSU->oidTarget = NA; } } pfmSSU->bIsRipcording = m_pShip->fRipcordActive(); g.fm.SendMessages(GetGroupSectorFlying(pcluster), FM_GUARANTEED, FM_FLUSH); SetDeviation(0.0f); } // if this is a drone that has arrived in a sector to which it was told // to go, clear its objective. if (!IsPlayer()) { for (Command i = 0; i < c_cmdMax; i++) { ImodelIGC* ptarget = m_pShip->GetCommandTarget(i); // if this command has a cluster buoy in this cluster... if (ptarget && ptarget->GetObjectType() == OT_buoy && ((IbuoyIGC*)ptarget)->GetBuoyType() == c_buoyCluster && ((IbuoyIGC*)ptarget)->GetCluster() == pcluster) { // clear the command m_pShip->SetCommand(i, NULL, c_cidNone); } } } } }
bool CPigShip::OnNewChatMessage() { ImodelIGC* pModel = GetIGC()->GetCommandTarget(c_cmdQueued); // Return if the chat message was not a command or no command is queued if (!pModel) return false; CommandID idCmd = GetIGC()->GetCommandID(c_cmdQueued); const char* pszVerb = (0 <= idCmd && idCmd < c_cidMax) ? c_cdAllCommands[idCmd].szVerb : ""; debugf("...got a <%s> command to %s!!!\n",pszVerb,pModel->GetName()); // Accept the queued command if auto accept is enabled return m_bAutoAcceptCommands ? SUCCEEDED(AcceptCommand(NULL)) : true; }
ImodelIGC* CclusterIGC::GetModel(const char* name) const { assert (name); for (ModelLinkIGC* l = m_models.first(); (l != NULL); l = l->next()) { ImodelIGC* m = l->data(); if (_stricmp(m->GetName(), name) == 0) { return m; } } return NULL; }
//------------------------------------------------------------------------------ void TurnToAction::Execute (void) { IshipIGC* pShip = static_cast<IshipIGC*> (static_cast<ImodelIGC*> (*m_pObject)); ImodelIGC* pTarget = static_cast<ImodelIGC*> (*m_pTarget); if (pShip && pTarget) { Vector delta = pTarget->GetPosition () - pShip->GetPosition (); turnToFace (delta, GetWindow ()->GetDeltaTime (), pShip, &g_setInputControls); g_setInputControls.jsValues[c_axisYaw] *= 0.5f; g_setInputControls.jsValues[c_axisPitch] *= 0.5f; g_setInputControls.jsValues[c_axisRoll] *= 0.5f; } else { g_setInputControls.jsValues[c_axisYaw] = NA; g_setInputControls.jsValues[c_axisPitch] = NA; g_setInputControls.jsValues[c_axisRoll] = NA; } }
//------------------------------------------------------------------------------ /* ImodelIGC* */ CurrentTarget::operator ImodelIGC* (void) { // first, get the ship and its target IshipIGC* pShip = static_cast<IshipIGC*> (static_cast<ImodelIGC*> (*m_pTarget)); assert (pShip); ImodelIGC* pTarget = pShip->GetCommandTarget (c_cmdCurrent); // there is an option to cache the target the first time this target is evaluated. // if that option is set... if (m_bLockOnFirstFetch) { // first check to see if we have done a fetch at all if (not m_pFetched) { // we haven't cached a target yet, so we need to get the target m_pFetched = new TypeIDTarget (pTarget ? pTarget->GetObjectType () : NA, pTarget ? pTarget->GetObjectID () : NA); } else { // we have cached a target, but the reason we want to cache the target is to // determine if a kill has happened, e.g. has the target been eliminated. The // problem is that the player may choose to change the target before // eliminating it, and then we are stuck waiting on the original target. Here // we check to see if the target has been changed w/o eliminating the // original target, and if so, adjust to compensate. ImodelIGC* pFetched = *m_pFetched; if ((pFetched != pTarget) and pFetched and pTarget) { // there has been such a change, so set up a new abstract target delete m_pFetched; m_pFetched = new TypeIDTarget (pTarget ? pTarget->GetObjectType () : NA, pTarget ? pTarget->GetObjectID () : NA); } } return (*m_pFetched); } // that option wasn't requested, so we just return the actual found target return pTarget; }
void CclusterIGC::Update(Time now) { if (now > m_lastUpdate) { float dt = now - m_lastUpdate; bool bStarted = m_pMission->GetMissionStage() == STAGE_STARTED; if (bStarted) { { //Have any stations launch docked drones for (StationLinkIGC* l = m_stations.first(); (l != NULL); l = l->next()) { IstationIGC* pstation = l->data(); ShipLinkIGC* pslNext; for (ShipLinkIGC* psl = pstation->GetShips()->first(); (psl != NULL); psl = pslNext) { IshipIGC* pship = psl->data(); pslNext = psl->next(); //Get the next link now since the ship may launch // const MissionParams* pmp = m_pMission->GetMissionParams(); 04/08 commented out as not needed // mmf 10/07 added so we can get at bExperimental game type if (pship->GetAutopilot() && (pship->GetPilotType() < c_ptPlayer)) { //Docked non-players on autopilot never are observers/parents assert (pship->GetParentShip() == NULL); assert (pship->GetChildShips()->n() == 0); // mmf/yp 10/07 added this so drones launch when ordered to even if OkToLaunch might be false // intentionally left c_cidMine out of the list otherwise miners would launch with their AI // 'order' to mine if (pship->OkToLaunch(now) || (pship->GetCommandID(c_cmdAccepted) == c_cidGoto) || (pship->GetCommandID(c_cmdAccepted) == c_cidBuild) ) pship->SetStation(NULL); // if (pship->OkToLaunch(now)) // mmf orig code // pship->SetStation(NULL); } } //Are any ships buzzing around the stations that a side has yet to eye? #121 #120 Imago 8/10 if (GetShips()->n() > 0 && pstation->GetRoidID() != NA) { Vector pos = pstation->GetRoidPos(); float Sig = pstation->GetRoidSig(); float Radius = pstation->GetRoidRadius(); if (Sig != 0.0f && Radius != 0.0f) { //check if they have a ship eying where the rock would be for (ShipLinkIGC* psl1 = GetShips()->first(); (psl1 != NULL); psl1 = psl1->next()) { IshipIGC* pship = psl1->data(); if (pship->GetParentShip() || pship->GetSide()->GetObjectID() == pstation->GetSide()->GetObjectID() || pstation->SeenBySide(pship->GetSide()) || !pstation->GetRoidSide(pship->GetSide()->GetObjectID())) continue; bool bEye = bSimpleEye(pship->GetHullType()->GetScannerRange(),GetMission()->GetModel(OT_ship,pship->GetObjectID()),Sig,pstation->GetSide()->GetGlobalAttributeSet().GetAttribute(c_gaSignature),Radius,pos); if (bEye) { //Turkey 3/13 #353: kill asteroids for all sides in that alliance. IsideIGC* pside1 = pship->GetSide(); for (SideLinkIGC* sl = m_pMission->GetSides()->first(); sl != NULL; sl = sl->next()) { IsideIGC* pside2 = sl->data(); if (pside1->AlliedSides(pside1, pside2)) { pstation->SetRoidSide(pside2->GetObjectID(),false); GetMission()->GetIgcSite()->KillAsteroidEvent(pstation->GetRoidID(),GetObjectID(),pside2); } } } } } } } } { m_fCost = m_pMission->GetFloatConstant(c_fcidBaseClusterCost); float costLifepod = m_pMission->GetFloatConstant(c_fcidLifepodCost); float costTurret = m_pMission->GetFloatConstant(c_fcidTurretCost); float costPlayer = m_pMission->GetFloatConstant(c_fcidPlayerCost); float costDrone = m_pMission->GetFloatConstant(c_fcidDroneCost); //Have miners and builders do any pre-plotted moves. Allow ships to suicide. ShipLinkIGC* lNext; for (ShipLinkIGC* l = m_ships.first(); (l != NULL); l = lNext) { IshipIGC* s = l->data(); lNext = l->next(); if (s->GetPilotType() < c_ptPlayer) m_fCost += costDrone; else if (s->GetParentShip() != NULL) m_fCost += costTurret; else { IhullTypeIGC* pht = s->GetBaseHullType(); assert (pht); m_fCost += pht->HasCapability(c_habmLifepod) ? costLifepod : costPlayer; } s->PreplotShipMove(now); } if (m_fCost > 0.0f) { m_fCost *= dt / m_pMission->GetFloatConstant(c_fcidClusterDivisor); } { //Have all ships on autopilot plot their moves. Allow ships to suicide. ShipLinkIGC* lNext; for (ShipLinkIGC* l = m_ships.first(); (l != NULL); l = lNext) { IshipIGC* s = l->data(); lNext = l->next(); s->PlotShipMove(now); } } } { //Have all ships execute their moves for (ShipLinkIGC* l = m_ships.first(); (l != NULL); l = l->next()) { IshipIGC* s = l->data(); if (s->GetParentShip() == NULL) { s->ExecuteShipMove(now); } } } } else m_fCost = 0.0f; { //Call the update method on all the contained models //models might self-terminate in the update and nuke earlier models in the update loop //NYI debugging variables //ObjectType oldObjectType = NA; //ObjectType newObjectType = NA; ModelLinkIGC* lNext; for (ModelLinkIGC* l = m_models.first(); (l != NULL); l = lNext) { //oldObjectType = newObjectType; //newObjectType = l->data()->GetObjectType(); lNext = l->next(); l->data()->Update(now); } } if (m_data.activeF && bStarted) { { //Update the bounding boxes for all moving objects & projectiles for (ModelLinkIGC* l = m_models.first(); (l != NULL); l = l->next()) { l->data()->SetBB(m_lastUpdate, now, dt); } m_tMax = dt; } m_kdrStatic.update(); m_kdrMoving.update(); { //Cast rays through the KD tree for each object for (ModelLinkIGC* l = m_modelsCastRay.first(); (l != NULL); l = l->next()) { ImodelIGC* m = l->data(); HitTest* ht = m->GetHitTest(); if (!ht->GetDeadF()) { m_kdrStatic.test(ht, &m_collisions); m_kdrMoving.test(ht, &m_collisions); } } } //Sort the collisions by the time they occur m_collisions.sort(0); //Process each collision (in order) { m_tOffset = 0.0f; for (m_collisionID = 0; (m_collisionID < m_collisions.n()); m_collisionID++) { const CollisionEntry& entry = m_collisions[m_collisionID]; if (!(entry.m_pHitTest1->GetDeadF() || entry.m_pHitTest2->GetDeadF())) { Time timeCollision = m_lastUpdate + (m_tOffset + entry.m_tCollision); ImodelIGC* pModelHitTest1 = (ImodelIGC*)(entry.m_pHitTest1->GetData()); assert (pModelHitTest1); ImodelIGC* pModelHitTest2 = (ImodelIGC*)(entry.m_pHitTest2->GetData()); assert (pModelHitTest2); //Give each participant in the collision a chance to handle the collision //but give the "1st" model first dibs. if ((pModelHitTest1->GetCluster() == this) && (pModelHitTest2->GetCluster() == this)) { pModelHitTest1->HandleCollision(timeCollision, entry.m_tCollision, entry, pModelHitTest2); } } } m_collisions.purge(); } { //Apply any damage from mines //Kids always follow parents in the ship list, so go from back to front //so that the killing a parent doesn't mean hitting dead elements in the list ShipLinkIGC* lTxen; for (ShipLinkIGC* l = m_ships.last(); (l != NULL); l = lTxen) { IshipIGC* s = l->data(); lTxen = l->txen(); s->ApplyMineDamage(); } } //Move each object & projectile { for (ModelLinkIGC* l = m_models.first(); (l != NULL); l = l->next()) { l->data()->Move(); } } if ((m_nPass++) % c_nPassesPerUpdate == 0) { for (ModelLinkIGC* l = m_models.first(); (l != NULL); l = l->next()) { l->data()->UpdateSeenBySide(); } m_pMission->GetIgcSite()->ClusterUpdateEvent(this); } } //Draw and resolve any explosions if (m_nExplosions != 0) { const int c_maxDmgs = 500; IdamageIGC* pdmgs[c_maxDmgs]; int nDmgs = 0; //Copy the list of models in the sector that can be damaged into for (ModelLinkIGC* l = m_modelsPickable.first(); (l != NULL); l = l->next()) { ImodelIGC* pmodel = l->data(); ObjectType type = pmodel->GetObjectType(); //Not everything that can take damage can be affected by an explosion. if ((type == OT_ship) || (type == OT_asteroid) || (type == OT_station) || (type == OT_missile) || (type == OT_probe)) { pmodel->AddRef(); pdmgs[nDmgs++] = (IdamageIGC*)pmodel; if (nDmgs == c_maxDmgs) break; } } ImineIGC* pmines[c_maxDmgs]; int nMines = 0; { for (MineLinkIGC* l = m_mines.first(); (l != NULL); l = l->next()) { ImineIGC* pm = l->data(); pm->AddRef(); pmines[nMines++] = pm; if (nMines == c_maxDmgs) break; } } int i = 0; do { ExplosionData& e = m_explosions[i]; m_pClusterSite->AddExplosion(e.position, e.radius, e.explosionType); float dt = (e.time - m_lastUpdate) - m_tOffset; //Now, the painful part: applying damage to everything in the sector that could be hit { for (int j = 0; (j < nDmgs); j++) { IdamageIGC* pTarget = pdmgs[j]; if (pTarget->GetCluster() == this) //Make sure it wasn't already destroyed { //The target is still around Vector p = pTarget->GetPosition() + dt * pTarget->GetVelocity(); float d = (e.position - p).Length() - pTarget->GetRadius(); if (d < e.radius) { float amount = e.amount; if (d > 0.0f) { float f = 1.0f - (d / e.radius); amount *= f * f; } pTarget->ReceiveDamage(e.damageType | c_dmgidNoWarn | c_dmgidNoDebris, amount, e.time, p, e.position, e.launcher); } } } } { for (int j = 0; (j < nMines); j++) { ImineIGC* pTarget = pmines[j]; if (pTarget->GetCluster() == this) //Make sure it wasn't already destroyed { //The target is still around const Vector& p = pTarget->GetPosition(); float d = (e.position - p).Length() - pTarget->GetRadius(); if (d < e.radius) { float amount = e.amount; if (d > 0.0f) { float f = 1.0f - (d / e.radius); amount *= f * f; } pTarget->ReduceStrength(amount); } } } } if (e.launcher) e.launcher->Release(); } while (++i < m_nExplosions); //Release all the cached pointers { while (--nDmgs >= 0) pdmgs[nDmgs]->Release(); } { while (--nMines >= 0) pmines[nMines]->Release(); } m_nExplosions = 0; } m_lastUpdate = now; } }
void CclusterIGC::RecalculateCollisions(float tOffset, ImodelIGC* pModel1, ImodelIGC* pModel2) { //Update the stop positions for the hit tests (& update their bounding boxes) assert ((pModel1->GetAttributes() & c_mtStatic) == 0); HitTest* pHitTest1 = pModel1->GetHitTest(); if (pHitTest1) { if (pHitTest1->GetDeadF()) pHitTest1 = NULL; else pHitTest1->SetStopPosition(); } HitTest* pHitTest2; if ((pModel2 == NULL) || (pModel2->GetAttributes() & c_mtStatic)) pHitTest2 = NULL; else { pHitTest2 = pModel2->GetHitTest(); if (pHitTest2) { if (pHitTest2->GetDeadF()) pHitTest2 = NULL; else pHitTest2->SetStopPosition(); } } if (pHitTest1 || pHitTest2) { m_tOffset += tOffset; //Don't bother recalculating collisions if we are already outside the window in which collisions can occur. if (m_tOffset <= m_tMax) { { //Move all objects to their positions at the time of the collision for (ModelLinkIGC* l = m_models.first(); (l != NULL); l = l->next()) { ImodelIGC* m = l->data(); HitTest* pht = m->GetHitTest(); //Move the models not involved in the collision if ((m != pModel1) && (m != pModel2)) m->Move(tOffset); else pht->AdjustTimes(tOffset); //Update the bounding boxes for everything pht->UpdateBB(); } } //Remove any collisions that involved either object involved in this collision m_collisions.flush(m_collisionID + 1, pHitTest1, pHitTest2); { //Check for any collisions between either ship and the rest of the stuff in the cluster for (ModelLinkIGC* l = m_models.first(); (l != NULL); l = l->next()) { ImodelIGC* m = l->data(); if ((m != pModel1) && (m != pModel2) && (m->GetAttributes() & (c_mtCastRay | c_mtHitable))) { HitTest* ht = m->GetHitTest(); if (!ht->GetDeadF()) { if (ht->GetID() != c_htidStaticObject) { //ht is not a static object, so it can always go first (which also handles //the problem that projectiles (which ht might be) go before ships). //prevent collisions between projectiles and their launcher. if (pHitTest1 && (ht->GetNoHit() != pHitTest1) && (pHitTest1->GetNoHit() != ht)) ht->Collide(pHitTest1, &m_collisions); if (pHitTest2 && (ht->GetNoHit() != pHitTest2) && (pHitTest2->GetNoHit() != ht)) ht->Collide(pHitTest2, &m_collisions); } else { //in collisions between static objects and non-static objects, the //non-static object is always first if (pHitTest1 && (ht->GetNoHit() != pHitTest1) && (pHitTest1->GetNoHit() != ht)) pHitTest1->Collide(ht, &m_collisions); if (pHitTest2 && (ht->GetNoHit() != pHitTest2) && (pHitTest2->GetNoHit() != ht)) pHitTest2->Collide(ht, &m_collisions); } } } } } //Resort the collisions of the yet to be handled collisions m_collisions.sort(m_collisionID + 1); } } }
void CweaponIGC::FireWeapon(Time now) { assert(m_mountID >= 0); assert(m_ship); bool fFiredShot = false; if (m_fActive && (m_nextFire < now)) { Time lastUpdate = m_ship->GetLastUpdate(); //Never fire retroactively. if (m_nextFire < lastUpdate) m_nextFire = lastUpdate; bool fSelected = fIsWeaponSelected(); float energy = m_ship->GetEnergy(); //the energy the ship would have at "now" if (energy >= m_typeData->energyPerShot) { //We'd be able to fire before now and would have enough energy at now to fire, so ... float rechargeRate = m_ship->GetHullType()->GetRechargeRate(); float energyDeficit = (m_nextFire - now) * //this is how much we are in the hole because we rechargeRate; //are shooting sooner than "now" (must be < 0) short ammo = m_ship->GetAmmo(); if ((ammo > 0) || (m_typeData->cAmmoPerShot == 0)) { // we are firing at least once this frame fFiredShot = true; m_pMission->GetIgcSite()->PlayFFEffect(effectFire, m_pshipGunner ? m_pshipGunner : m_ship); //Get the stuff that won't change between shots IclusterIGC* cluster = m_ship->GetCluster(); assert(cluster); const Orientation& shipOrientation = m_ship->GetOrientation(); //Orientation orientationBfr; const Orientation* pMyOrientation; if (m_pshipGunner) { /* orientationBfr = m_pshipGunner->GetOrientation() * (*m_porientation * shipOrientation); pMyOrientation = &orientationBfr; */ pMyOrientation = &(m_pshipGunner->GetOrientation()); } else { pMyOrientation = &shipOrientation; } //This is how much energy deficit recovers between shots float dtimeBurst = GetDtBurst(); float recharge = rechargeRate * dtimeBurst; const Vector& myVelocity = m_ship->GetVelocity(); Vector myPosition = m_ship->GetPosition() + *m_pposition * shipOrientation; //*pMyOrientation; /* m_ship->GetThingSite()->AddMuzzleFlare( m_emissionPt, min(dtimeBurst * 0.5f, 0.05f) ); */ DataProjectileIGC dataProjectile; dataProjectile.projectileTypeID = m_projectileType->GetObjectID(); float lifespan = GetLifespan(); float speed = m_projectileType->GetSpeed(); if (m_typeData->cAmmoPerShot) speed *= m_ship->GetSide()->GetGlobalAttributeSet().GetAttribute(c_gaSpeedAmmo); bool absoluteF = m_projectileType->GetAbsoluteF(); const Vector* ppositionTarget; const Vector* pvelocityTarget; ImodelIGC* ptarget = NULL; if (m_projectileType->GetBlastPower() != 0.0f) { if (m_pshipGunner) ptarget = m_pshipGunner->GetCommandTarget(c_cmdCurrent); else ptarget = m_ship->GetCommandTarget(c_cmdCurrent); if (ptarget) { if ((ptarget->GetCluster() == cluster) && m_ship->CanSee(ptarget)) { ppositionTarget = &(ptarget->GetPosition()); pvelocityTarget = &(ptarget->GetVelocity()); } else ptarget = NULL; } } int nShots = fSelected ? 10 : 0; //Only allow a single shot if the weapon is no longer selected do { if (energy + energyDeficit < m_typeData->energyPerShot) { //We don't have enough energy to fire at our prefered time ... so wait until we do. m_nextFire += (m_typeData->energyPerShot - (energy + energyDeficit)) / rechargeRate; } //Permute the "forward" direction slightly by a random amount dataProjectile.forward = pMyOrientation->GetForward(); if (m_typeData->dispersion != 0.0f) { float r = random(0.0f, m_typeData->dispersion); float a = random(0.0f, 2.0f * pi); dataProjectile.forward += (r * cos(a)) * pMyOrientation->GetRight(); dataProjectile.forward += (r * sin(a)) * pMyOrientation->GetUp(); dataProjectile.forward.SetNormalize(); } dataProjectile.velocity = speed * dataProjectile.forward; if (!absoluteF) dataProjectile.velocity += myVelocity; Vector position = myPosition + myVelocity * (m_nextFire - lastUpdate); dataProjectile.lifespan = lifespan; if (ptarget) { Vector dV = *pvelocityTarget - dataProjectile.velocity; float dV2 = dV.LengthSquared(); if (dV2 != 0.0f) { Vector dP = position - *ppositionTarget; //reverse so time has right sense dataProjectile.lifespan = (dV * dP) / dV2; if (dataProjectile.lifespan > lifespan) dataProjectile.lifespan = lifespan; else if (dataProjectile.lifespan < 0.1f) dataProjectile.lifespan = 0.1f; //Don't let it explode in our face } } IprojectileIGC* p = (IprojectileIGC*)(m_pMission->CreateObject(m_nextFire, OT_projectile, &dataProjectile, sizeof(dataProjectile))); if (p) { if (m_pshipGunner) p->SetGunner(m_pshipGunner); else p->SetLauncher(m_ship); p->SetPosition(position); p->SetCluster(cluster); p->Release(); } energyDeficit += rechargeRate * dtimeBurst; energy -= m_typeData->energyPerShot; ammo -= m_typeData->cAmmoPerShot; m_nextFire += dtimeBurst; } while ((nShots-- > 0) && (m_nextFire < now) && (energy + energyDeficit >= m_typeData->energyPerShot) && (ammo > 0)); m_ship->SetAmmo(ammo > 0 ? ammo : 0); if ((ammo == 0) && (m_typeData->cAmmoPerShot != 0)) fSelected = false; m_ship->SetEnergy(energy); } } if (!fSelected) Deactivate(); } // if we fired a shot, keep track of it (note - stored localy because the // call to deactivate (above) clears the member variable). m_fFiringShot = fFiredShot; // if we are still firing and have the energy and ammo for the next shot, // assume we are firing a burst. if ((m_ship->GetEnergy() >= m_typeData->energyPerShot) && (m_ship->GetAmmo() >= m_typeData->cAmmoPerShot) && (m_fFiringBurst || (m_fActive && m_fFiringShot)) // a burst starts with a shot ) { m_fFiringBurst = true; } else { m_fFiringBurst = false; } }
//------------------------------------------------------------------------------ Condition* Mission6::CreateMission (void) { GoalList* pGoalList = new GoalList; // play the introductory audio pGoalList->AddGoal (CreatePlaySoundGoal (salCommenceScanSound)); // wait half second pGoalList->AddGoal (new Goal (new ElapsedTimeCondition (0.5f))); // tm_6_01 // Okay, Cadet, here's your Advanced Fighter. There's a base // outpost here in case you need to replenish yourself. pGoalList->AddGoal (CreatePlaySoundGoal (tm_6_01Sound)); // wait two more seconds pGoalList->AddGoal (new Goal (new ElapsedTimeCondition (2.0f))); // tm_6_02 // Iron Coalition Intelligence reports inbound enemy craft. // They're using an old code for their comms, so we can hear // them. Watch your message stream to see what they're up to. { Goal* pGoal = CreatePlaySoundGoal (tm_6_02Sound); pGoal->AddStartAction (new SetDisplayModeAction (TrekWindow::cmCockpit)); pGoal->AddStartAction (new MessageAction ("Watch the chat to see what the enemy craft are after.")); pGoalList->AddGoal (pGoal); } // wait half second pGoalList->AddGoal (new Goal (new ElapsedTimeCondition (0.5f))); // tm_6_03 // DEFEND THE MINERS! This simulation is over when you die. pGoalList->AddGoal (CreatePlaySoundGoal (tm_6_03Sound)); // wait two more seconds pGoalList->AddGoal (new Goal (new ElapsedTimeCondition (2.0f))); // need this ImissionIGC* pMission = trekClient.GetCore(); ImodelIGC* pStation = pMission->GetModel (OT_station, 1030); // wait for player to be dead { Goal* pGoal = new Goal (new FalseCondition); // create enemy ships ShipID enemyShipID = pMission->GenerateNewShipID (); CreateDroneAction* pCreateDroneAction = new CreateDroneAction ("Enemy Support", enemyShipID, 310, 1, c_ptWingman); pCreateDroneAction->SetCreatedLocation (GetStartSectorID (), Vector (3800.0f, 4275.0f, 855.0f)); Condition* pShipIsDestroyedcondition = new GetShipIsDestroyedCondition2 (OT_ship, static_cast<ObjectID> (enemyShipID)); pGoal->AddConstraintCondition (new ConditionalAction (pShipIsDestroyedcondition, pCreateDroneAction)); enemyShipID = pMission->GenerateNewShipID (); pCreateDroneAction = new CreateDroneAction ("Enemy Fighter", enemyShipID, 315, 1, c_ptWingman); pCreateDroneAction->SetCreatedLocation (GetStartSectorID (), Vector (3800.0f, 4175.0f, 855.0f)); pShipIsDestroyedcondition = new GetShipIsDestroyedCondition2 (OT_ship, static_cast<ObjectID> (enemyShipID)); pGoal->AddConstraintCondition (new ConditionalAction (pShipIsDestroyedcondition, pCreateDroneAction)); pGoalList->AddGoal (pGoal); } // build the goal that we'll return { Goal* pGoal = new Goal (pGoalList); // create friendly miners Vector pos = pStation->GetPosition (); pos.x += random(-1000.0f, 1000.0f); pos.y += random(-1000.0f, 1000.0f); pos.z += random(-1000.0f, 1000.0f); ShipID minerShipID = pMission->GenerateNewShipID (); CreateDroneAction* pCreateDroneAction = new CreateDroneAction ("Miner 01", minerShipID, 436, 0, c_ptMiner); pCreateDroneAction->SetCreatedLocation (GetStartSectorID (), pos); Condition* pShipIsDestroyedcondition = new GetShipIsDestroyedCondition2 (OT_ship, static_cast<ObjectID> (minerShipID)); pGoal->AddConstraintCondition (new ConditionalAction (pShipIsDestroyedcondition, pCreateDroneAction)); pos = pStation->GetPosition (); pos.x += random(-1000.0f, 1000.0f); pos.y += random(-1000.0f, 1000.0f); pos.z += random(-1000.0f, 1000.0f); minerShipID = pMission->GenerateNewShipID (); pCreateDroneAction = new CreateDroneAction ("Miner 02", minerShipID, 436, 0, c_ptMiner); pCreateDroneAction->SetCreatedLocation (GetStartSectorID (), pos); pShipIsDestroyedcondition = new GetShipIsDestroyedCondition2 (OT_ship, static_cast<ObjectID> (minerShipID)); pGoal->AddConstraintCondition (new ConditionalAction (pShipIsDestroyedcondition, pCreateDroneAction)); pos = pStation->GetPosition (); pos.x += random(-1000.0f, 1000.0f); pos.y += random(-1000.0f, 1000.0f); pos.z += random(-1000.0f, 1000.0f); minerShipID = pMission->GenerateNewShipID (); pCreateDroneAction = new CreateDroneAction ("Miner 03", minerShipID, 436, 0, c_ptMiner); pCreateDroneAction->SetCreatedLocation (GetStartSectorID (), pos); pShipIsDestroyedcondition = new GetShipIsDestroyedCondition2 (OT_ship, static_cast<ObjectID> (minerShipID)); pGoal->AddConstraintCondition (new ConditionalAction (pShipIsDestroyedcondition, pCreateDroneAction)); pos = pStation->GetPosition (); pos.x += random(-1000.0f, 1000.0f); pos.y += random(-1000.0f, 1000.0f); pos.z += random(-1000.0f, 1000.0f); minerShipID = pMission->GenerateNewShipID (); pCreateDroneAction = new CreateDroneAction ("Miner 04", minerShipID, 436, 0, c_ptMiner); pCreateDroneAction->SetCreatedLocation (GetStartSectorID (), pos); pShipIsDestroyedcondition = new GetShipIsDestroyedCondition2 (OT_ship, static_cast<ObjectID> (minerShipID)); pGoal->AddConstraintCondition (new ConditionalAction (pShipIsDestroyedcondition, pCreateDroneAction)); return pGoal; } }
void Paint(ItemID pitemArg, Surface* psurface, bool bSelected, bool bFocus) { ImodelIGC* pDestination = (ImodelIGC*)pitemArg; IshipIGC* pship = NULL; IstationIGC* pstation = NULL; if (pDestination == NULL || trekClient.MyMission() == NULL) return; if (pDestination->GetObjectType() == OT_ship) { CastTo(pship, pDestination); } else { assert(pDestination->GetObjectType() == OT_station); CastTo(pstation, pDestination); } // draw the selection bar if (bSelected) { psurface->FillRect( WinRect(0, 0, GetXSize(), GetYSize()), Color::Red() ); } TRef<IEngineFont> pfont; // show the place we currently are in bold if (pship && pship == trekClient.GetShip()->GetParentShip() || pstation && pstation == trekClient.GetShip()->GetStation()) { pfont = TrekResources::SmallBoldFont(); } else { pfont = TrekResources::SmallFont(); } Color color; if (CanKeepCurrentShip(pDestination)) { color = Color::White(); } else { color = 0.75f * Color::White(); } // draw the name psurface->DrawString( pfont, color, WinPoint(0, 0), pship ? pship->GetName() : pstation->GetName() ); // draw the ship type (if any) if (pship) { psurface->DrawString( pfont, color, WinPoint(m_viColumns[0], 0), HullName(pDestination) ); } // draw the cluster psurface->DrawString( pfont, color, WinPoint(m_viColumns[1] + 2, 0), SectorName(pDestination) ); // draw the total number of turrets (if appropriate) if (pship && NumTurrets(pship)) { int nNumTurrets = NumTurrets(pship); if (nNumTurrets != 0) { psurface->DrawString( pfont, color, WinPoint(m_viColumns[2] + 2, 0), ZString((int)MannedTurrets(pship)) + ZString("/") + ZString(nNumTurrets) ); } } }
bool OnButtonTeleport() { ImodelIGC* pDestination = (ImodelIGC*)(m_plistPaneDestinations->GetSelection()); IstationIGC* pstation = NULL; if (pDestination == NULL || trekClient.MyMission() == NULL || trekClient.GetShip()->GetCluster() != NULL) return true; if (pDestination->GetObjectType() == OT_ship) { // if this is a ship, try boarding it. IshipIGC* pship; CastTo(pship, pDestination); if (trekClient.GetShip()->GetParentShip() != NULL) { trekClient.DisembarkAndBoard(pship); } else { trekClient.BoardShip(pship); } trekClient.PlaySoundEffect(personalJumpSound); } else { // try teleporting to that station IstationIGC* pstation; CastTo(pstation, pDestination); if (trekClient.GetShip()->GetParentShip() != NULL) { // if they are already there, just get off of the ship if (pstation == trekClient.GetShip()->GetParentShip()->GetStation()) { trekClient.BoardShip(NULL); } else { trekClient.DisembarkAndTeleport(pstation); } } else { if (pstation != trekClient.GetShip()->GetStation()) { trekClient.SetMessageType(BaseClient::c_mtGuaranteed); BEGIN_PFM_CREATE(trekClient.m_fm, pfmDocked, C, DOCKED) END_PFM_CREATE pfmDocked->stationID = pstation->GetObjectID(); trekClient.StartLockDown( "Teleporting to " + ZString(pstation->GetName()) + "....", BaseClient::lockdownTeleporting); } } } // dismiss the teleport pane. GetWindow()->TurnOffOverlayFlags(ofTeleportPane); return true; }
//This should only be called from the ChangeCluster() callback. void CFSPlayer::SetCluster(IclusterIGC* pcluster, bool bViewOnly) { CFSShip::SetCluster(pcluster, bViewOnly); if (pcluster) { SetDPGroup((CFSCluster*)(pcluster->GetPrivateData()), true); IshipIGC* pshipParent = GetIGCShip()->GetParentShip(); if ((pshipParent == NULL) || bViewOnly) { ShipID shipID = GetIGCShip()->GetObjectID(); assert(0 == g.fm.CbUsedSpaceInOutbox()); if (!bViewOnly) { //Move the player to his destination BEGIN_PFM_CREATE(g.fm, pfmSetCluster, S, SET_CLUSTER) END_PFM_CREATE pfmSetCluster->sectorID = pcluster->GetObjectID(); //Send the position of the parent ship if we are a child, otherwise our position IshipIGC* pshipSource = pshipParent ? pshipParent : GetIGCShip(); pshipSource->ExportShipUpdate(&(pfmSetCluster->shipupdate)); pfmSetCluster->cookie = NewCookie(); } { for (ShipLinkIGC* pshiplink = pcluster->GetShips()->first(); pshiplink; pshiplink = pshiplink->next()) { IshipIGC * pshipExist = pshiplink->data(); if ((pshipExist != GetIGCShip()) && (pshipExist != pshipParent)) { IshipIGC* pshipExistParent = pshipExist->GetParentShip(); //Tell the new player where the existing ship is/was //provided the existing ship is not the child of some other ship //and is not the parent of the new ship if (pshipExistParent == NULL) { CFSShip * pfsShipExist = (CFSShip *) pshipExist->GetPrivateData(); pfsShipExist->QueueLoadoutChange(); BEGIN_PFM_CREATE(g.fm, pfmSSU, S, SINGLE_SHIP_UPDATE) END_PFM_CREATE //Always use the ship update based on the server's current view of the universe //(this shouldn't be a lot worse than anything the player sent and it is easier) pshipExist->ExportShipUpdate(&(pfmSSU->shipupdate)); { ImodelIGC* pmodelTarget = pshipExist->GetCommandTarget(c_cmdCurrent); if (pmodelTarget) { pfmSSU->otTarget = pmodelTarget->GetObjectType(); pfmSSU->oidTarget = pmodelTarget->GetObjectID(); } else { pfmSSU->otTarget = NA; pfmSSU->oidTarget = NA; } } pfmSSU->bIsRipcording = pshipExist->fRipcordActive(); } } } } { // Let's build up a list of station updates so we can batch 'em down IsideIGC* pside = GetIGCShip()->GetSide(); { const StationListIGC * pstnlist = pcluster->GetStations(); int nStations = 0; { //Count the number of visible stations for (StationLinkIGC* pstnlink = pstnlist->first(); pstnlink; pstnlink = pstnlink->next()) { IstationIGC* pstation = pstnlink->data(); if (pstation->SeenBySide(pside)) nStations++; } } if (nStations != 0) { // tell the client what happened BEGIN_PFM_CREATE(g.fm, pfmStationsUpdate, S, STATIONS_UPDATE) FM_VAR_PARM(NULL, nStations * sizeof(StationState)) END_PFM_CREATE StationState* pss = (StationState*)(FM_VAR_REF(pfmStationsUpdate, rgStationStates)); for (StationLinkIGC* pstnlink = pstnlist->first(); pstnlink; pstnlink = pstnlink->next()) { IstationIGC * pstation = pstnlink->data(); if (pstation->SeenBySide(pside)) { pss->stationID = pstation->GetObjectID(); pss->bpHullFraction = pstation->GetFraction(); (pss++)->bpShieldFraction = pstation->GetShieldFraction(); } } } } { //Let's build up a list of probe updates and batch them on down (only damage & visible probes) const ProbeListIGC * pprblist = pcluster->GetProbes(); int nProbes = 0; { for (ProbeLinkIGC* pprblink = pprblist->first(); pprblink; pprblink = pprblink->next()) { if (pprblink->data()->SeenBySide(pside)) nProbes++; } } if (nProbes != 0) { BEGIN_PFM_CREATE(g.fm, pfmProbesUpdate, S, PROBES_UPDATE) FM_VAR_PARM(NULL, nProbes * sizeof(ProbeState)) END_PFM_CREATE ProbeState* pps = (ProbeState*)(FM_VAR_REF(pfmProbesUpdate, rgProbeStates)); for (ProbeLinkIGC* pprblink = pprblist->first(); pprblink; pprblink = pprblink->next()) { IprobeIGC * pprobe = pprblink->data(); if (pprobe->SeenBySide(pside)) { pps->probeID = pprobe->GetObjectID(); (pps++)->bpFraction = pprobe->GetFraction(); } } } } { //Let's build up a list of asteroid updates and batch them on down const AsteroidListIGC * pastlist = pcluster->GetAsteroids(); int nAsteroids = 0; { for (AsteroidLinkIGC* pastlink = pastlist->first(); pastlink; pastlink = pastlink->next()) { if (pastlink->data()->SeenBySide(pside)) nAsteroids++; } } if (nAsteroids != 0) { BEGIN_PFM_CREATE(g.fm, pfmAsteroidsUpdate, S, ASTEROIDS_UPDATE) FM_VAR_PARM(NULL, nAsteroids * sizeof(AsteroidState)) END_PFM_CREATE AsteroidState* pas = (AsteroidState*)(FM_VAR_REF(pfmAsteroidsUpdate, rgAsteroidStates)); for (AsteroidLinkIGC* pastlink = pastlist->first(); pastlink; pastlink = pastlink->next()) { IasteroidIGC * pasteroid = pastlink->data(); if (pasteroid->SeenBySide(pside)) { pas->asteroidID = pasteroid->GetObjectID(); pas->ore = short(pasteroid->GetOre()); pas->co.Set(pasteroid->GetOrientation()); (pas++)->bpFraction = pasteroid->GetFraction(); } } } } } //Also send the identical message to all of the ship's children] if (!bViewOnly) //TheRock 4-1-2010 fixed ships overlaying in f3 while on a turret { for (ShipLinkIGC* psl = GetIGCShip()->GetChildShips()->first(); (psl != NULL); psl = psl->next()) { CFSShip* pfsShip = (CFSShip*)(psl->data()->GetPrivateData()); assert (pfsShip->IsPlayer()); pfsShip->GetPlayer()->ResetLastUpdate(); g.fm.SendMessages(pfsShip->GetPlayer()->GetConnection(), FM_GUARANTEED, FM_DONT_FLUSH); } } g.fm.SendMessages(GetConnection(), FM_GUARANTEED, FM_FLUSH); } } else if (bViewOnly) { IstationIGC* pstation = GetIGCShip()->GetStation(); assert (pstation); CFSCluster* pfsCluster = (CFSCluster*)(pstation->GetCluster()->GetPrivateData()); SetDPGroup(pfsCluster, false); } else SetDPGroup(NULL, false); }