예제 #1
0
    //------------------------------------------------------------------------------
    Goal*       Mission5::CreateGoal03 (void)
    {
        GoalList*   pGoalList = new GoalList;

		// tm_5_12
		// Attention, Cadet, new contact: an enemy scout. In some 
		// cases, utility craft like miners will run home for 
		// protection, but you can tell them to hide by giving them 
		// orders to go to a base. You left-click the miners, then 
		// left-click the Go To command, and then right-click ÿ the 
		// base.
        {
            Goal*               pGoal = CreatePlaySoundGoal (tm_5_12Sound);
            IwarpIGC*           pAlephMars = trekClient.GetCore ()->GetWarp (1052);
            Orientation         alephMarsOrientation = pAlephMars->GetOrientation ();

            // create the enemy scout
            Vector              pos = pAlephMars->GetPosition () + (alephMarsOrientation.GetForward () * random (800.0f, 1200.0f)) + (alephMarsOrientation.GetRight () * random(-100.0f, 200.0f));
            CreateDroneAction*  pCreateDroneAction = new CreateDroneAction ("Enemy Scout", m_enemyScoutID, 310, 1, c_ptWingman);
            pCreateDroneAction->SetCreatedLocation (GetStartSectorID () + 1, pos);
            pGoal->AddStartAction (pCreateDroneAction);

            // tell the enemy scout of these guys to do nothing
            pGoal->AddStartAction (new SetCommandAction (m_enemyScoutID, c_cmdAccepted, NULL, c_cidDoNothing));
            pGoal->AddStartAction (new SetCommandAction (m_enemyScoutID, c_cmdCurrent, NULL, c_cidDoNothing));

            // set its signature to infinity
            pGoal->AddStartAction (new SetSignatureAction (OT_ship, m_enemyScoutID, 1.0e6f));
            pGoalList->AddGoal (pGoal);
        }

        // wait half second
        pGoalList->AddGoal (new Goal (new ElapsedTimeCondition (0.5f)));

		// tm_5_13
		// Most enemy ships can be considered a threat to your miners 
		// unless you have plenty of defending pilots ? which you 
		// don?t. So let's get those miners to shelter ? send all 
		// three of them to the base.
        pGoalList->AddGoal (CreatePlaySoundGoal (tm_5_13Sound));

		// tm_5_13r
		// Send all three of your miners to base for safety.
        {
            Condition*  pAndConditionA = new AndCondition (new GetCommandCondition (m_miner2ID, c_cidGoto), new GetCommandCondition (m_miner3ID, c_cidGoto));
            Condition*  pConditionB = new GetCommandCondition (m_miner4ID, c_cidGoto);
            Goal*       pGoal = new Goal (new AndCondition (pAndConditionA, pConditionB));
            pGoal->AddStartAction (new MessageAction ("Order all three miners back to base for safety."));
            pGoal->AddConstraintCondition (CreateTooLongCondition (30.0f, tm_5_13rSound));
            pGoalList->AddGoal (pGoal);
        }

        // wait half second
        pGoalList->AddGoal (new Goal (new ElapsedTimeCondition (0.5f)));

		// tm_5_14
		// Good! Utility ships like miners and constructors are 
		// drones. They will always accept your orders.
        pGoalList->AddGoal (CreatePlaySoundGoal (tm_5_14Sound));

        // wait half second
        pGoalList->AddGoal (new Goal (new ElapsedTimeCondition (0.5f)));

        return new Goal (pGoalList);
    }
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);

                //We'll be able to take a shot
                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;

                //If we have a target ... find the closest enemy ship who is a valid target
                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)
                    {
                        //Threats to stations get highest priority
                        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;

                    //It is going to shoot ... make it visible to everyone in the sector
                    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))
                            {
                                //Does this side have any scanners in the sector?
                                ClusterSite*    pcs = pcluster->GetClusterSite();
                                const ScannerListIGC*   psl = pcs->GetScanners(psideOther->GetObjectID());
                                if ((psl->n() != 0) || (m_pMission->GetMissionParams()->bAllowAlliedViz && psideOther->AlliedSides(psideOther,pside))) //ALLY 7/3/09 VISIBILITY 7/11/09 imago
                                    SetSideVisibility(psideOther, true);
                                else
                                    m_bSeenByAll = false;
                            }
                        }
                    }

                    //We have a target ... fire along directionMin (modulo dispersion)
                    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
                    {
                        //Permute the "forward" direction slightly by a random amount
                        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();
                        }

                        //We never move, so skip all the velocity calculations
                        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
                {
                    //No shots this cycle
                    m_nextFire = now;
                }
            }
        }

        TmodelIGC<IprobeIGC>::Update(now);
    }
}
void CFSShip::HitWarp(IwarpIGC * pwarp)
{
    //Ignore jumps that happen too closely together
    if (m_warpState == warpReady)
    {
		// Andon - Added check for aleph mass limits
		if (m_pShip->GetMass() <= pwarp->MassLimit() || !IsPlayer() && pwarp->MassLimit() > 0 || pwarp->MassLimit() < 0)
		{
			if (IsPlayer())
			{
				m_warpState = warpNoUpdate;
			}

			IwarpIGC *    pwarpDest    = pwarp->GetDestination();
			assert (pwarpDest);
			IclusterIGC * pclusterDest = pwarpDest->GetCluster();

			ShipStatusWarped(pwarp);

			Orientation alephOrientation = pwarpDest->GetOrientation();
			const Vector&   v = m_pShip->GetVelocity();
			float           speed2 = v.LengthSquared();
			float           speed  = float(sqrt(speed2));
			if (speed2 > 0)
			{
			  float           error;
			  {
				  //How close is the ship coming to the center of the warp?
				  Vector          dp = pwarp->GetPosition() - m_pShip->GetPosition();

				  float   t = (dp * v) / speed2;
				  float   d = (dp - t * v).LengthSquared();
				  float   r = pwarp->GetRadius();

				  error = (d / (r*r)) + 0.125f;      //Error ranges from 0.125 to 1.125
				  // yp: to prevent 'spin of death' in massive ships.
				  // This works and is explained in that the more massive the ship the less effect going through the aleph should have
				  // on its rotational velocity. The massive amount of inertia should decrease changes in rotational velocity.
				  if(m_pShip->GetMass() > 300.0f)
				  {
					error = error * (300.0f / m_pShip->GetMass()); // the greater the mass is above 750 the less error will be applied.
				  }
				  // yp end
			  }

			  alephOrientation.Pitch(random(-error, error));
			  alephOrientation.Yaw(random(-error, error));

			  m_pShip->SetCurrentTurnRate(c_axisRoll,
										  m_pShip->GetCurrentTurnRate(c_axisRoll) +
										  random(pi * 0.5f * error, pi * 1.5f * error));  //Must be less than 2.0 * pi
			}
			m_pShip->SetOrientation(alephOrientation);
			const Vector&   backward = alephOrientation.GetBackward();

			speed = -(speed + pwarp->GetMission()->GetFloatConstant(c_fcidExitWarpSpeed));
			m_pShip->SetVelocity(backward * speed);

			m_pShip->SetPosition(pwarpDest->GetPosition() +
								 (alephOrientation.GetUp() * random(2.0f, 5.0f)) +
								 (alephOrientation.GetRight() * random(2.0f, 5.0f)) -
								 (m_pShip->GetRadius() + 5.0f) * backward);

			GetIGCShip()->SetCluster(pclusterDest);
		}
    }
}