goal.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. #include "pch.h"
  2. /*-------------------------------------------------------------------------
  3. * Function: Goal::Report
  4. *-------------------------------------------------------------------------
  5. * Purpose:
  6. * This is really just a wrapper on DroneSendChat. Pretty simple.
  7. */
  8. void Goal::Report(const char* format, ...)
  9. {
  10. char szChat[256]; // $CRC: sync this with client
  11. va_list vl;
  12. va_start(vl, format);
  13. int cbChat = wvsprintfA(szChat, format, vl);
  14. assert(cbChat < sizeof(szChat));
  15. va_end(vl);
  16. m_pShip->GetMission()->GetIgcSite()->DroneSendChat(m_pShip, szChat, CHAT_TEAM, m_pShip);
  17. }
  18. /*-------------------------------------------------------------------------
  19. * Function: IdleGoal::Update
  20. *-------------------------------------------------------------------------
  21. * Purpose:
  22. * Sit there and dodge.
  23. */
  24. void IdleGoal::Update(Time now, float dt)
  25. {
  26. assert(!OBJECT_IS_BAD(m_pShip));
  27. // Stay still by going to your current location. This lets the drones dodge things (aka projectiles)
  28. // even while they aren't moving.
  29. DoGotoAction(m_pShip, now, NULL, m_pShip->GetPosition(), Vector::GetZero(), 0.0f, dt, m_pDrone->GetMoveSkill());
  30. Goal::Update(now, dt);
  31. }
  32. /*-------------------------------------------------------------------------
  33. * Function: KillAnythingGoal::Update
  34. *-------------------------------------------------------------------------
  35. * Purpose:
  36. * If there are any enemies in the sector, then attack them, but don't leave
  37. * the sector doing it.
  38. */
  39. void KillAnythingGoal::Update(Time now, float dt)
  40. {
  41. assert(!OBJECT_IS_BAD(m_pShip));
  42. // Find the closest enemy ship
  43. ImodelIGC* pAttackTarget = FindTarget(m_pShip,
  44. c_ttEnemy | c_ttNeutral | c_ttShip | c_ttNearest);
  45. if (pAttackTarget) // Now we've decided whether there is anyone to worry about, so attack them.
  46. {
  47. // Use SameSectorDestroy, so that we don't get pulled away
  48. Goal* newGoal = new SameSectorDestroyGoal(m_pDrone, pAttackTarget);
  49. m_pDrone->SetGoal(newGoal);
  50. newGoal->Update(now, dt);
  51. Goal::Update(now,dt);
  52. return;
  53. }
  54. else // There is no-one around. Just dodge, or repair if we are hurt
  55. {
  56. if (m_pShip->GetFraction() < 1.0f) // If I'm hurt, I should go repair...
  57. {
  58. IstationIGC* pstation = (IstationIGC*)(m_pDrone->GetRepairStation());
  59. if (pstation)
  60. {
  61. Goal* newGoal = new MaybeRepairGoal(m_pDrone, pstation);
  62. m_pDrone->SetGoal(newGoal);
  63. newGoal->Update(now, dt);
  64. }
  65. }
  66. else // Otherwise just dodge
  67. DoGotoAction(m_pShip, now, NULL, m_pShip->GetPosition(), Vector::GetZero(), 0.0f, dt, m_pDrone->GetMoveSkill());
  68. }
  69. Goal::Update(now, dt);
  70. }
  71. /*-------------------------------------------------------------------------
  72. * Function: GotoGoal::Update
  73. *-------------------------------------------------------------------------
  74. * Purpose:
  75. * Go to the desired target, and push a stop command when I get there, if
  76. * desired
  77. */
  78. void GotoGoal::Update(Time now, float dt)
  79. {
  80. assert (!OBJECT_IS_BAD(m_pShip) && !OBJECT_IS_BAD(m_pTarget));
  81. if (m_pTarget->GetCluster() != m_pShip->GetCluster()) // Make sure the target is in this sector
  82. {
  83. m_pDrone->SetGoal(new GotoSameSectorGoal(m_pDrone, m_pTarget));
  84. m_pDrone->GetGoal()->Update(now, dt);
  85. Goal::Update(now,dt);
  86. return;
  87. }
  88. if (DoGotoAction(m_pShip, // This handles just about everything else
  89. now,
  90. m_pTarget,
  91. m_pTarget->GetPosition(),
  92. m_pTarget->GetVelocity(),
  93. distFromTarget,
  94. dt,
  95. m_pDrone->GetMoveSkill(),
  96. (m_pTarget->GetObjectType() == OT_warp),
  97. false,
  98. fDodgeBullets))
  99. {
  100. // Then we are there
  101. if (fStopThere && !fGotThere) // make sure I only do this once
  102. m_pDrone->SetGoal(new StayPutGoal(m_pDrone));
  103. fGotThere = true;
  104. }
  105. Goal::Update(now, dt);
  106. }
  107. /*-------------------------------------------------------------------------
  108. * Function: FollowGoal::Update
  109. *-------------------------------------------------------------------------
  110. * Purpose:
  111. * Go just behind the target... Farther behind if the target is moving.
  112. * This is a simple way of "flying in formation"
  113. */
  114. void FollowGoal::Update(Time now, float dt)
  115. {
  116. assert (!OBJECT_IS_BAD(m_pShip) && !OBJECT_IS_BAD(m_pTarget));
  117. if (m_pTarget->GetCluster() != m_pShip->GetCluster()) // Make sure the target is in this sector
  118. {
  119. m_pDrone->SetGoal(new GotoSameSectorGoal(m_pDrone, m_pTarget));
  120. m_pDrone->GetGoal()->Update(now, dt);
  121. Goal::Update(now, dt);
  122. return;
  123. }
  124. Vector pos = m_pTarget->GetPosition(); // Base everything off the pos and vel of the target
  125. Vector vel = m_pTarget->GetVelocity();
  126. pos -= m_pTarget->GetOrientation().GetForward() * (m_pTarget->GetRadius() + c_fHowCloseFollow); // Fly in formation by flying behind
  127. pos -= vel / 10.0f; // Farther behind based on speed
  128. DoGotoAction(m_pShip, now, m_pTarget, pos, vel, m_pTarget->GetRadius(), dt, m_pDrone->GetMoveSkill());
  129. Goal::Update(now, dt);
  130. };
  131. /*-------------------------------------------------------------------------
  132. * Function: DestroyGoal::Update
  133. *-------------------------------------------------------------------------
  134. * Purpose:
  135. * To destroy the target. If we don't have any weapons mounted, then try
  136. * to ram the target. If we do, then the current approach is to get into a
  137. * good position, and then just use the turret attack code.
  138. * Note:
  139. * I was hoping to add 5 or 6 different attack styles here, and then have the
  140. * drone choose between them based on the situation. I didn't get to it. :(
  141. */
  142. void DestroyGoal::Update(Time now, float dt) {
  143. assert (!OBJECT_IS_BAD(m_pShip) && !OBJECT_IS_BAD(m_pTarget));
  144. if (m_pTarget->GetCluster() != m_pShip->GetCluster()) // Make sure the target is in this sector
  145. {
  146. m_pDrone->SetGoal(new GotoSameSectorGoal(m_pDrone, m_pTarget));
  147. m_pDrone->GetGoal()->Update(now, dt);
  148. Goal::Update(now, dt);
  149. return;
  150. }
  151. IweaponIGC* w = (IweaponIGC*)m_pShip->GetMountedPart(ET_Weapon, 0); // Get the mounted weapon
  152. if (w) {
  153. IprojectileTypeIGC* pProjectile = w->GetProjectileType();
  154. float fRange = pProjectile->GetSpeed() * pProjectile->GetLifespan(); // Weapon range
  155. Vector vToTarg = m_pTarget->GetPosition() - m_pShip->GetPosition();
  156. // If we are within weapon range, and we aren't going to hit any friendlies then do turret attack
  157. if (fRange*fRange > vToTarg.LengthSquared())
  158. {
  159. if (StationaryAttackTarget(m_pShip, now, m_pTarget, dt, m_pDrone->GetShootSkill(), m_pDrone->GetMoveSkill(), true)) {
  160. SetState(c_Shooting);
  161. Goal::Update(now, dt);
  162. return;
  163. }
  164. }
  165. else
  166. {
  167. SetState(c_Goto);
  168. /*
  169. m_pDrone->SetGoal(new GotoGoal(m_pDrone, m_pTarget, fRange, false, false));
  170. m_pDrone->GetGoal()->Update(now, dt);
  171. Goal::Update(now, dt);
  172. return;
  173. */
  174. // This is good in theory, but to pull it off, the ending condition of the Goto has to be the same as the fRange check above.
  175. // I fixed this case for the turretAttack relocation, but didn't get around to testing that fix here.
  176. // The advantage of doing this is that the mimic command will cause pirates and the like to fly in formation a little more often.
  177. }
  178. }
  179. else
  180. SetState(c_Ramming);
  181. // Otherwise move towards target ( and ram it )
  182. DoGotoAction(m_pShip, now, m_pTarget, m_pTarget->GetPosition(), Vector::GetZero(), m_pTarget->GetRadius() + m_pShip->GetRadius() - c_fHowClose, dt, m_pDrone->GetMoveSkill(), false, false, false);
  183. Goal::Update(now, dt);
  184. }
  185. /*-------------------------------------------------------------------------
  186. * Function: PatrolGoal::Update
  187. *-------------------------------------------------------------------------
  188. * Purpose:
  189. * Find the closest enemy. If there aren't any interesting enemies, then
  190. * continue going to either the target or back to the starting position.
  191. */
  192. void PatrolGoal::Update(Time now, float dt) {
  193. assert (!OBJECT_IS_BAD(m_pShip) && !OBJECT_IS_BAD(m_pTarget));
  194. // Find the closest enemy
  195. ImodelIGC* pAttackTarget = FindTarget(m_pShip,
  196. c_ttEnemy | c_ttNeutral | c_ttShip | c_ttNearest);
  197. // If he is close enough, then attack him, otherwise continue patrolling
  198. if (pAttackTarget)
  199. {
  200. // Close enough = 1500.0??
  201. Vector vToAttackTarg = pAttackTarget->GetPosition() - m_pShip->GetPosition();
  202. // 1500 ^2 = 2250000
  203. if (vToAttackTarg.LengthSquared() < 2250000.0f)
  204. {
  205. m_pDrone->SetGoal(c_ctDestroy, pAttackTarget);
  206. m_pDrone->GetGoal()->Update(now, dt);
  207. Goal::Update(now, dt);
  208. return;
  209. }
  210. }
  211. if (m_bToSecondTarget)
  212. {
  213. if (DoGotoAction(m_pShip, now, NULL, m_vFavoriteSpot, Vector::GetZero(), 0.0f, dt, m_pDrone->GetMoveSkill()))
  214. {
  215. // then we're there...
  216. m_bToSecondTarget = false;
  217. m_pDrone->Verbose("I got back to where I started. Going back to %s", GetModelName(m_pTarget));
  218. }
  219. }
  220. else
  221. {
  222. if (DoGotoAction(m_pShip, now, m_pTarget, m_pTarget->GetPosition(), m_pTarget->GetVelocity(), c_fHowClose + m_pTarget->GetRadius() + m_pShip->GetRadius(), dt, m_pDrone->GetMoveSkill()))
  223. {
  224. // then we're there...
  225. m_bToSecondTarget = true;
  226. m_pDrone->Verbose("I got to %s, going back to where I started", GetModelName(m_pTarget));
  227. }
  228. }
  229. Goal::Update(now, dt);
  230. }
  231. /*-------------------------------------------------------------------------
  232. * Function: PickupGoal::Update
  233. *-------------------------------------------------------------------------
  234. * Purpose:
  235. * Just move to the center of the object. The collision should pick it up
  236. */
  237. void PickupGoal::Update(Time now, float dt) {
  238. assert (!OBJECT_IS_BAD(m_pShip) && !OBJECT_IS_BAD(m_pTarget));
  239. if (m_pTarget->GetCluster() != m_pShip->GetCluster())
  240. {
  241. m_pDrone->SetGoal(new GotoSameSectorGoal(m_pDrone, m_pTarget));
  242. m_pDrone->GetGoal()->Update(now, dt);
  243. Goal::Update(now, dt);
  244. return;
  245. }
  246. if (DoGotoAction(m_pShip, now, m_pTarget, m_pTarget->GetPosition(), Vector::GetZero(), 0.0f, dt, m_pDrone->GetMoveSkill()))
  247. {
  248. // Got there, now what do I do???
  249. }
  250. Goal::Update(now, dt);
  251. }
  252. /*-------------------------------------------------------------------------
  253. * Function: DefendGoal::Update
  254. *-------------------------------------------------------------------------
  255. * Purpose:
  256. * If there are any enemies that could endanger the defendee, then attack them.
  257. * If not, then just orbit or follow the target (static or dynamic).
  258. */
  259. void DefendGoal::Update(Time now, float dt) {
  260. assert (!OBJECT_IS_BAD(m_pShip) && !OBJECT_IS_BAD(m_pTarget));
  261. if (m_pTarget->GetCluster() != m_pShip->GetCluster()) // Make sure the target is in the same cluster
  262. {
  263. m_pDrone->SetGoal(new GotoSameSectorGoal(m_pDrone, m_pTarget));
  264. m_pDrone->GetGoal()->Update(now, dt);
  265. Goal::Update(now, dt);
  266. return;
  267. }
  268. // If we are here, then we aren't currently targeting anyone, check
  269. // for the closest enemy and decided if they are close enough to worry about
  270. ImodelIGC* pAttackTarget = FindTarget(m_pShip,
  271. c_ttEnemy | c_ttNeutral | c_ttShip | c_ttNearest,
  272. NULL, NULL,
  273. &(m_pTarget->GetPosition()));
  274. // "Close Enough" == ScanRange / 2
  275. float distToWorryAbout = m_pShip->GetHullType()->GetScannerRange() / 2;
  276. if (pAttackTarget) // Is the closest enemy within that range?
  277. {
  278. Vector dist = pAttackTarget->GetPosition() - m_pTarget->GetPosition();
  279. if (dist.LengthSquared() > (distToWorryAbout * distToWorryAbout))
  280. pAttackTarget = NULL; // too far away
  281. }
  282. // Now we've decided whether there is anyone to worry about, so attack them.
  283. if (pAttackTarget)
  284. {
  285. Goal* newGoal = new DefendingDestroyGoal(m_pDrone, pAttackTarget, m_pTarget, distToWorryAbout);
  286. m_pDrone->SetGoal(newGoal);
  287. m_pDrone->GetGoal()->Update(now, dt);
  288. Goal::Update(now, dt);
  289. return;
  290. }
  291. // Otherwise try to orbit/follow the defendee
  292. else
  293. {
  294. if (m_pTarget->GetAttributes() & c_mtStatic)
  295. {
  296. DoGotoAction(m_pShip,
  297. now,
  298. m_pTarget,
  299. m_pTarget->GetPosition(),
  300. Vector::GetZero(), // use top orbit speed
  301. (m_pTarget->GetRadius() + m_pShip->GetRadius()) * 2.0f, // as good a radius as any??
  302. dt,
  303. m_pDrone->GetMoveSkill(),
  304. false,
  305. true); // orbit
  306. }
  307. else
  308. {
  309. DoGotoAction(m_pShip,
  310. now,
  311. m_pTarget,
  312. m_pTarget->GetPosition(),
  313. m_pTarget->GetVelocity(),
  314. c_fHowClose + m_pTarget->GetRadius() + m_pShip->GetRadius(),
  315. dt,
  316. m_pDrone->GetMoveSkill());
  317. }
  318. }
  319. Goal::Update(now, dt);
  320. }
  321. /*-------------------------------------------------------------------------
  322. * Function: RepairGoal::Update
  323. *-------------------------------------------------------------------------
  324. * Purpose:
  325. * Find a station and get to it, so that my hull will be repaired.
  326. * Run away from enemies.
  327. */
  328. void RepairGoal::Update(Time now, float dt) {
  329. assert(m_pShip);
  330. if (OBJECT_IS_BAD(m_pTarget))
  331. {
  332. m_pTarget = m_pDrone->GetRepairStation();
  333. // todo: remove this line when I am completely confident in FindBestStation and FindBestTarget:
  334. // CURTC: Or what happens if they can't find a station to repair at?
  335. if (m_pTarget)
  336. SetGotoPlan(Waypoint::c_oEnter, m_pTarget, c_fHowClose);
  337. }
  338. NewGotoGoal::Update(now, dt);
  339. }
  340. /*-------------------------------------------------------------------------
  341. * Function: CaptureGoal::Update
  342. *-------------------------------------------------------------------------
  343. * Purpose:
  344. * Disable the station's shields, and then dock with it to take it over
  345. */
  346. void CaptureGoal::Update(Time now, float dt) {
  347. assert(!OBJECT_IS_BAD(m_pShip) && !OBJECT_IS_BAD(m_pTarget));
  348. if (m_pTarget->GetCluster() != m_pShip->GetCluster()) // Make sure that we're in the right cluster
  349. {
  350. m_pDrone->SetGoal(new GotoSameSectorGoal(m_pDrone, m_pTarget));
  351. m_pDrone->GetGoal()->Update(now, dt);
  352. Goal::Update(now, dt);
  353. return;
  354. }
  355. IstationIGC* pStation;
  356. CastTo(pStation, m_pTarget);
  357. // Check the shields
  358. if ((pStation->GetSide() != m_pShip->GetSide()) &&
  359. (pStation->GetShieldFraction() >= 0.0f))
  360. {
  361. m_pDrone->SetGoal(new DisableGoal(m_pDrone, m_pTarget));
  362. m_pDrone->GetGoal()->Update(now, dt);
  363. Goal::Update(now, dt); // skip NewGotoGoal::Update
  364. return;
  365. }
  366. //DoGotoAction(m_pShip, now, m_pTarget, m_pTarget->GetPosition(), Vector::GetZero(), 0.0f, dt, m_pDrone->GetMoveSkill(), false, false, false);
  367. NewGotoGoal::Update(now, dt);
  368. }
  369. /*-------------------------------------------------------------------------
  370. * Function: ScoutGoal::Update
  371. *-------------------------------------------------------------------------
  372. * Purpose:
  373. * If we have a target, then do a spiral around it (by orbitting with an
  374. * incrementally larger radius). If not, spiral around the center of the cluster (0,0,0).
  375. * Announce all enemies that are in our scan range. Run away from enemies
  376. */
  377. void ScoutGoal::Update(Time now, float dt)
  378. {
  379. assert (!OBJECT_IS_BAD(m_pShip));
  380. if (OBJECT_IS_BAD(m_pTarget))
  381. m_pTarget = NULL;
  382. if (m_pTarget && m_pTarget->GetCluster() != m_pShip->GetCluster()) // Make sure that we are in the right cluster
  383. {
  384. m_pDrone->SetGoal(new GotoSameSectorGoal(m_pDrone, m_pTarget));
  385. m_pDrone->GetGoal()->Update(now, dt);
  386. Goal::Update(now, dt);
  387. return;
  388. }
  389. const ShipListIGC* ships = m_pShip->GetCluster()->GetShips();
  390. ShipLinkIGC* sLink = ships->first();
  391. IsideIGC* mySide = m_pShip->GetSide();
  392. Vector myPosition = m_pShip->GetPosition();
  393. float myRadius = m_pShip->GetRadius();
  394. IshipIGC * pEnemy = NULL;
  395. float flClosest = 0.0f;
  396. // Traverse the ship list
  397. while (sLink != NULL)
  398. {
  399. IshipIGC* pship = sLink->data();
  400. // Put in side visibility stuff here
  401. if (pship->GetSide() != mySide)
  402. {
  403. Announce(pship); // Announce everyone.
  404. IweaponIGC* w = (IweaponIGC*)pship->GetMountedPart(ET_Weapon, 0); // Would we really know this? Is this unfair?
  405. if (w) // If we are in weapons range, then RUN.
  406. {
  407. IprojectileTypeIGC* pProjectile = w->GetProjectileType();
  408. float fRange = pProjectile->GetSpeed() * w->GetLifespan();
  409. float distFromShots = (pship->GetPosition() - myPosition).Length() - fRange - myRadius;
  410. if (distFromShots < flClosest)
  411. {
  412. flClosest = distFromShots;
  413. pEnemy = pship;
  414. }
  415. }
  416. }
  417. sLink = sLink->next();
  418. };
  419. // If we found an enemy that we are in it's weapon range, move in the opposite direction
  420. if (pEnemy)
  421. {
  422. SetState(c_Running);
  423. DoGotoAction(m_pShip,
  424. now,
  425. NULL,
  426. (2* myPosition) - pEnemy->GetPosition(), // opposite direction of enemy
  427. Vector::GetZero(),
  428. 0.0f,
  429. dt,
  430. m_pDrone->GetMoveSkill(),
  431. false, // don't run through alephs
  432. false, // don't orbit
  433. false); // don't dodge bullets (or we'll never get away!)
  434. Goal::Update(now, dt);
  435. return;
  436. }
  437. // If no enemies, then orbit and increment radius
  438. SetState(c_Orbitting);
  439. if (DoGotoAction(m_pShip,
  440. now,
  441. m_pTarget,
  442. (m_pTarget) ? m_pTarget->GetPosition() : Vector::GetZero(),
  443. Vector::GetZero(),
  444. radius,
  445. dt,
  446. m_pDrone->GetMoveSkill(),
  447. false,
  448. true))
  449. {
  450. radius += flRadIncreasePerCycle; // only increment if we are close to the desired radius.
  451. if (radius > c_flOuterLimit || radius < c_flInnerLimit)
  452. flRadIncreasePerCycle = -flRadIncreasePerCycle;
  453. }
  454. Goal::Update(now, dt);
  455. }
  456. /*-------------------------------------------------------------------------
  457. * Function: MimicGoal::Update
  458. *-------------------------------------------------------------------------
  459. * Purpose:
  460. * Keep a local goal that is always based on the goal of the guy we are
  461. * mimicing. If he is attacking, or disappearing, then do that. Otherwise,
  462. * just follow the guy (which means try to fly in formation).
  463. */
  464. void MimicGoal::Update(Time now, float dt)
  465. {
  466. assert(!OBJECT_IS_BAD(m_pShip) && !OBJECT_IS_BAD(m_pTarget));
  467. if (m_pdTarget->GetDisappear())
  468. m_pDrone->Disappear();
  469. Goal * toMimic = m_pdTarget->GetGoal();
  470. SetGoal(toMimic->GetType(), toMimic->GetTarget());
  471. if (m_pGoal && !m_pGoal->Done())
  472. m_pGoal->Update(now, dt);
  473. Goal::Update(now, dt);
  474. }
  475. /*-------------------------------------------------------------------------
  476. * Class: FaceGoal
  477. *-------------------------------------------------------------------------
  478. * Purpose:
  479. * We just want to turn to face our target. Meant primarily for automated
  480. * client frame rate testing.
  481. */
  482. void FaceGoal::Update(Time now, float dt)
  483. {
  484. assert(!OBJECT_IS_BAD(m_pShip) && !OBJECT_IS_BAD(m_pTarget));
  485. Vector path = m_pTarget->GetPosition() - m_pShip->GetPosition();
  486. ControlData controls;
  487. controls.Reset();
  488. turnToFace(path, dt, m_pShip, &controls, m_pDrone->GetMoveSkill());
  489. m_pShip->SetStateBits(now, weaponsMaskIGC | buttonsMaskIGC, 0);
  490. m_pShip->SetControls(controls);
  491. Goal::Update(now, dt);
  492. }
  493. /*-------------------------------------------------------------------------
  494. * Function: TestGoal::Update
  495. *-------------------------------------------------------------------------
  496. * Purpose:
  497. * This never really got used, but it seemed cool. Run through all of the
  498. * accepted commands for this drone, and go until they're done. The switch
  499. * statement was to set up appropriate situations for each command.
  500. * Notes:
  501. * The problem is that some of the goals are never-ending. Have to add a
  502. * time-out for those.
  503. */
  504. void TestGoal::Update(Time now, float dt)
  505. {
  506. while (!m_pShip->AcceptsCommandF(cidCurrent))
  507. cidCurrent++;
  508. if (!Done())
  509. {
  510. const CommandData& cmddata = m_pShip->GetMission()->GetCommand(cidCurrent);
  511. if (strlen(cmddata.szImage))
  512. {
  513. ImodelIGC * pTarget = NULL;
  514. switch(cidCurrent) // Set up appropriate targets, etc.
  515. {
  516. case c_ctDestroy:
  517. // Make an enemy target to fire at
  518. break;
  519. }
  520. m_pDrone->Verbose("Now Testing %s", cmddata.szVerb);
  521. m_pDrone->SetGoal((CommandType) cidCurrent, pTarget);
  522. }
  523. }
  524. cidCurrent++;
  525. Goal::Update(now, dt);
  526. }
  527. void ConstructGoal::Update(Time now, float dt)
  528. {
  529. //Do we have a good target?
  530. assert ((m_pTarget == NULL) || (m_pTarget->GetObjectType() == OT_asteroid));
  531. assert (m_pstationtype);
  532. AsteroidAbilityBitMask aabm = m_pstationtype->GetBuildAABM();
  533. IasteroidIGC* pasteroid;
  534. CastTo(pasteroid, m_pTarget);
  535. if (OBJECT_IS_BAD(m_pTarget) || !pasteroid->HasCapability(aabm))
  536. {
  537. m_pTarget = (aabm != 0)
  538. ? FindTarget(m_pShip,
  539. c_ttNeutral | c_ttAsteroid | c_ttNearest,
  540. NULL, NULL, NULL, NULL,
  541. aabm)
  542. : NULL;
  543. if (m_pTarget)
  544. {
  545. m_pDrone->SendChat(droneInTransitSound, "Building %s at %s", m_pstationtype->GetName(), GetModelName(m_pTarget));
  546. }
  547. else
  548. {
  549. //Can't find anything: complain but do nothing else
  550. m_pDrone->SendChat(droneAintGonnaWorkSound, "No place to build %s", m_pstationtype->GetName());
  551. //Pop the goal stack for the drone
  552. m_pDrone->m_goal = NULL;
  553. m_pDrone->DetermineGoal();
  554. Drone* pdrone = m_pDrone;
  555. delete this;
  556. return;
  557. }
  558. }
  559. if (m_pTarget->GetCluster() != m_pShip->GetCluster())
  560. {
  561. m_pDrone->SetGoal(new GotoSameSectorGoal(m_pDrone, m_pTarget));
  562. m_pDrone->GetGoal()->Update(now, dt);
  563. Goal::Update(now, dt);
  564. return;
  565. }
  566. m_doneF = DoGotoAction(m_pShip, now, m_pTarget,
  567. m_pTarget->GetPosition(), Vector::GetZero(),
  568. m_pTarget->GetRadius() + m_pShip->GetRadius(), dt, m_pDrone->GetMoveSkill());
  569. Goal::Update(now, dt);
  570. }