drone.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. #include "pch.h"
  2. /*-------------------------------------------------------------------------
  3. * Function: Drone::Drone
  4. *-------------------------------------------------------------------------
  5. * Purpose:
  6. * Does nothing accept initialize all of the drone variables
  7. */
  8. Drone::Drone(IshipIGC* id, DroneType dt) :
  9. m_pShip(id),
  10. m_goal(NULL),
  11. m_goalMemory(0,0),
  12. bVerbose(false),
  13. dType(dt),
  14. m_fDie(false),
  15. m_fDisappear(false),
  16. m_flShootSkill(0.0f),
  17. m_flMoveSkill(0.0f),
  18. m_flBravery(0.0f),
  19. m_pStation(NULL),
  20. m_index(g_drones.GetIndex())
  21. {}
  22. /*-------------------------------------------------------------------------
  23. * Function: Drone::Update
  24. *-------------------------------------------------------------------------
  25. * Purpose:
  26. * Update the ship controls....
  27. * Start by checking the instincts, then check the current goal. If that goal is
  28. * not done yet, then run that goal. Otherwise try to find a goal for next time
  29. * using DetermineGoal()
  30. */
  31. void Drone::Update(Time now, float dt)
  32. {
  33. if (m_pShip->GetStation()) // undock immediately
  34. {
  35. m_pShip->SetStation(NULL);
  36. }
  37. assert (m_pShip->GetCluster() != NULL);
  38. Instincts(); // Check some things EVERY round
  39. if (m_goal && m_goal->Done())
  40. {
  41. m_goal->DoneEvent(); // Mostly for done messages
  42. delete m_goal;
  43. m_goal = NULL;
  44. }
  45. if (!m_goal)
  46. {
  47. DetermineGoal();
  48. }
  49. if (m_goal)
  50. {
  51. m_goal->Update(now, dt); // The goal is not done, update the controls using that goal
  52. }
  53. else
  54. {
  55. //No goal ... well, do nothing
  56. m_pShip->SetStateM(now, 0);
  57. ControlData cd;
  58. cd.Reset();
  59. m_pShip->SetControls(cd);
  60. }
  61. if (m_fDie == true) // This has to be the last thing in the update cycle
  62. {
  63. //Self-destruct ... but first nuke parts, fuel & ammo
  64. {
  65. PartLinkIGC* ppl;
  66. while (ppl = m_pShip->GetParts()->first()) //intentional assignement
  67. {
  68. ppl->data()->Terminate();
  69. }
  70. }
  71. m_pShip->SetAmmo(0);
  72. m_pShip->SetFuel(0.0f);
  73. m_pShip->GetMission()->GetIgcSite()->KillShipEvent(now, m_pShip, NULL, 0.0f, m_pShip->GetPosition(), Vector::GetZero());
  74. }
  75. }
  76. /*-------------------------------------------------------------------------
  77. * Function: Drone::SetShip
  78. *-------------------------------------------------------------------------
  79. * Purpose:
  80. * If I have to update the ship, I also have to update the goals which save the
  81. * ship seperately
  82. */
  83. void Drone::SetShip(IshipIGC* ship)
  84. {
  85. assert(ship);
  86. m_pShip = ship;
  87. // Kind of a pain, but I have to make sure that the goals are using the correct ship, too
  88. if (m_goal)
  89. m_goal->m_pShip = ship;
  90. for (int i=m_goalMemory.GetCount(); i>0; i--)
  91. {
  92. m_goalMemory[i-1]->m_pShip = ship;
  93. }
  94. }
  95. /*-------------------------------------------------------------------------
  96. * Function: Drone::Message
  97. *-------------------------------------------------------------------------
  98. * Purpose:
  99. * Most commands end up using SetGoal(command), but there are a few exceptions
  100. * to that rule. Catch those exceptions here.
  101. */
  102. bool
  103. Drone::Message(Time now, CommandID cm, ImodelIGC* pmodelObject)
  104. {
  105. if (!m_pShip->AcceptsCommandF(cm)) // Make sure that this drone can do this command
  106. {
  107. SendChat(droneCantDoThatSound, "I can't do that, you must have the wrong drone");
  108. return false;
  109. }
  110. const CommandData& cmdata = m_pShip->GetMission()->GetCommand(cm);
  111. if (pmodelObject) // Make sure that the target is appropriate for that command
  112. {
  113. if (!cmdata.LegalObject(pmodelObject->GetObjectType()))
  114. {
  115. SendChat(droneCantDoThatSound, "I can't do that to %s", GetModelName(pmodelObject));
  116. return false;
  117. }
  118. if (pmodelObject == m_pShip) {
  119. SendChat(droneCantDoThatSound, "I can't do that to myself...");
  120. return false;
  121. }
  122. }
  123. else if (cmdata.otmLegal != 0)
  124. {
  125. SendChat(droneCantDoThatSound, "I can't do that to nothing");
  126. return false;
  127. }
  128. CommandType ct = (CommandType) cm;
  129. if (ct == c_ctNoCommand) // Cut out the junk commands
  130. {
  131. SendChat(droneCantDoThatSound, "I don't understand...");
  132. return false;
  133. }
  134. else if (ct == c_ctStatus) // Get the status
  135. Status();
  136. else if (ct == c_ctHome) // Set the home station
  137. {
  138. if (pmodelObject && pmodelObject->GetObjectType() == OT_station)
  139. SetStation(pmodelObject);
  140. else SendChat(droneCantDoThatSound, "That's not a station!");
  141. }
  142. else if (ct == c_ctVerbose) // Toggle verbose
  143. {
  144. ToggleVerbose();
  145. if (bVerbose)
  146. Status();
  147. }
  148. else if (ct == c_ctSDestruct) // Self Destruct
  149. {
  150. Die();
  151. }
  152. else if (ct == c_ctPop) // Pop a goal
  153. {
  154. if (m_goal)
  155. {
  156. delete m_goal;
  157. m_goal = NULL;
  158. }
  159. DetermineGoal();
  160. }
  161. else // It is a command associated with a goal.
  162. { // Clear the current goals and do this order
  163. ClearGoals();
  164. SetGoal(ct, pmodelObject, true);
  165. }
  166. return true;
  167. }
  168. /*-------------------------------------------------------------------------
  169. * Function: Drone::SendChat
  170. *-------------------------------------------------------------------------
  171. * Purpose:
  172. * A wrapper on the GameSite::DroneSendChat function
  173. */
  174. void
  175. Drone::SendChat(SoundID soundID, const char* format, ...)
  176. {
  177. char szChat[256]; // $CRC: sync this with client
  178. va_list vl;
  179. va_start(vl, format);
  180. int cbChat = wvsprintfA(szChat, format, vl);
  181. assert(cbChat < sizeof(szChat));
  182. va_end(vl);
  183. m_pShip->GetMission()->GetIgcSite()->DroneSendChat(m_pShip, szChat, CHAT_TEAM, m_pShip, soundID);
  184. }
  185. /*-------------------------------------------------------------------------
  186. * Function: Drone::Verbose
  187. *-------------------------------------------------------------------------
  188. * Purpose:
  189. * A wrapper on the m_pShip->GetMission()->GetIgcSite()->DroneSendChat function, but only send the chat
  190. * if verbose mode is on.
  191. */
  192. void Drone::Verbose(const char* format, ...)
  193. {
  194. if (!bVerbose)
  195. return;
  196. char szChat[256]; // $CRC: sync this with client
  197. va_list vl;
  198. va_start(vl, format);
  199. int cbChat = wvsprintfA(szChat, format, vl);
  200. assert(cbChat < sizeof(szChat));
  201. va_end(vl);
  202. m_pShip->GetMission()->GetIgcSite()->DroneSendChat(m_pShip, szChat, CHAT_TEAM, m_pShip);
  203. }
  204. /*-------------------------------------------------------------------------
  205. * Function: Drone::Status
  206. *-------------------------------------------------------------------------
  207. * Purpose:
  208. * Send status information over the chat. Goal information and drone info, too
  209. */
  210. void Drone::Status (void)
  211. {
  212. if (m_goal)
  213. m_goal->Status();
  214. else
  215. SendChat(NA, "No goal information available");
  216. Verbose("I am in %s", m_pShip->GetCluster()->GetName());
  217. Verbose("Shooting skill: %d%% Moving Skill %d%% Bravery: %d%%", (int)(m_flShootSkill*100), (int)(m_flMoveSkill*100), (int)(m_flBravery*100));
  218. }
  219. /*-------------------------------------------------------------------------
  220. * Function: Drone::DetermineGoal
  221. *-------------------------------------------------------------------------
  222. * Purpose:
  223. * Given the current goal, the goal stack, and the default goal, come up with a goal
  224. * for the drone
  225. */
  226. void Drone::DetermineGoal(void)
  227. {
  228. if (m_goal) // Already have a goal
  229. return;
  230. while (m_goalMemory.GetCount()) // Have a goal in memory, do that
  231. {
  232. RestoreGoal();
  233. assert(m_goal);
  234. if (!m_goal->Done())
  235. return;
  236. }
  237. SetGoal(GetNewDefaultGoal()); // No goals anywhere, use the default.
  238. }
  239. /*-------------------------------------------------------------------------
  240. * Function: Drone::GetNewDefaultGoal
  241. *-------------------------------------------------------------------------
  242. * Purpose:
  243. * This is meant to re-declared in the child classes. Default goal for a default
  244. * drone is to sit their and be dodge.
  245. */
  246. Goal* Drone::GetNewDefaultGoal(void)
  247. {
  248. Verbose("I'll just stay here and wait for an order");
  249. return new IdleGoal(this);
  250. }
  251. /*-------------------------------------------------------------------------
  252. * Function: Drone::SetGoal
  253. *-------------------------------------------------------------------------
  254. * Purpose:
  255. * Given the commandtype and target, backup the current goal and set m_goal
  256. * appropriately. Also send a confirmation message.
  257. */
  258. void Drone::SetGoal(CommandType cm, ImodelIGC* pTarget, bool reply)
  259. {
  260. BackupGoal();
  261. assert(cm != c_ctNoCommand);
  262. switch(cm)
  263. {
  264. case c_ctDestroy:
  265. {
  266. if (pTarget) {
  267. m_goal = new DestroyGoal(this, pTarget);
  268. if (reply)
  269. SendChat(NA, "I'm going to try to destroy %s", GetModelName(pTarget));
  270. }
  271. else {
  272. m_goal = new KillAnythingGoal(this);
  273. if (reply)
  274. SendChat(NA, "I'm going to try to destroy any enemies that I see");
  275. }
  276. }
  277. break;
  278. case c_ctMine:
  279. {
  280. MiningDrone* pDrone = NULL;
  281. CastTo(pDrone, this);
  282. if ((pTarget->GetObjectType() == OT_asteroid) &&
  283. ((IasteroidIGC*)pTarget)->HasCapability(c_aabmMineHe3))
  284. {
  285. m_goal = new MineGoal(pDrone, pTarget);
  286. if (reply)
  287. {
  288. SendChat(droneInTransitSound, "I'm going to mine %s", GetModelName(pTarget));
  289. }
  290. }
  291. else
  292. {
  293. SendChat(droneCantDoThatSound, "I can't do that");
  294. }
  295. }
  296. break;
  297. case c_ctUnload:
  298. {
  299. MiningDrone* pDrone = NULL;
  300. CastTo(pDrone, this);
  301. IstationIGC* pStation;
  302. CastTo(pStation, pTarget);
  303. if (pStation)
  304. {
  305. m_goal = new UnloadGoal(pDrone, pStation);
  306. if (reply)
  307. {
  308. if (pStation)
  309. SendChat(NA, "I'm going to unload at %s", GetModelName(pStation));
  310. else
  311. SendChat(NA, "I'm going to go unload");
  312. }
  313. }
  314. }
  315. break;
  316. case c_ctPatrol:
  317. {
  318. if (pTarget) {
  319. m_goal = new PatrolGoal(this, pTarget);
  320. if (reply)
  321. SendChat(NA, "I'm going to patrol between where I am now, and %s", GetModelName(pTarget));
  322. }
  323. }
  324. break;
  325. case c_ctGoto:
  326. {
  327. if (pTarget)
  328. {
  329. //enter starbases by default, goto everything else
  330. m_goal = new NewGotoGoal(this, pTarget, (pTarget->GetObjectType() == OT_station) ||
  331. (pTarget->GetObjectType() == OT_warp)
  332. ? Waypoint::c_oEnter
  333. : Waypoint::c_oGoto);
  334. //m_goal = new GotoGoal(this, pTarget, true);
  335. if (reply)
  336. SendChat(NA, "I'm going to %s", GetModelName(pTarget));
  337. }
  338. }
  339. break;
  340. case c_ctPickup:
  341. {
  342. if (pTarget) {
  343. m_goal = new PickupGoal(this, pTarget);
  344. if (reply)
  345. SendChat(NA, "I'm going to pick up %s", GetModelName(pTarget));
  346. }
  347. }
  348. break;
  349. case c_ctDefend:
  350. {
  351. if (pTarget) {
  352. m_goal = new DefendGoal(this, pTarget);
  353. if (reply)
  354. SendChat(NA, "I'll defend %s to the end", GetModelName(pTarget));
  355. }
  356. }
  357. break;
  358. case c_ctStop:
  359. {
  360. m_goal = new StayPutGoal(this);
  361. if (reply)
  362. SendChat(NA, "Just hangin'");
  363. }
  364. break;
  365. case c_ctDisable:
  366. {
  367. if (pTarget) {
  368. m_goal = new DisableGoal(this, pTarget);
  369. if (reply)
  370. SendChat(NA, "I'm going to attempt to disable %s", GetModelName(pTarget));
  371. }
  372. }
  373. break;
  374. case c_ctFollow:
  375. {
  376. if (pTarget) {
  377. m_goal = new FollowGoal(this, pTarget);
  378. if (reply)
  379. SendChat(NA, "Following %s", GetModelName(pTarget));
  380. }
  381. }
  382. break;
  383. case c_ctScout:
  384. {
  385. m_goal = new ScoutGoal(this, pTarget);
  386. if (reply)
  387. SendChat(NA, "I'm scouting %s", (pTarget) ? GetModelName(pTarget) : m_pShip->GetCluster()->GetName());
  388. }
  389. break;
  390. case c_ctRepair:
  391. {
  392. if (pTarget)
  393. {
  394. m_goal = new RepairGoal(this, pTarget);
  395. if (reply)
  396. SendChat(NA, "I'm repairing");
  397. }
  398. }
  399. break;
  400. case c_ctCapture:
  401. {
  402. if (pTarget) {
  403. m_goal = new CaptureGoal(this, pTarget);
  404. if (reply)
  405. SendChat(NA, "Attempting to capture %s", GetModelName(pTarget));
  406. }
  407. }
  408. break;
  409. case c_ctFace:
  410. {
  411. if (pTarget)
  412. {
  413. m_goal = new FaceGoal(this, pTarget);
  414. if (reply)
  415. SendChat(NA, "I'll sit here and face %s", GetModelName(pTarget));
  416. }
  417. }
  418. break;
  419. case c_ctConstruct:
  420. {
  421. ConstructionDrone* pcd = NULL;
  422. CastTo(pcd, this);
  423. IstationTypeIGC* pst = pcd->GetBuildStationType();
  424. if ((pTarget->GetObjectType() == OT_asteroid) &&
  425. ((IasteroidIGC*)pTarget)->HasCapability(pst->GetBuildAABM()))
  426. {
  427. m_goal = new ConstructGoal(this,
  428. pst,
  429. (IasteroidIGC*)pTarget);
  430. if (reply)
  431. {
  432. SendChat(droneInTransitSound, "Building %s at %s", pst->GetName(), GetModelName(pTarget));
  433. }
  434. }
  435. else
  436. {
  437. SendChat(droneCantDoThatSound, "I can't do that");
  438. }
  439. }
  440. break;
  441. case c_ctTest:
  442. {
  443. m_goal = new TestGoal(this);
  444. bVerbose = true;
  445. if (reply)
  446. SendChat(NA, "Initializing test run");
  447. }
  448. break;
  449. }
  450. }
  451. /*-------------------------------------------------------------------------
  452. * Function: Drone::SetGoal
  453. *-------------------------------------------------------------------------
  454. * Purpose:
  455. * Don't even have to switch on the command type, just backup and set the
  456. * goal
  457. */
  458. void Drone::SetGoal(Goal* goal)
  459. {
  460. if (goal) {
  461. BackupGoal();
  462. m_goal = goal;
  463. }
  464. }
  465. /*-------------------------------------------------------------------------
  466. * Function: Drone::SetGoal
  467. *-------------------------------------------------------------------------
  468. * Purpose:
  469. * Take the current goal, and move it to the top of the memory stack.
  470. */
  471. void Drone::BackupGoal(void)
  472. {
  473. if (!m_goal)
  474. return;
  475. m_goalMemory.PushEnd(m_goal);
  476. m_goal = NULL;
  477. }
  478. /*-------------------------------------------------------------------------
  479. * Function: Drone::RestoreGoal
  480. *-------------------------------------------------------------------------
  481. * Purpose:
  482. * Take the top of the stack, and put it as the current goal
  483. */
  484. void Drone::RestoreGoal(void)
  485. {
  486. int goalNum = m_goalMemory.GetCount();
  487. if (goalNum) {
  488. if (m_goal)
  489. delete m_goal;
  490. goalNum--; // the index equals the number of goals - 1
  491. m_goal = m_goalMemory[goalNum];
  492. m_goalMemory.Remove(goalNum);
  493. }
  494. else
  495. {
  496. Verbose("Tried to pop with no goals in memory");
  497. }
  498. }
  499. /*-------------------------------------------------------------------------
  500. * Function: Drone::ClearGoals
  501. *-------------------------------------------------------------------------
  502. * Purpose:
  503. * Clear the current goal and the entire goal stack. Start fresh.
  504. */
  505. void Drone::ClearGoals(void)
  506. {
  507. int index = m_goalMemory.GetCount();
  508. while (index--)
  509. {
  510. if (m_goalMemory[index])
  511. delete m_goalMemory[index];
  512. m_goalMemory.Remove(index);
  513. }
  514. if (m_goal)
  515. delete m_goal;
  516. m_goal = NULL;
  517. }
  518. /*-------------------------------------------------------------------------
  519. * Function: Drone::Instincts
  520. *-------------------------------------------------------------------------
  521. * Purpose:
  522. * There are certain things that I always want to check, regardless of my
  523. * goal. Put all of those in here.
  524. */
  525. bool Drone::Instincts(void)
  526. {
  527. if ((m_pShip->GetFraction() <= (1.0f - m_flBravery)) || (GetAmmoState(m_pShip) == c_asEmpty)) // Should I run away?
  528. {
  529. if ((dType == c_dtPirate) || (dType == c_dtBountyHunter))
  530. {
  531. if (!GetDisappear())
  532. {
  533. SendChat(NA, "It's just not worth it, I'm outta here");
  534. SetGoal(new DisappearGoal(this));
  535. return true;
  536. }
  537. }
  538. else
  539. {
  540. if (!m_goal || m_goal->GetType() != c_ctRepair)
  541. {
  542. // Check my entire goal history for a repair command, because I still want to be able to have sub-goals
  543. bool anyRepairGoals = false;
  544. for (int i = m_goalMemory.GetCount(); i>0; i--)
  545. {
  546. if (m_goalMemory[i-1]->GetType() == c_ctRepair)
  547. {
  548. anyRepairGoals = true;
  549. break;
  550. }
  551. }
  552. if (!anyRepairGoals)
  553. {
  554. IstationIGC* pstation = (IstationIGC*)(GetRepairStation());
  555. if (pstation)
  556. {
  557. SendChat(droneTooMuchDamageSound, "Forget this. I have to go get repaired");
  558. SetGoal(new RepairGoal(this, pstation));
  559. return true;
  560. }
  561. }
  562. }
  563. }
  564. }
  565. // When we get DamageTracking for the drones... Check to see if there is anyone that is just REALLY kicking our butts, REALLY being
  566. // defined in part by the bravery, and then decide to attack that person.
  567. return false;
  568. }
  569. /*-------------------------------------------------------------------------
  570. * Function: Drone::FindBestStation
  571. *-------------------------------------------------------------------------
  572. * Purpose:
  573. * When the drone needs to dock, this function will return the station which
  574. * he should dock at. It gives priority to any station that it has been
  575. * explicitly told.
  576. */
  577. IstationIGC* Drone::FindBestStation(bool fCheckEnemyStations)
  578. {
  579. IstationIGC* pHomeStation = m_pStation;
  580. // Go to my assigned station if it is in the cluster
  581. if (pHomeStation && m_pShip->GetCluster() == pHomeStation->GetCluster())
  582. return pHomeStation;
  583. // Find the closest friendly station in the cluster
  584. IstationIGC* pStation = (IstationIGC*) FindTarget(m_pShip,
  585. c_ttFriendly | c_ttStation | c_ttNearest | c_ttAnyCluster);
  586. return pStation;
  587. }
  588. /*-------------------------------------------------------------------------
  589. * Function: WingManDrone::GetNewDefaultGoal
  590. *-------------------------------------------------------------------------
  591. * Purpose:
  592. * Return a new default command for the drone
  593. */
  594. Goal* WingManDrone::GetNewDefaultGoal(void)
  595. {
  596. Verbose("Watching for enemy ships..");
  597. return new KillAnythingGoal(this);
  598. }
  599. /*-------------------------------------------------------------------------
  600. * Function: AutoPilotDrone::GetNewDefaultGoal
  601. *-------------------------------------------------------------------------
  602. * Purpose:
  603. * Return a new default command for the drone
  604. */
  605. Goal* AutoPilotDrone::GetNewDefaultGoal(void)
  606. {
  607. return new IdleGoal(this);
  608. }
  609. /*-------------------------------------------------------------------------
  610. * Function: PigPilotDrone::GetNewDefaultGoal
  611. *-------------------------------------------------------------------------
  612. * Purpose:
  613. * Return a new default command for the drone
  614. */
  615. Goal* PigPilotDrone::GetNewDefaultGoal(void)
  616. {
  617. return new IdleGoal(this);
  618. }
  619. #if 0
  620. void PigPilotDrone::Update(Time now, float dt)
  621. {
  622. // Do nothing until undocked
  623. if (m_pShip->GetStation())
  624. return;
  625. }
  626. #endif
  627. /*-------------------------------------------------------------------------
  628. * Function: BountyHunter::SetGoal
  629. *-------------------------------------------------------------------------
  630. * Purpose:
  631. * Can only take one target, once. Assert that here.
  632. */
  633. void BountyHunter::SetGoal(CommandType cm, ImodelIGC* pTarget, bool reply)
  634. {
  635. if (cm == c_ctDestroy && pTarget && pTarget->GetCluster())
  636. {
  637. if (m_pTarget)
  638. {
  639. if (reply)
  640. SendChat(NA, "I already have my target");
  641. return;
  642. }
  643. else
  644. {
  645. ClearGoals();
  646. if (reply)
  647. SendChat(NA, "As you wish, %s will be terminated", GetModelName(m_pTarget));
  648. m_pTarget = pTarget;
  649. }
  650. }
  651. Drone::SetGoal(cm, pTarget);
  652. }
  653. /*-------------------------------------------------------------------------
  654. * Function: BountyHunter::GetNewDefaultGoal
  655. *-------------------------------------------------------------------------
  656. * Purpose:
  657. * Return a new default command for the drone
  658. */
  659. Goal* BountyHunter::GetNewDefaultGoal(void)
  660. {
  661. if (m_pTarget) // Already got my target
  662. {
  663. if (m_pTarget->GetCluster()) // He's not dead
  664. {
  665. Verbose("Attempting to kill %s", GetModelName(m_pTarget));
  666. return new DestroyGoal(this, m_pTarget);
  667. }
  668. else // He is dead
  669. {
  670. Verbose("My work here is done. %s has been reduced to his component atoms", GetModelName(m_pTarget));
  671. return new DisappearGoal(this);
  672. }
  673. }
  674. else // Still waiting for a target
  675. {
  676. Verbose("Waiting for my kill command");
  677. return new IdleGoal(this);
  678. }
  679. }
  680. /*-------------------------------------------------------------------------
  681. * Function: Pirate::GetNewDefaultGoal
  682. *-------------------------------------------------------------------------
  683. * Purpose:
  684. * Return a new default command for the drone
  685. */
  686. Goal* Pirate::GetNewDefaultGoal(void)
  687. {
  688. // Look for a leader pirate in this sector
  689. // (aka, a pirate that is not currently just trying to follow someone else)
  690. // If I find one, then fly on his wing (follow)
  691. // If not, then I get to be the leader, and I should look for miners that I can take out
  692. // If I was already leaving, then I should still leave
  693. if (GetDisappear())
  694. {
  695. Verbose("Disappearing");
  696. return new DisappearGoal(this);
  697. }
  698. {
  699. Drone* leader = NULL;
  700. for (int i = 0; i < MAX_DRONES; i++)
  701. {
  702. if (leader = g_drones.m_pDroneList[i]) // This is an intentional assignment
  703. {
  704. if (leader != this && leader->GetDroneType() == c_dtPirate && leader->GetShip()->GetCluster() == m_pShip->GetCluster())
  705. { // Then it is another Pirate in this sector, now check his goal
  706. if (leader->GetGoal() && leader->GetGoal()->GetType() != c_ctMimic)
  707. { // Then we have our leader!
  708. Verbose("Following %s, he's my hero", GetModelName(leader->GetShip()));
  709. return new MimicGoal(this, leader);
  710. }
  711. }
  712. }
  713. }
  714. }
  715. // If I get here, then that means I get to be the leader! Let's find some trouble to get into...
  716. {
  717. Drone* target = NULL;
  718. for (int i = 0; i < MAX_DRONES; i++)
  719. {
  720. if (target = g_drones.m_pDroneList[i])
  721. {
  722. if (target != this && target->GetDroneType() == c_dtMining && target->GetShip()->GetCluster() == m_pShip->GetCluster())
  723. { // Then it is a Miner in this sector... that's good enough. Let's go get him
  724. Verbose("I'm off to kill the miners");
  725. return new DestroyGoal(this, target->GetShip());
  726. }
  727. }
  728. }
  729. }
  730. // If we get here, then there is really no damage that I can/should do in this sector... Disappear.
  731. Verbose("Disappearing");
  732. return new DisappearGoal(this);
  733. }
  734. void ConstructionDrone::Initialize(IstationTypeIGC* pstationtype)
  735. {
  736. m_pstationtype = pstationtype;
  737. SetGoal(new ConstructGoal(this, pstationtype, NULL));
  738. }