1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156 |
- #ifndef GOAL_H_
- #define GOAL_H_
- /*-------------------------------------------------------------------------
- * Constant: HowClose
- *-------------------------------------------------------------------------
- * Purpose:
- * How close do I want the GotoGoal to put me to my target.
- * Since I didn't want to have every call to GotoGoal have to specify the
- * acceptable radius from the target, I overloaded the constructor, and let
- * the default value be defined with this constant.
- */
- const float c_fHowClose = 40.0f; //Leave a lot of slack so things won't bounce on autopilot
- /*-------------------------------------------------------------------------
- * Constant: HowCloseFollow
- *-------------------------------------------------------------------------
- * Purpose:
- * Probably don't want to follow something as close as I would want to goto
- * it, so make that it's own variable
- */
- const float c_fHowCloseFollow = 25.0f;
- // Abstract Goal Types:
- /*-------------------------------------------------------------------------
- * Abstract Class: Goal
- *-------------------------------------------------------------------------
- * Purpose:
- * This class sets up the interface and framework for all of the goal classes
- * and implements default behaviors so that the children don't have to redo code.
- */
- class Goal
- {
- public:
- Goal(Drone* pDrone, CommandType type) :
- m_pDrone(pDrone),
- m_pShip(pDrone->GetShip()),
- m_tCreated(Time::Now()),
- m_tLastUpdate(Time::Now()),
- m_ctType(type),
- DONE(true)
- {};
- virtual ~Goal() // Need virtual destructor so that I can call Goal::~Goal for all children, too
- {};
-
- virtual void Update(Time now, float dt) // Keep timing, and update CshipIGC targeting info
- {
- m_tLastUpdate = now;
- };
- virtual bool Done(void) // Never end
- {
- return false;
- };
- virtual void Status(void) = 0; // Just an interface class
- virtual void DoneEvent(void) // Default done message
- {
- m_pDrone->Verbose("Goal Accomplished...");
- };
- CommandType GetType(void) // Return the type of child this is
- {
- return m_ctType;
- };
- virtual ImodelIGC* GetTarget(void) // Some goals do have targets, but assume that we don't
- {
- return NULL;
- };
- protected:
- void Report(const char* format, ...); // Call Gamesite::DroneSendChat()
- Drone* m_pDrone; // Keep track of the drone that is using this goal
- IshipIGC* m_pShip; // Can get this from the drone, but we use it all the time
- Time m_tCreated; // Keep some timing information
- Time m_tLastUpdate;
- CommandType m_ctType; // Need to know a which child it is
- const bool DONE; // Just mapping true to the name DONE
- friend class Drone; // Drone needs to get at this stuff
- };
- /*-------------------------------------------------------------------------
- * Abstract Class: TargetedGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * A majority of the goals need to keep a target. Hold on to that TRef here,
- * and handle the basic checks for whether that object is still valid, etc.
- */
- class TargetedGoal : public Goal
- {
- public:
- TargetedGoal(Drone* pDrone, ImodelIGC* pTarget, CommandType type) :
- Goal(pDrone, type),
- m_pTarget(pTarget)
- {};
-
- virtual bool Done(void) // Done if my object is no longer valid
- {
- return (OBJECT_IS_BAD(m_pTarget));
- };
-
- virtual void DoneEvent(void) // Default targeted goal done message
- {
- m_pDrone->Verbose("Target is no longer valid");
- };
- virtual ImodelIGC* GetTarget(void) // Return the real target
- {
- return m_pTarget;
- };
- protected:
- TRef<ImodelIGC> m_pTarget; // Keep track of a target for the goal
- };
- // Actual Goal Types
- /*-------------------------------------------------------------------------
- * Class: IdleGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * Don't do anything but sit still and dodge. This goal never ends.
- */
- class IdleGoal : public Goal
- {
- public:
- IdleGoal (Drone* pDrone) :
- Goal(pDrone, c_ctStop)
- {};
-
- virtual void Update(Time now, float dt);
- virtual void Status(void)
- {
- Report("Awaiting orders");
- };
- };
- /*-------------------------------------------------------------------------
- * Class: StayPutGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * Don't do anything but sit still and dodge. This goal times out after
- * the TIME_LIMIT.
- */
- class StayPutGoal : public IdleGoal
- {
- public:
- StayPutGoal (Drone* pDrone) :
- IdleGoal(pDrone),
- TIME_LIMIT(120.0f)
- {};
-
- virtual bool Done(void) // Have we hit the time limit yet?
- {
- float length = m_tLastUpdate - m_tCreated;
- return (length >= TIME_LIMIT);
- };
- virtual void DoneEvent(void) // If it ended, it was because it timed out
- {
- m_pDrone->Verbose("I'm not going to just sit here forever");
- };
- protected:
- const float TIME_LIMIT; // How long will I just sit there?
- };
- /*-------------------------------------------------------------------------
- * Class: GotoGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * Use the DoGotoAction to get within the specified radius of the target,
- * and maybe stop when we get there.
- */
- class GotoGoal : public TargetedGoal
- {
- public:
- GotoGoal (Drone* pDrone, ImodelIGC* pTarget, bool stopThere = false, bool dodgeBullets = true) :
- TargetedGoal(pDrone,pTarget, c_ctGoto),
- fGotThere(false),
- fStopThere(stopThere),
- fDodgeBullets(dodgeBullets)
- {
- distFromTarget = c_fHowClose + pTarget->GetRadius();
- m_dist2 = distFromTarget * distFromTarget;
- };
- GotoGoal (Drone* pDrone, ImodelIGC* pTarget, float radius, bool stopThere = false, bool dodgeBullets = true) :
- TargetedGoal(pDrone,pTarget, c_ctGoto),
- fGotThere(false),
- distFromTarget(radius - 1.0f), // If we are given a radius, then adjust it to account for the
- fStopThere(stopThere), // weirdness of DoGotoAction (considers a goal done if the distance between the
- fDodgeBullets(dodgeBullets) // goal and the current pos is less that sqrt(1) )
- {
- m_dist2 = distFromTarget * distFromTarget;
- };
- virtual void Update(Time now, float dt);
- virtual void Status()
- {
- Report("Going to %s", GetModelName(m_pTarget));
- };
- virtual bool Done() // Either the object is bad, or we got there
- {
- //Hack time ... do a special case for going to a warp: you are there if you are in the same sector as its destination
- if (m_pTarget->GetObjectType() == OT_warp)
- {
- IwarpIGC* pwarpDestination = ((IwarpIGC*)((ImodelIGC*)m_pTarget))->GetDestination();
- assert (pwarpDestination);
- return m_pShip->GetCluster() == pwarpDestination->GetCluster();
- }
- return (fGotThere || TargetedGoal::Done()) ;
- };
- virtual void DoneEvent() // Report a message appropriate to why we finished
- {
- if (TargetedGoal::Done())
- TargetedGoal::DoneEvent();
- else
- m_pDrone->Verbose("I have reached %s", GetModelName(m_pTarget));
- };
- private:
- float distFromTarget; // Need to figure out the actual range that we want (but only need to do it once)
- bool fGotThere; // Set this flag according to DoGotoAction
- bool fStopThere; // Do we want to push a stop command when we get there?
- bool fDodgeBullets; // Sometimes, we don't want to dodge bullets in the process
- float m_dist2; // Only compute distance*distance one time
- };
- class NewGotoGoal : public TargetedGoal
- {
- public:
- NewGotoGoal (Drone* pDrone,
- ImodelIGC* pTarget,
- Waypoint::Objective objective = Waypoint::c_oEnter,
- float offset = c_fHowClose,
- CommandType ct = c_ctGoto)
- :
- TargetedGoal(pDrone, pTarget, ct),
- m_gotoplan(pDrone->GetShip())
- {
- m_gotoplan.Set(objective, pTarget, offset);
- };
- virtual void Update(Time now, float dt)
- {
- if (m_pTarget)
- m_gotoplan.Execute(now, dt, true);
- }
- virtual void Status()
- {
- Report("Going to %s", GetModelName(m_pTarget));
- };
- virtual bool Done() // Either the object is bad, or we got there
- {
- return !m_pTarget; //m_gotoplan.GetMaskWaypoints() == 0;
- };
- virtual void DoneEvent() // Report a message appropriate to why we finished
- {
- if (TargetedGoal::Done())
- TargetedGoal::DoneEvent();
- else
- m_pDrone->Verbose("I have reached %s", GetModelName(m_pTarget));
- };
- void SetGotoPlan(Waypoint::Objective o, ImodelIGC * pmodelTarget, float offset = 0.0f)
- {
- m_pTarget = pmodelTarget;
- m_gotoplan.Set(o, pmodelTarget, offset);
- }
- protected:
- GotoPlan m_gotoplan;
- };
- /*-------------------------------------------------------------------------
- * Class: GotoSameSectorGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * If we aren't in the same sector as the target, then we need to go through
- * alephs until we are in the right sector. FindPath should always return the
- * correct to go through next.
- */
- class GotoSameSectorGoal : public GotoGoal
- {
- public:
- GotoSameSectorGoal (Drone *pDrone, ImodelIGC* pTarget, bool dodgeBullets = true) :
- GotoGoal(pDrone, FindPath(pDrone->GetShip(), pTarget), 0.0f, false, dodgeBullets),
- m_pFinalTarget(pTarget),
- m_pCurCluster(pDrone->GetShip()->GetCluster()),
- m_pTarCluster(pTarget->GetCluster())
- {};
- virtual void Update(Time now, float dt) // If the clusters of either of the objects change,
- { // then recompute the FindPath
- assert (!OBJECT_IS_BAD(m_pTarget) && !OBJECT_IS_BAD(m_pFinalTarget));
- if ((m_pShip->GetCluster() != m_pCurCluster) || (m_pFinalTarget->GetCluster() != m_pTarCluster))
- {
- m_pCurCluster = m_pShip->GetCluster();
- m_pTarCluster = m_pFinalTarget->GetCluster();
- m_pTarget = FindPath(m_pShip, m_pFinalTarget);
- if (Done())
- return;
- }
- GotoGoal::Update(now, dt); // Just goto the aleph
- };
- virtual bool Done() // If either of the objects is no longer valid,
- { // or we have succeeding in getting to the same sector
- return (TargetedGoal::Done() || OBJECT_IS_BAD(m_pFinalTarget) || (m_pShip->GetCluster() == m_pFinalTarget->GetCluster()));
- };
- virtual void DoneEvent() // Announce that we got there
- {
- if (TargetedGoal::Done())
- TargetedGoal::DoneEvent();
- else
- m_pDrone->Verbose("%s and I are both in %s", GetModelName(m_pFinalTarget), m_pTarCluster->GetName());
- };
- private:
- TRef<ImodelIGC> m_pFinalTarget; // This is the model we're trying to get to
- TRef<IclusterIGC> m_pCurCluster; // This is the cluster we are currently in
- TRef<IclusterIGC> m_pTarCluster; // This is the cluster that we are trying to get to
- };
- /*-------------------------------------------------------------------------
- * Class: FollowGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * Fly on the wing of the target object. If the target is static, then this
- * is just an un-ending goto command
- */
- class FollowGoal : public TargetedGoal
- {
- public:
- FollowGoal (Drone* pDrone, ImodelIGC* pTarget) :
- TargetedGoal(pDrone,pTarget, c_ctFollow)
- {};
- virtual void Update(Time now, float dt);
- virtual void Status(void)
- {
- Report("Following %s", GetModelName(m_pTarget));
- };
- };
- /*-------------------------------------------------------------------------
- * Class: DestroyGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * Attack the target with all of your guns. If you don't have any guns,
- * then try to ram it to death
- */
- class DestroyGoal : public TargetedGoal
- {
- public:
- DestroyGoal (Drone* pDrone, ImodelIGC* pTarget) :
- TargetedGoal(pDrone,pTarget, c_ctDestroy),
- sCurrent(c_None)
- {};
- virtual void Update(Time now, float dt);
- virtual void Status(void)
- {
- Report("Attempting to destroy %s", GetModelName(m_pTarget));
- };
- virtual void DoneEvent(void) // Somehow the object is no longer around
- {
- m_pDrone->Verbose("%s has been destroyed", GetModelName(m_pTarget));
- };
- protected:
- enum State // Maintian some state information for verbose comments
- {
- c_Shooting, // Four different "modes"
- c_Goto,
- c_Ramming,
- c_None
- };
- virtual void SetState(State sNew) // Call this all the time, and only use it if the state changed
- {
- if (sNew == sCurrent)
- return;
- sCurrent = sNew;
-
- switch (sNew)
- {
- case c_Shooting:
- m_pDrone->Verbose("I'm in range, and opening fire on %s", GetModelName(m_pTarget));
- break;
- case c_Goto:
- m_pDrone->Verbose("%s is out of range, I'm going after it", GetModelName(m_pTarget));
- break;
- case c_Ramming:
- m_pDrone->Verbose("I don't have any weapons mounted, I'm trying to RAM %s", GetModelName(m_pTarget));
- break;
- }
- };
- State sCurrent; // Remember the state
- };
- /*-------------------------------------------------------------------------
- * Class: KillAnythingGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * Look for the closest enemy in the sector, and try to destroy it. If there
- * aren't any enemies, then just hang tight, and dodge.
- */
- class KillAnythingGoal : public Goal
- {
- public:
- KillAnythingGoal(Drone *pDrone) :
- Goal(pDrone, c_ctDestroy)
- {};
- virtual void Update(Time now, float dt);
- virtual void Status(void)
- {
- Report("Looking for enemies");
- };
- };
- /*-------------------------------------------------------------------------
- * Class: SameSectorDestroyGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * Same as the DestroyGoal, except we don't actually leave the sector trying
- * to kill this guy.
- */
- class SameSectorDestroyGoal : public DestroyGoal
- {
- public:
- SameSectorDestroyGoal(Drone* pDrone, ImodelIGC* pTarget) :
- DestroyGoal(pDrone, pTarget)
- {};
- virtual bool Done(void) // End if our clusters are not the same
- {
- return (DestroyGoal::Done() || m_pShip->GetCluster() != m_pTarget->GetCluster());
- };
- virtual void DoneEvent(void) // Could be that we killed him, or he might have left the sector
- {
- if (DestroyGoal::Done())
- DestroyGoal::DoneEvent();
- else
- m_pDrone->Verbose("%s has left the sector", GetModelName(m_pTarget));
- };
- };
- /*-------------------------------------------------------------------------
- * Class: DisableGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * Same as DestroyGoal, except we stop once we have taken out the target's shields
- */
- class DisableGoal : public DestroyGoal
- {
- public:
- DisableGoal (Drone* pDrone, ImodelIGC* pTarget) :
- DestroyGoal(pDrone, pTarget)
- {};
- virtual bool Done(void) // Check if the shields have been destroyed
- {
- switch (m_pTarget->GetObjectType()) // Different ways to get the shields
- {
- case OT_ship:
- {
- IshieldIGC* shield = (IshieldIGC*) ((IshipIGC*)m_pTarget.operator->())->GetMountedPart(ET_Shield, 0);
- return ((shield == NULL) || (shield->GetFraction() < 0.0f));
- }
- case OT_station:
- {
- IstationIGC* pTargetStation = (IstationIGC*) m_pTarget.operator->();
- return ( pTargetStation->GetShieldFraction() < 0.0f);
- }
- default:
- return true;
- }
- };
- virtual void Status(void)
- {
- Report("Attempting to disable %s", GetModelName(m_pTarget));
- };
- virtual void DoneEvent(void) // Could have died, but hopefully we disabled it
- {
- if (OBJECT_IS_BAD(m_pTarget))
- m_pDrone->Verbose("%s was destroyed while I was attempting to disable it", GetModelName(m_pTarget));
- else
- m_pDrone->Verbose("%s is disabled", GetModelName(m_pTarget));
- };
- };
- /*-------------------------------------------------------------------------
- * Class: DefendingDestroyGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * Try to destroy this guy, but end if you get too far from your defend target,
- * or if there are better targets for you to try to get.
- */
- class DefendingDestroyGoal : public DestroyGoal {
- public:
- DefendingDestroyGoal (Drone* pDrone, ImodelIGC* pTarget, ImodelIGC* pDefendee, float range) :
- DestroyGoal(pDrone,pTarget), m_pDefendee(pDefendee), fRangeSquared(range * range)
- {};
- virtual bool Done(void)
- {
- if (DestroyGoal::Done()) // The normal destroy ending conditions still apply
- return true;
- if (!OBJECT_IS_BAD(m_pDefendee))
- { // If my defendee dies, I probably want to go ahead
- // and kill the guy
- // Otherwise, make sure I'm not too far from home
- Vector vFromHome = m_pShip->GetPosition() - m_pDefendee->GetPosition();
- return (vFromHome.LengthSquared() > fRangeSquared);
- }
- // todo: add a check for other possible (more worthy targets here)
- return false;
- };
- virtual void DoneEvent(void)
- {
- if (OBJECT_IS_BAD(m_pDefendee))
- m_pDrone->Verbose("I have failed");
- else
- m_pDrone->Verbose("%s is no longer a threat to %s", GetModelName(m_pTarget), GetModelName(m_pDefendee));
- };
- protected:
- const TRef<ImodelIGC> m_pDefendee; // Need to remember who I am defending
- const float fRangeSquared; // How far can I get from him? (only compute the square once)
- };
- /*-------------------------------------------------------------------------
- * Class: PatrolGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * Fly back and forth from the starting position and the target, attacking
- * any enemies that I find on the way
- */
- class PatrolGoal : public TargetedGoal
- {
- public:
- PatrolGoal(Drone* pDrone, ImodelIGC* pTarget, Vector vSweetSpot) :
- TargetedGoal(pDrone, pTarget, c_ctPatrol),
- m_vFavoriteSpot(vSweetSpot),
- m_bToSecondTarget(false)
- {};
- PatrolGoal(Drone* pDrone, ImodelIGC* pTarget) :
- TargetedGoal(pDrone, pTarget, c_ctPatrol),
- m_vFavoriteSpot(pDrone->GetShip()->GetPosition()),
- m_bToSecondTarget(false)
- {};
-
- virtual void Update(Time now, float dt);
- virtual void Status(void)
- {
- Report("I'm patrolling");
- };
- protected:
- Vector m_vFavoriteSpot; // This is the starting point (one of two targets), the other target is m_pTarget
- bool m_bToSecondTarget; // Remember which way I am going right now
- };
- /*-------------------------------------------------------------------------
- * Class: PickupGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * Go pickup this target. Duh. We know that we are done because that object would
- * not exist any more.
- */
- class PickupGoal : public TargetedGoal
- {
- public:
- PickupGoal (Drone* pDrone, ImodelIGC* pTarget) :
- TargetedGoal(pDrone,pTarget, c_ctPickup)
- {};
- virtual void Update(Time now, float dt);
- virtual void DoneEvent(void)
- {
- m_pDrone->Verbose("Got it");
- };
- virtual void Status(void)
- {
- Report("Attempting to pick up %s", GetModelName(m_pTarget));
- };
- };
- /*-------------------------------------------------------------------------
- * Class: RepairGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * Get to some station to repair myself. Goal satisfied when my hull is
- * at full strength. This goal goes with the instincts.
- */
- class RepairGoal : public NewGotoGoal
- {
- public:
- RepairGoal (Drone* pDrone, ImodelIGC* pStation) :
- NewGotoGoal(pDrone,
- pStation,
- Waypoint::c_oEnter, 0.0f, c_ctRepair)
- {};
- virtual void Update(Time now, float dt);
- virtual void Status(void)
- {
- Report("Heading to %s to repair myself", GetModelName(m_pTarget));
- };
- virtual bool Done(void) // My hull has all of it's hitpoints.
- {
- return (m_pShip->GetFraction() >= 1.0f) &&
- (GetAmmoState(m_pShip) != c_asEmpty);
- };
- virtual void DoneEvent(void)
- {
- m_pDrone->Verbose("All better");
- };
- };
- /*-------------------------------------------------------------------------
- * Class: MaybeRepairGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * Repair, but end if there are any enemies in the sector. Repairing just
- * seems like a good thing to do when nobody is around. Right now, this just
- * gets called from KillAnythingGoal.
- */
- class MaybeRepairGoal : public RepairGoal
- {
- public:
- MaybeRepairGoal(Drone *pDrone, IstationIGC* pstation) :
- RepairGoal(pDrone, pstation)
- {};
- virtual bool Done(void) // If we can find any enemy ships, then we're done
- {
- return (RepairGoal::Done() || FindTarget(m_pShip,
- c_ttEnemy | c_ttShip));
- };
- };
- /*-------------------------------------------------------------------------
- * Class: CaptureGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * Make the target station have the same side as you. When it is an enemy
- * station, that means disabling it, and then docking to claim it.
- */
- class CaptureGoal : public NewGotoGoal
- {
- public:
- CaptureGoal (Drone *pDrone, ImodelIGC* pStation) :
- NewGotoGoal(pDrone, pStation)
- {};
- virtual void Update(Time now, float dt);
- virtual void Status(void)
- {
- Report("Attempting to capture %s", GetModelName(m_pTarget));
- };
- virtual bool Done(void) // Done if the station dies, or if it is on our side.
- {
- return (TargetedGoal::Done() || m_pTarget->GetSide() == m_pShip->GetSide());
- };
- virtual void DoneEvent(void)
- {
- if (TargetedGoal::Done())
- TargetedGoal::DoneEvent();
- else
- m_pDrone->Verbose("%s is on our side", GetModelName(m_pTarget));
- };
- };
- /*-------------------------------------------------------------------------
- * Class: DefendGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * If the target is static, then I'll orbit it. Dynamic objects, I just follow.
- * If any enemies come too close to my defendee, then I try to destroy them.
- */
- class DefendGoal : public TargetedGoal
- {
- public:
- DefendGoal (Drone* pDrone, ImodelIGC* pTarget) :
- TargetedGoal(pDrone,pTarget, c_ctDefend),
- fDone(false)
- {
- if (OBJECT_IS_BAD(m_pTarget))
- fDone = true;
- };
- virtual void Update(Time now, float dt);
- virtual bool Done(void)
- {
- if (fDone) // special message if initial target is not valid
- {
- m_pDrone->Verbose("Defend target is not valid.");
- return true;
- }
- if (OBJECT_IS_BAD(m_pTarget)) // if we were defending something, and it died,
- { // then we could try to defend other stations in our sector
- m_pTarget = FindTarget(m_pShip,
- c_ttFriendly | c_ttStation | c_ttNearest);
- if (!m_pTarget)
- {
- return true;
- }
- m_pDrone->Verbose("I have failed, now defending %s", GetModelName(m_pTarget));
- }
- return false;
- };
- virtual void Status(void)
- {
- Report("Defending %s", GetModelName(m_pTarget));
- };
- private:
- bool fDone; // in case of bad initial targets
- };
- /*-------------------------------------------------------------------------
- * Class: ScoutGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * If we are given a target, then start spiraling out from there. If not, spiral
- * around 0,0,0. Spiral out and then back in (radii based on Inner and Outer Limit vars)
- * Report any enemies in scan range (report each on once). Run away from enemies.
- */
- class ScoutGoal : public TargetedGoal
- {
- public:
- ScoutGoal (Drone* pDrone, ImodelIGC* pTarget) :
- TargetedGoal(pDrone,pTarget, c_ctScout),
- m_vmReportedEnemies(0,0),
- flRadIncreasePerCycle(2.0f),
- sCurrent(c_None),
- c_flOuterLimit(5000.0f),
- c_flInnerLimit(100.0f),
- radius(100.0f)
- {
- if (!OBJECT_IS_BAD(pTarget))
- flRadIncreasePerCycle = 0.0f;
- };
- ~ScoutGoal() // Clear our reported enemies memory
- {
- for (int i = m_vmReportedEnemies.GetCount(); i > 0; i--)
- {
- m_vmReportedEnemies[i-1]->Release();
- }
- }
- virtual void Update(Time now, float dt);
- virtual bool Done(void) // Never stop, unless told to
- {
- return false;
- };
-
- virtual void Status(void)
- {
- if (m_pTarget)
- Report("I'm scouting around %s", GetModelName(m_pTarget));
- else
- Report("I'm scouting %s", m_pShip->GetCluster()->GetName());
- State sOld = sCurrent; // print out state message, too
- SetState(c_None);
- SetState(sOld);
- };
- protected:
- bool Announce(IshipIGC* pObject) // Announce a ship. If we already announced it, then just return
- {
- // check to see if we have already reported it
- if (m_vmReportedEnemies.Find(pObject) != -1)
- return false;
- // if not, announce it
- Report("Reporting: I found %s in %s", pObject->GetName(), m_pShip->GetCluster()->GetName());
- // add to the list of things we have reported
- pObject->AddRef();
- m_vmReportedEnemies.PushEnd(pObject);
- return true;
- };
- private:
- float radius; // Current orbital radius
- TVector<IshipIGC*, DefaultEquals> m_vmReportedEnemies; // Reported enemy list
- float flRadIncreasePerCycle; // Amount that radius changes per cycle
- const float c_flOuterLimit; // Outer radius size
- const float c_flInnerLimit; // Inner radius size
- enum State // Three two states
- {
- c_Orbitting,
- c_Running,
- c_None
- };
- virtual void SetState(State sNew)
- {
- if (sNew == sCurrent)
- return;
- sCurrent = sNew;
-
- switch (sNew)
- {
- case c_Orbitting:
- if (m_pTarget)
- m_pDrone->Verbose("I'm orbitting %s, currently with radius %d", GetModelName(m_pTarget), (int) radius);
- else
- m_pDrone->Verbose("I'm scouting %s", m_pShip->GetCluster()->GetName());
- break;
- case c_Running:
- m_pDrone->Verbose("I'm attempting to stay away from enemy ships");
- break;
- }
- };
- State sCurrent; // Current state
- };
- /*-------------------------------------------------------------------------
- * Class: DisappearGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * Some of the special characters want to go through an aleph and never come out the
- * other side. This is that disappearing trick.
- * Notes:
- * Rob thinks that it is really bad and incredibly annoying to be chasing a guy,
- * almost killing him, into an aleph. Then when you follow him through, he's not
- * on the other side. I think that is cool, but he hates it. He was thinking that
- * maybe we could only make them "disappear" if they are not being targetted at all.
- */
- class DisappearGoal : public GotoGoal
- {
- public:
- DisappearGoal(Drone* pDrone) : // Find the closest aleph
- GotoGoal(pDrone, FindTarget(pDrone->GetShip(), c_ttNeutral | c_ttWarp | c_ttNearest), 0.0f)
- {
- pDrone->Disappear(); // Set flag in the drone class
- if (!m_pTarget)
- pDrone->Die(); // If I couldn't find an aleph, then just self destruct
- };
- virtual void Status(void)
- {
- if (m_pDrone->GetDroneType() == c_dtBountyHunter)
- {
- BountyHunter* pBounty;
- CastTo(pBounty, m_pDrone);
- // Bounty hunter is ONLY doing this if his mission is accomplished. He repairs at base instead of running away
- Report("Mission Accomplished. %s is no more", GetModelName(pBounty->m_pTarget));
- }
- else // Right now this is just a pirate
- {
- if (m_pShip->GetFraction() <= (1.0f - m_pDrone->GetBravery())) // Either my leader chickened out, or I did
- {
- Report("Pirate guild retreating");
- }
- else // There's no more miners to kill
- {
- Report("Arggh..Jimlad, There's no bounty to be had, you scurvy nave.");
- }
- }
- };
- };
- /*-------------------------------------------------------------------------
- * Class: MimicGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * This is only for the pirates right now. Basically, it is a hack on the
- * normal drone structure. The drone's goal is always to mimic, but the
- * mimic goal keeps a goal of it's own, and calls that update every time.
- * Basically, he follows the target when the target is moving, and attacks
- * what his "leader" or target is attacking, etc.
- */
- class MimicGoal: public TargetedGoal
- {
- public:
- MimicGoal(Drone *pDrone, Drone* pTarget) :
- TargetedGoal(pDrone, pTarget->GetShip(), c_ctMimic),
- m_pdTarget(pTarget),
- m_pGoal(NULL)
- {};
- virtual void Update(Time now, float dt);
-
- virtual void Status(void)
- {
- Report("Following %s, he's our leader", GetModelName(m_pTarget));
- };
- virtual void DoneEvent(void)
- {
- m_pDrone->Verbose("%s is gone, time for a new leader", GetModelName(m_pTarget));
- };
- protected:
- void SetGoal(CommandType ctype, ImodelIGC* pTarget)
- {
- if (m_pGoal && m_pGoal->GetType() == ctype && m_pGoal->GetTarget() == pTarget) // We're already doing it, done
- return;
- if (ctype == c_ctNoCommand || ctype == c_ctMimic) // Don't want to mimic a mimic (that would be bad)
- return;
- if (m_pGoal) // It's new, so clear the old goal
- {
- delete m_pGoal;
- m_pGoal = NULL;
- }
- if (ctype != c_ctDestroy) // Follow him, unless he is killing something
- {
- ctype = c_ctFollow;
- pTarget = m_pTarget;
- }
- m_pDrone->SetGoal(ctype, pTarget); // Play the goal games
- m_pGoal = m_pDrone->GetGoal();
- m_pDrone->m_goal = NULL;
- m_pDrone->RestoreGoal();
- };
-
- Drone * m_pdTarget; // The drone that you are mimicing
- Goal * m_pGoal; // The goal you are running to mimic
- };
- /*-------------------------------------------------------------------------
- * Class: FaceGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * We just want to turn to face our target. Meant primarily for automated
- * client frame rate testing.
- */
- class FaceGoal : public TargetedGoal
- {
- public:
- FaceGoal(Drone* pDrone, ImodelIGC* pTarget) :
- TargetedGoal(pDrone, pTarget, c_ctFace)
- {};
- virtual void Update(Time now, float dt);
- virtual bool Done(void) // Can't face something in a different cluster
- {
- return (!m_pTarget || m_pTarget->GetCluster() != m_pShip->GetCluster());
- };
- virtual void Status(void)
- {
- Report("Facing %s", GetModelName(m_pTarget));
- };
- };
- /*-------------------------------------------------------------------------
- * Class: ConstructGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * We just want to turn to face our target. Meant primarily for automated
- * client frame rate testing.
- */
- class ConstructGoal : public TargetedGoal
- {
- public:
- ConstructGoal(Drone* pDrone,
- IstationTypeIGC* pstationtype,
- IasteroidIGC* pasteroid)
- :
- TargetedGoal(pDrone, pasteroid, c_ctConstruct),
- m_pstationtype(pstationtype),
- m_doneF(false)
- {
- };
- virtual void Update(Time now, float dt);
- virtual bool Done(void) // Can't face something in a different cluster
- {
- return m_doneF && !OBJECT_IS_BAD(m_pTarget);
- };
- virtual void DoneEvent(void)
- {
- assert (!OBJECT_IS_BAD(m_pTarget));
- m_pDrone->SendChat(m_pstationtype->GetCompletionSound(), "%s completed.", m_pstationtype->GetName());
- m_pDrone->GetShip()->GetMission()->GetIgcSite()->BuildStation((IasteroidIGC*)((ImodelIGC*)m_pTarget),
- m_pDrone->GetShip()->GetSide(),
- m_pstationtype,
- m_tLastUpdate);
- //Quietly kill the ship (after nuking its parts to prevent treasure from being created)
- {
- PartLinkIGC* plink;
- while (plink = m_pDrone->GetShip()->GetParts()->first()) //Not ==
- plink->data()->Terminate();
- }
- m_pDrone->Die();
- };
- virtual void Status(void)
- {
- Report("Building %s", m_pstationtype->GetName());
- };
- private:
- TRef<IstationTypeIGC> m_pstationtype;
- bool m_doneF;
- };
- /*-------------------------------------------------------------------------
- * Class: TestGoal
- *-------------------------------------------------------------------------
- * Purpose:
- * This was meant to just cycle through all of the goals possible for that drone,
- * but it never got implemented completely. :( Good in theory.
- */
- class TestGoal : public Goal
- {
- public:
- TestGoal(Drone* pDrone) :
- Goal(pDrone, c_ctTest),
- cidCurrent(0)
- {};
- virtual void Update(Time now, float dt);
- virtual void Status(void)
- {
- Report("Testing");
- };
- virtual bool Done(void) // We tested all of the goals
- {
- return (cidCurrent >= m_pShip->GetMission()->GetNcommands());
- };
- virtual void DoneEvent(void)
- {
- m_pDrone->Verbose("Done with test");
- };
- private:
- CommandID cidCurrent; // Which goal are we on right now
- };
- #endif
|