DRIVE.CPP 91 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338
  1. //
  2. // Copyright 2020 Electronic Arts Inc.
  3. //
  4. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
  5. // software: you can redistribute it and/or modify it under the terms of
  6. // the GNU General Public License as published by the Free Software Foundation,
  7. // either version 3 of the License, or (at your option) any later version.
  8. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
  9. // in the hope that it will be useful, but with permitted additional restrictions
  10. // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
  11. // distributed with this program. You should have received a copy of the
  12. // GNU General Public License along with permitted additional restrictions
  13. // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
  14. /* $Header: /CounterStrike/DRIVE.CPP 1 3/03/97 10:24a Joe_bostic $ */
  15. /***********************************************************************************************
  16. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  17. ***********************************************************************************************
  18. * *
  19. * Project Name : Command & Conquer *
  20. * *
  21. * File Name : DRIVE.CPP *
  22. * *
  23. * Programmer : Joe L. Bostic *
  24. * *
  25. * Start Date : April 22, 1994 *
  26. * *
  27. * Last Update : October 31, 1996 [JLB] *
  28. * *
  29. *---------------------------------------------------------------------------------------------*
  30. * Functions: *
  31. * DriveClass::AI -- Processes unit movement and rotation. *
  32. * DriveClass::Approach_Target -- Handles approaching the target in order to attack it. *
  33. * DriveClass::Assign_Destination -- Set the unit's NavCom. *
  34. * DriveClass::Class_Of -- Fetches a reference to the class type for this object. *
  35. * DriveClass::Debug_Dump -- Displays status information to monochrome screen. *
  36. * DriveClass::Do_Turn -- Tries to turn the vehicle to the specified direction. *
  37. * DriveClass::DriveClass -- Constructor for drive class object. *
  38. * DriveClass::Fixup_Path -- Adds smooth start path to normal movement path. *
  39. * DriveClass::Force_Track -- Forces the unit to use the indicated track. *
  40. * DriveClass::Lay_Track -- Handles track laying logic for the unit. *
  41. * DriveClass::Limbo -- Prepares vehicle and then limbos it. *
  42. * DriveClass::Mark_Track -- Marks the midpoint of the track as occupied. *
  43. * DriveClass::Ok_To_Move -- Checks to see if this object can begin moving. *
  44. * DriveClass::Per_Cell_Process -- Handles when unit finishes movement into a cell. *
  45. * DriveClass::Response_Attack -- Voice feedback when ordering the unit to attack a target. *
  46. * DriveClass::Response_Move -- Voice feedback when ordering the unit to move. *
  47. * DriveClass::Response_Select -- Voice feedback when selecting the unit. *
  48. * DriveClass::Scatter -- Causes the unit to travel to a nearby safe cell. *
  49. * DriveClass::Smooth_Turn -- Handles the low level coord calc for smooth turn logic. *
  50. * DriveClass::Start_Of_Move -- Tries to get a unit to advance toward cell. *
  51. * DriveClass::Stop_Driver -- Handles removing occupation bits when driving stops. *
  52. * DriveClass::Teleport_To -- Teleport object to specified location. *
  53. * DriveClass::While_Moving -- Processes unit movement. *
  54. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  55. #include "function.h"
  56. #ifdef NEVER
  57. void test(void)
  58. {
  59. enum nums {one, two, three};
  60. nums x;
  61. nums *ptr;
  62. ptr = &x;
  63. }
  64. #endif
  65. /***********************************************************************************************
  66. * DriveClass::Response_Select -- Voice feedback when selecting the unit. *
  67. * *
  68. * This is the voice to play when the unit is selected. *
  69. * *
  70. * INPUT: none *
  71. * *
  72. * OUTPUT: none *
  73. * *
  74. * WARNINGS: none *
  75. * *
  76. * HISTORY: *
  77. * 12/30/1994 JLB : Created. *
  78. *=============================================================================================*/
  79. void DriveClass::Response_Select(void)
  80. {
  81. assert(IsActive);
  82. static VocType _response[] = {
  83. VOC_VEHIC,
  84. VOC_REPORT,
  85. VOC_YESSIR,
  86. VOC_YESSIR,
  87. VOC_YESSIR,
  88. VOC_AWAIT
  89. };
  90. VocType response = _response[Sim_Random_Pick(0, ARRAY_SIZE(_response)-1)];
  91. if (AllowVoice) {
  92. Sound_Effect(response, fixed(1), -(ID+1));
  93. }
  94. }
  95. /***********************************************************************************************
  96. * DriveClass::Response_Move -- Voice feedback when ordering the unit to move. *
  97. * *
  98. * This plays the audio feedback when ordering this unit to move to a new destination. *
  99. * *
  100. * INPUT: none *
  101. * *
  102. * OUTPUT: none *
  103. * *
  104. * WARNINGS: none *
  105. * *
  106. * HISTORY: *
  107. * 12/30/1994 JLB : Created. *
  108. *=============================================================================================*/
  109. void DriveClass::Response_Move(void)
  110. {
  111. assert(IsActive);
  112. static VocType _response[] = {
  113. VOC_ACKNOWL,
  114. VOC_AFFIRM,
  115. };
  116. VocType response = _response[Sim_Random_Pick(0, ARRAY_SIZE(_response)-1)];
  117. if (AllowVoice) {
  118. Sound_Effect(response, fixed(1), -(ID+1));
  119. }
  120. }
  121. /***********************************************************************************************
  122. * DriveClass::Response_Attack -- Voice feedback when ordering the unit to attack a target. *
  123. * *
  124. * This plays the audio feedback when ordering this unit to attack. *
  125. * *
  126. * INPUT: none *
  127. * *
  128. * OUTPUT: none *
  129. * *
  130. * WARNINGS: none *
  131. * *
  132. * HISTORY: *
  133. * 12/30/1994 JLB : Created. *
  134. *=============================================================================================*/
  135. void DriveClass::Response_Attack(void)
  136. {
  137. assert(IsActive);
  138. static VocType _response[] = {
  139. VOC_AFFIRM,
  140. VOC_ACKNOWL
  141. };
  142. VocType response = _response[Sim_Random_Pick(0, ARRAY_SIZE(_response)-1)];
  143. if (AllowVoice) {
  144. Sound_Effect(response, fixed(1), -(ID+1));
  145. }
  146. }
  147. /***********************************************************************************************
  148. * DriveClass::Scatter -- Causes the unit to travel to a nearby safe cell. *
  149. * *
  150. * This routine is called when the unit discovers that it should get out of the "hot seat" *
  151. * and move to an adjacent cell. Since the safety of the adjacent cell is not determined *
  152. * before the move begins, it will appear that the unit is just scattering (which it *
  153. * should). *
  154. * *
  155. * INPUT: threat -- The coordinate of the source of the threat. The unit will try to move *
  156. * roughly away from the threat. *
  157. * *
  158. * forced -- The threat is real and a serious effort to scatter should be made. *
  159. * *
  160. * nokidding-- The scatter should affect the player's infantry even if it otherwise *
  161. * wouldn't have. *
  162. * *
  163. * OUTPUT: none *
  164. * *
  165. * WARNINGS: none *
  166. * *
  167. * HISTORY: *
  168. * 09/25/1994 JLB : Created. *
  169. * 09/27/1995 JLB : Revised to never scatter if already moving. *
  170. * 07/09/1996 JLB : Moved to DriveClass so that ships will scatter too. *
  171. * 08/02/1996 JLB : Added the "nokidding" parameter. *
  172. *=============================================================================================*/
  173. void DriveClass::Scatter(COORDINATE threat, bool forced, bool nokidding)
  174. {
  175. assert(IsActive);
  176. /*
  177. ** Certain missions prevent scattering regardless of whether it would be
  178. ** a good idea or not.
  179. */
  180. if (MissionControl[Mission].IsParalyzed) return;
  181. if ((What_Am_I() != RTTI_UNIT || !((UnitClass *)this)->IsDumping) && (!Target_Legal(NavCom) || (nokidding && !IsRotating))) {
  182. if (!Target_Legal(TarCom) || forced || Random_Pick(1, 4) == 1) {
  183. FacingType toface;
  184. FacingType newface;
  185. CELL newcell;
  186. if (threat != 0) {
  187. toface = Dir_Facing(Direction8(threat, Coord));
  188. toface = toface + FacingType(Random_Pick(0, 2)-1);
  189. } else {
  190. toface = Dir_Facing(PrimaryFacing.Current());
  191. toface = toface + FacingType(Random_Pick(0, 2)-1);
  192. }
  193. for (FacingType face = FACING_N; face < FACING_COUNT; face++) {
  194. newface = toface + face;
  195. newcell = Adjacent_Cell(Coord_Cell(Coord), newface);
  196. if (Map.In_Radar(newcell) && Can_Enter_Cell(newcell) == MOVE_OK) {
  197. Assign_Destination(::As_Target(newcell));
  198. }
  199. }
  200. }
  201. }
  202. }
  203. /***********************************************************************************************
  204. * DriveClass::Limbo -- Prepares vehicle and then limbos it. *
  205. * *
  206. * This routine removes the occupation bits for the vehicle and also handles cleaning up *
  207. * any vehicle reservation bits. After this, it then proceeds with limboing the unit. *
  208. * *
  209. * INPUT: none *
  210. * *
  211. * OUTPUT: bool; Was the vehicle limboed? *
  212. * *
  213. * WARNINGS: none *
  214. * *
  215. * HISTORY: *
  216. * 12/22/1994 JLB : Created. *
  217. *=============================================================================================*/
  218. bool DriveClass::Limbo(void)
  219. {
  220. if (!IsInLimbo) {
  221. Stop_Driver();
  222. TrackNumber = -1;
  223. }
  224. return(FootClass::Limbo());
  225. }
  226. /***********************************************************************************************
  227. * DriveClass::Stop_Driver -- Handles removing occupation bits when driving stops. *
  228. * *
  229. * This routine will remove the "reservation" flag (if present) when the vehicle is *
  230. * required to stop movement. *
  231. * *
  232. * INPUT: none *
  233. * *
  234. * OUTPUT: bool; Was the vehicle stopped? *
  235. * *
  236. * WARNINGS: none *
  237. * *
  238. * HISTORY: *
  239. * 12/22/1994 JLB : Created. *
  240. *=============================================================================================*/
  241. bool DriveClass::Stop_Driver(void)
  242. {
  243. assert(IsActive);
  244. /*
  245. ** We only need to do something if the vehicle is actually going
  246. ** somewhere.
  247. */
  248. if (Head_To_Coord()) {
  249. /*
  250. ** Safe off whether the vehicle is down or not so we know whether
  251. ** we have to put it back down.
  252. */
  253. int temp = IsDown;
  254. /*
  255. ** If the vehicle is down, pick it up so it doesn't interfere with
  256. ** our flags.
  257. */
  258. if (temp) {
  259. Mark(MARK_UP);
  260. }
  261. /*
  262. ** Call the drive class function which will let us release the
  263. ** reserved track.
  264. */
  265. Mark_Track(Head_To_Coord(), MARK_UP);
  266. /*
  267. ** If it was down it should be down when we are done.
  268. */
  269. if (temp) {
  270. Mark(MARK_DOWN);
  271. }
  272. }
  273. return(FootClass::Stop_Driver());
  274. }
  275. /***********************************************************************************************
  276. * DriveClass::Do_Turn -- Tries to turn the vehicle to the specified direction. *
  277. * *
  278. * This routine will set the vehicle to rotate to the direction specified. For tracked *
  279. * vehicles, it is just a simple rotation. For wheeled vehicles, it performs a series *
  280. * of short drives (three point turn) to face the desired direction. *
  281. * *
  282. * INPUT: dir -- The direction that this vehicle should face. *
  283. * *
  284. * OUTPUT: none *
  285. * *
  286. * WARNINGS: none *
  287. * *
  288. * HISTORY: *
  289. * 05/29/1995 JLB : Created. *
  290. *=============================================================================================*/
  291. void DriveClass::Do_Turn(DirType dir)
  292. {
  293. assert(IsActive);
  294. if (dir != PrimaryFacing) {
  295. #ifdef TOFIX
  296. /*
  297. ** Special rotation track is needed for units that
  298. ** cannot rotate in place.
  299. */
  300. if (Special.IsThreePoint && TrackNumber == -1 && Techno_Type_Class()->Speed == SPEED_WHEEL) {
  301. int facediff; // Signed difference between current and desired facing.
  302. FacingType face; // Current facing (ordinal value).
  303. facediff = PrimaryFacing.Difference(dir) >> 5;
  304. facediff = Bound(facediff, -2, 2);
  305. if (facediff) {
  306. face = Dir_Facing(PrimaryFacing);
  307. IsOnShortTrack = true;
  308. Force_Track(face*FACING_COUNT + (face + facediff), Coord);
  309. Path[0] = FACING_NONE;
  310. Set_Speed(0xFF); // Full speed.
  311. }
  312. } else {
  313. PrimaryFacing.Set_Desired(dir);
  314. }
  315. #else
  316. PrimaryFacing.Set_Desired(dir);
  317. // IsRotating = true;
  318. #endif
  319. }
  320. }
  321. /***********************************************************************************************
  322. * DriveClass::Teleport_To -- Teleport object to specified location. *
  323. * *
  324. * This will teleport the object to the specified location or as close as possible to it *
  325. * if the destination is blocked. *
  326. * *
  327. * INPUT: cell -- The desired destination cell to teleport to. *
  328. * *
  329. * OUTPUT: bool; Was the teleport successful? *
  330. * *
  331. * WARNINGS: All current activity of this object will be terminated by the teleport. It will *
  332. * arrive at the destination in static guard mode. *
  333. * *
  334. * HISTORY: *
  335. * 10/21/1996 JLB : Created. *
  336. * 10/31/1996 JLB : Handles flag teleport case. *
  337. *=============================================================================================*/
  338. bool DriveClass::Teleport_To(CELL cell)
  339. {
  340. /*
  341. ** All cargo gets destroyed.
  342. */
  343. if (Rule.IsChronoKill) {
  344. Kill_Cargo(NULL);
  345. }
  346. Stop_Driver();
  347. Force_Track(-1, 0);
  348. PrimaryFacing.Set_Current(PrimaryFacing.Desired());
  349. Transmit_Message(RADIO_OVER_OUT);
  350. Assign_Destination(TARGET_NONE);
  351. Assign_Target(TARGET_NONE);
  352. Assign_Mission(MISSION_NONE);
  353. Commence();
  354. Mark(MARK_UP);
  355. /*
  356. ** A teleported unit will drop the flag right where it's at.
  357. */
  358. if (What_Am_I() == RTTI_UNIT && ((UnitClass *)this)->Flagged != HOUSE_NONE) {
  359. HouseClass::As_Pointer(((UnitClass *)this)->Flagged)->Flag_Attach(Coord_Cell(Coord));
  360. }
  361. if (Can_Enter_Cell(cell) != MOVE_OK) {
  362. cell = Map.Nearby_Location(cell, Techno_Type_Class()->Speed);
  363. }
  364. Coord = Cell_Coord(cell);
  365. Mark(MARK_DOWN);
  366. Look(false);
  367. Per_Cell_Process(PCP_END);
  368. return(true);
  369. }
  370. /***********************************************************************************************
  371. * DriveClass::Force_Track -- Forces the unit to use the indicated track. *
  372. * *
  373. * This override (nuclear bomb) style routine is to be used when a unit needs to start *
  374. * on a movement track but is outside the normal movement system. This occurs when a *
  375. * harvester starts driving off of a refinery. *
  376. * *
  377. * INPUT: track -- The track number to start on. *
  378. * *
  379. * coord -- The coordinate that the unit will end up at when the movement track *
  380. * is completed. *
  381. * *
  382. * OUTPUT: none *
  383. * *
  384. * WARNINGS: none *
  385. * *
  386. * HISTORY: *
  387. * 03/17/1995 JLB : Created. *
  388. *=============================================================================================*/
  389. void DriveClass::Force_Track(int track, COORDINATE coord)
  390. {
  391. assert(IsActive);
  392. TrackNumber = track;
  393. TrackIndex = 0;
  394. if (coord != 0) {
  395. Start_Driver(coord);
  396. }
  397. }
  398. /***********************************************************************************************
  399. * DriveClass::DriveClass -- Constructor for drive class object. *
  400. * *
  401. * This will initialize the drive class to its default state. It is called as a result *
  402. * of creating a unit. *
  403. * *
  404. * INPUT: classid -- The unit's ID class. It is passed on to the foot class constructor. *
  405. * *
  406. * OUTPUT: none *
  407. * *
  408. * WARNINGS: none *
  409. * *
  410. * HISTORY: *
  411. * 07/13/1994 JLB : Created. *
  412. *=============================================================================================*/
  413. DriveClass::DriveClass(RTTIType rtti, int id, HousesType house) :
  414. FootClass(rtti, id, house),
  415. IsMoebius(false),
  416. IsHarvesting(false),
  417. IsTurretLockedDown(false),
  418. IsOnShortTrack(false),
  419. SpeedAccum(0),
  420. MoebiusCountDown(0),
  421. MoebiusCell(0),
  422. TrackNumber(-1),
  423. TrackIndex(0)
  424. {
  425. }
  426. #ifdef CHEAT_KEYS
  427. /***********************************************************************************************
  428. * DriveClass::Debug_Dump -- Displays status information to monochrome screen. *
  429. * *
  430. * This debug utility function will display the status of the drive class to the mono *
  431. * screen. It is through this information that bugs can be tracked down. *
  432. * *
  433. * INPUT: none *
  434. * *
  435. * OUTPUT: none *
  436. * *
  437. * WARNINGS: none *
  438. * *
  439. * HISTORY: *
  440. * 05/31/1994 JLB : Created. *
  441. *=============================================================================================*/
  442. void DriveClass::Debug_Dump(MonoClass * mono) const
  443. {
  444. assert(IsActive);
  445. mono->Fill_Attrib(66, 14, 12, 1, IsMoebius ? MonoClass::INVERSE : MonoClass::NORMAL);
  446. FootClass::Debug_Dump(mono);
  447. }
  448. #endif
  449. /***********************************************************************************************
  450. * DriveClass::Smooth_Turn -- Handles the low level coord calc for smooth turn logic. *
  451. * *
  452. * This routine calculates the new coordinate value needed for the *
  453. * smooth turn logic. The adjustment and flag values must be *
  454. * determined prior to entering this routine. *
  455. * *
  456. * INPUT: adj -- The adjustment coordinate as lifted from the *
  457. * correct smooth turn table. *
  458. * *
  459. * dir -- Pointer to dir for possible modification *
  460. * according to the flag bits. *
  461. * *
  462. * OUTPUT: Returns with the coordinate the unit should positioned to. *
  463. * *
  464. * WARNINGS: none *
  465. * *
  466. * HISTORY: *
  467. * 03/14/1994 JLB : Created. *
  468. * 07/13/1994 JLB : Converted to member function. *
  469. *=============================================================================================*/
  470. COORDINATE DriveClass::Smooth_Turn(COORDINATE adj, DirType & dir)
  471. {
  472. assert(IsActive);
  473. DirType workdir = dir;
  474. int x,y;
  475. int temp;
  476. TrackControlType flags = TrackControl[TrackNumber].Flag;
  477. x = Coord_X(adj);
  478. y = Coord_Y(adj);
  479. if (flags & F_T) {
  480. temp = x;
  481. x = y;
  482. y = temp;
  483. workdir = (DirType)(DIR_W - workdir);
  484. }
  485. if (flags & F_X) {
  486. x = -x;
  487. workdir = (DirType)-workdir;
  488. }
  489. if (flags & F_Y) {
  490. y = -y;
  491. workdir = (DirType)(DIR_S - workdir);
  492. }
  493. dir = workdir;
  494. return(XY_Coord( (LEPTON)(Coord_X(Head_To_Coord()) + x), (LEPTON)(Coord_Y(Head_To_Coord()) + y)));
  495. }
  496. /***********************************************************************************************
  497. * DriveClass::Assign_Destination -- Set the unit's NavCom. *
  498. * *
  499. * This routine is used to set the unit's navigation computer to the *
  500. * specified target. Once the navigation computer is set, the unit *
  501. * will start planning and moving toward the destination. *
  502. * *
  503. * INPUT: target -- The destination target for the unit to head to. *
  504. * *
  505. * OUTPUT: none *
  506. * *
  507. * WARNINGS: none *
  508. * *
  509. * HISTORY: *
  510. * 09/07/1992 JLB : Created. *
  511. * 04/15/1994 JLB : Converted to member function. *
  512. *=============================================================================================*/
  513. void DriveClass::Assign_Destination(TARGET target)
  514. {
  515. assert(IsActive);
  516. /*
  517. ** Abort early if there is anything wrong with the parameters
  518. ** or the unit already is assigned the specified destination.
  519. */
  520. if (target == NavCom) return;
  521. /*
  522. ** For harvesting type vehicles, it might go into a dock and unload procedure
  523. ** when the harvester is full and an empty refinery is selected as a target.
  524. */
  525. BuildingClass * b = As_Building(target);
  526. /*
  527. ** If the player clicked on refinery but it is not busy, then assign
  528. ** it to unload at the refinery.
  529. */
  530. if (b != NULL && *b == STRUCT_REFINERY && What_Am_I() == RTTI_UNIT && ((UnitTypeClass *)Techno_Type_Class())->IsToHarvest) {
  531. if (Contact_With_Whom() != b && !b->In_Radio_Contact()) {
  532. /*
  533. ** Establish radio contact protocol. If the facility responds correctly,
  534. ** then remain in radio contact and proceed toward the desired destination.
  535. */
  536. if (Transmit_Message(RADIO_HELLO, b) == RADIO_ROGER) {
  537. if (Mission != MISSION_ENTER && Mission != MISSION_HARVEST) {
  538. Assign_Mission(MISSION_ENTER);
  539. target = TARGET_NONE;
  540. } else {
  541. // target = TARGET_NONE;
  542. }
  543. } else {
  544. // target = TARGET_NONE;
  545. }
  546. } else {
  547. // target = TARGET_NONE;
  548. }
  549. }
  550. /*
  551. ** Set the unit's navigation computer.
  552. */
  553. FootClass::Assign_Destination(target);
  554. Path[0] = FACING_NONE; // Force recalculation of path.
  555. if (!IsDriving && Mission != MISSION_UNLOAD) {
  556. Start_Of_Move();
  557. }
  558. }
  559. /***********************************************************************************************
  560. * DriveClass::While_Moving -- Processes unit movement. *
  561. * *
  562. * This routine is used to process movement for the units as they move. *
  563. * It is called many times for each cell's worth of movement. This *
  564. * routine only applies after the next cell HeadTo has been determined. *
  565. * *
  566. * INPUT: none *
  567. * *
  568. * OUTPUT: true/false; Should this routine be called again? *
  569. * *
  570. * WARNINGS: none *
  571. * *
  572. * HISTORY: *
  573. * 02/02/1992 JLB : Created. *
  574. * 04/15/1994 JLB : Converted to member function. *
  575. *=============================================================================================*/
  576. bool DriveClass::While_Moving(void)
  577. {
  578. assert(IsActive);
  579. /*
  580. ** Perform quick legality checks.
  581. */
  582. if (!IsDriving || TrackNumber == -1 || (IsRotating && !Techno_Type_Class()->IsTurretEquipped)) {
  583. SpeedAccum = 0; // Kludge? No speed should accumulate if movement is on hold.
  584. return(false);
  585. }
  586. /*
  587. ** If enough movement has accumulated so that the unit can
  588. ** visibly move on the map, then process accordingly.
  589. ** Slow the unit down if he's carrying a flag.
  590. */
  591. MPHType maxspeed = MPHType(min(Techno_Type_Class()->MaxSpeed * SpeedBias * House->GroundspeedBias, (int)MPH_LIGHT_SPEED));
  592. if (IsFormationMove) maxspeed = FormationMaxSpeed;
  593. int actual; // Working movement addition value.
  594. if (((UnitClass *)this)->Flagged != HOUSE_NONE) {
  595. actual = SpeedAccum + ((int)maxspeed/2) * fixed(Speed, 256);
  596. } else {
  597. actual = SpeedAccum + maxspeed * fixed(Speed, 256);
  598. }
  599. if (actual > PIXEL_LEPTON_W) {
  600. TurnTrackType const * track; // Track control pointer.
  601. TrackType const * ptr; // Pointer to coord offset values.
  602. int tracknum; // The track number being processed.
  603. FacingType nextface; // Next facing queued in path.
  604. bool adj; // Is a turn coming up?
  605. track = &TrackControl[TrackNumber];
  606. if (IsOnShortTrack) {
  607. tracknum = track->StartTrack;
  608. } else {
  609. tracknum = track->Track;
  610. }
  611. ptr = RawTracks[tracknum-1].Track;
  612. nextface = Path[0];
  613. /*
  614. ** Determine if there is a turn coming up. If there is
  615. ** a turn, then track jumping might occur.
  616. */
  617. adj = false;
  618. if (nextface != FACING_NONE && Dir_Facing(track->Facing) != nextface) {
  619. adj = true;
  620. }
  621. /*
  622. ** Skip ahead the number of track steps required (limited only
  623. ** by track length). Set the unit to the new position and
  624. ** flag the unit accordingly.
  625. */
  626. Mark(MARK_UP);
  627. while (actual > PIXEL_LEPTON_W) {
  628. COORDINATE offset;
  629. DirType dir;
  630. actual -= PIXEL_LEPTON_W;
  631. offset = ptr[TrackIndex].Offset;
  632. if (offset || !TrackIndex) {
  633. dir = ptr[TrackIndex].Facing;
  634. Coord = Smooth_Turn(offset, dir);
  635. PrimaryFacing.Set(dir);
  636. /*
  637. ** See if "per cell" processing is necessary.
  638. */
  639. if (TrackIndex && RawTracks[tracknum-1].Cell == TrackIndex) {
  640. Mark(MARK_DOWN);
  641. Per_Cell_Process(PCP_DURING);
  642. if (!IsActive) {
  643. return(false);
  644. }
  645. Mark(MARK_UP);
  646. }
  647. /*
  648. ** The unit could "jump tracks". Check to see if the unit should
  649. ** do so.
  650. */
  651. if (/**this != UNIT_GUNBOAT &&*/ nextface != FACING_NONE && adj && RawTracks[tracknum-1].Jump == TrackIndex && TrackIndex) {
  652. TurnTrackType const * newtrack; // Proposed jump-to track.
  653. int tnum;
  654. tnum = (int)(Dir_Facing(track->Facing) * FACING_COUNT) + (int)nextface;
  655. newtrack = &TrackControl[tnum];
  656. if (newtrack->Track && RawTracks[newtrack->Track-1].Entry) {
  657. COORDINATE c = Head_To_Coord();
  658. int oldspeed = Speed;
  659. c = Adjacent_Cell(c, nextface);
  660. switch (Can_Enter_Cell(Coord_Cell(c), nextface)) {
  661. case MOVE_OK:
  662. IsOnShortTrack = false; // Shouldn't be necessary, but...
  663. TrackNumber = tnum;
  664. track = newtrack;
  665. tracknum = track->Track;
  666. TrackIndex = RawTracks[tracknum-1].Entry-1; // Anticipate increment.
  667. ptr = RawTracks[tracknum-1].Track;
  668. adj = false;
  669. Stop_Driver();
  670. IsDriving = true;
  671. Per_Cell_Process(PCP_END);
  672. IsDriving = false;
  673. if (!IsActive) return(false);
  674. if (Start_Driver(c)) {
  675. Set_Speed(oldspeed);
  676. memcpy((char*)&Path[0], (char*)&Path[1], CONQUER_PATH_MAX-1);
  677. Path[CONQUER_PATH_MAX-1] = FACING_NONE;
  678. } else {
  679. Path[0] = FACING_NONE;
  680. TrackNumber = -1;
  681. actual = 0;
  682. }
  683. break;
  684. case MOVE_CLOAK:
  685. Map[c].Shimmer();
  686. break;
  687. case MOVE_TEMP:
  688. #ifdef TOFIX
  689. if (*this == UNIT_HARVESTER || !House->IsHuman) {
  690. #else
  691. if (!House->IsHuman) {
  692. #endif
  693. Map[c].Incoming(0, true, true);
  694. }
  695. break;
  696. }
  697. }
  698. }
  699. TrackIndex++;
  700. } else {
  701. actual = 0;
  702. Coord = Head_To_Coord();
  703. Stop_Driver();
  704. TrackNumber = -1;
  705. TrackIndex = NULL;
  706. /*
  707. ** Perform "per cell" activities.
  708. */
  709. Mark(MARK_DOWN);
  710. Per_Cell_Process(PCP_END);
  711. if (!IsActive) return(false);
  712. Mark(MARK_UP);
  713. break;
  714. }
  715. }
  716. if (IsActive) {
  717. Mark(MARK_DOWN);
  718. }
  719. }
  720. /*
  721. ** Replace any remainder back into the unit's movement
  722. ** accumulator to be processed next pass.
  723. */
  724. SpeedAccum = actual;
  725. return(true);
  726. }
  727. /***********************************************************************************************
  728. * DriveClass::Per_Cell_Process -- Handles when unit finishes movement into a cell. *
  729. * *
  730. * This routine is called when a unit has mostly or completely *
  731. * entered a cell. The unit might be in the middle of a movement track *
  732. * when this routine is called. It's primary purpose is to perform *
  733. * sighting and other "per cell" activities. *
  734. * *
  735. * INPUT: why -- Specifies the circumstances under which this routine was called. *
  736. * *
  737. * OUTPUT: none *
  738. * *
  739. * WARNINGS: none *
  740. * *
  741. * HISTORY: *
  742. * 11/03/1993 JLB : Created. *
  743. * 03/30/1994 JLB : Revamped for track system. *
  744. * 04/15/1994 JLB : Converted to member function. *
  745. * 06/18/1994 JLB : Converted to virtual function. *
  746. * 06/18/1994 JLB : Distinguishes between center and near-center conditions. *
  747. *=============================================================================================*/
  748. void DriveClass::Per_Cell_Process(PCPType why)
  749. {
  750. assert(IsActive);
  751. if (why == PCP_END) {
  752. CELL cell = Coord_Cell(Coord);
  753. /*
  754. ** Check to see if it has reached its destination. If so, then clear the NavCom
  755. ** regardless of the remaining path list.
  756. */
  757. if (As_Cell(NavCom) == cell) {
  758. IsTurretLockedDown = false;
  759. NavCom = TARGET_NONE;
  760. Path[0] = FACING_NONE;
  761. }
  762. Lay_Track();
  763. }
  764. FootClass::Per_Cell_Process(why);
  765. }
  766. /***********************************************************************************************
  767. * DriveClass::Start_Of_Move -- Tries to get a unit to advance toward cell. *
  768. * *
  769. * This will try to start a unit advancing toward the cell it is *
  770. * facing. It will check for and handle legality and reserving of the *
  771. * necessary cell. *
  772. * *
  773. * INPUT: none *
  774. * *
  775. * OUTPUT: true/false; Should this routine be called again because *
  776. * initial start operation is temporarily delayed? *
  777. * *
  778. * WARNINGS: none *
  779. * *
  780. * HISTORY: *
  781. * 02/02/1992 JLB : Created. *
  782. * 10/18/1993 JLB : This should be called repeatedly until HeadTo is not NULL. *
  783. * 03/16/1994 JLB : Revamped for track logic. *
  784. * 04/15/1994 JLB : Converted to member function. *
  785. * 06/19/1995 JLB : Fixed so that it won't fire on ground unnecessarily. *
  786. * 07/13/1995 JLB : Handles bumping into cloaked objects. *
  787. * 09/22/1995 JLB : Breaks out of hopeless hunt mode. *
  788. * 07/10/1996 JLB : Sets scan limit if necessary. *
  789. *=============================================================================================*/
  790. bool DriveClass::Start_Of_Move(void)
  791. {
  792. assert(IsActive);
  793. FacingType facing; // Direction movement will commence.
  794. DirType dir; // Desired actual facing toward destination.
  795. int facediff; // Difference between current and desired facing.
  796. int speed; // Speed of unit.
  797. CELL destcell; // Cell of destination.
  798. LandType ground; // Ground unit is entering.
  799. COORDINATE dest; // Destination coordinate.
  800. facing = Path[0];
  801. if (!Target_Legal(NavCom) && facing == FACING_NONE) {
  802. IsTurretLockedDown = false;
  803. Stop_Driver();
  804. if (Mission == MISSION_MOVE) {
  805. Enter_Idle_Mode();
  806. }
  807. return(false); // Why is it calling this routine!?!
  808. }
  809. /*
  810. ** Reduce the path length if the target is a unit and the
  811. ** range to the unit is less than the precalculated path steps.
  812. */
  813. if (facing != FACING_NONE) {
  814. int dist;
  815. if (Is_Target_Vessel(NavCom) || Is_Target_Unit(NavCom) || Is_Target_Infantry(NavCom)) {
  816. dist = Lepton_To_Cell((LEPTON)Distance(NavCom));
  817. if (dist < ARRAY_SIZE(Path)) {
  818. Path[dist] = FACING_NONE;
  819. facing = Path[0]; // Maybe needed.
  820. }
  821. }
  822. }
  823. /*
  824. ** If the path is invalid at this point, then generate one. If
  825. ** generating a new path fails, then abort NavCom.
  826. */
  827. if (facing == FACING_NONE) {
  828. /*
  829. ** If after a path search, there is still no valid path, then set the
  830. ** NavCom to null and let the script take care of assigning a new
  831. ** navigation target.
  832. */
  833. if (PathDelay != 0) {
  834. return(false);
  835. }
  836. if (!Basic_Path()) {
  837. /*
  838. ** If the unit is close enough to the target then just stop
  839. ** driving now. This prevents the fidgeting that would occur
  840. ** if they mindlessly kept trying to get to the exact location
  841. ** desired. This is quite necessary since it is typical to move
  842. ** several units with the same mouse click.
  843. */
  844. if (!Is_On_Priority_Mission() && Distance(NavCom) < Rule.CloseEnoughDistance && (Mission == MISSION_MOVE || Mission == MISSION_GUARD_AREA)) {
  845. Assign_Destination(TARGET_NONE);
  846. if (!IsActive) return(false);
  847. } else {
  848. /*
  849. ** If a basic path could not be found, but the immediate move destination is
  850. ** blocked by a friendly temporary blockage, then cause that blockage
  851. ** to scatter.
  852. */
  853. CELL cell = Adjacent_Cell(Coord_Cell(Center_Coord()), PrimaryFacing.Current());
  854. if (Map.In_Radar(cell)) {
  855. MoveType ok = Can_Enter_Cell(cell);
  856. if (ok == MOVE_TEMP) {
  857. CellClass * cellptr = &Map[cell];
  858. TechnoClass * blockage = cellptr->Cell_Techno();
  859. if (blockage && House->Is_Ally(blockage)) {
  860. /*
  861. ** If the target can be told to get out of the way, only bother
  862. ** to do so if we aren't very close to the target and this
  863. ** object can just say "good enough" and stop here.
  864. */
  865. if (Distance(NavCom) < Rule.CloseEnoughDistance && !In_Radio_Contact()) {
  866. Assign_Destination(TARGET_NONE);
  867. return(false);
  868. } else {
  869. cellptr->Incoming(0, true, false);
  870. // cellptr->Incoming(0, true, true);
  871. }
  872. }
  873. }
  874. }
  875. if (TryTryAgain > 0) {
  876. TryTryAgain--;
  877. } else {
  878. Assign_Destination(TARGET_NONE);
  879. if (!IsActive) return(false);
  880. if (IsNewNavCom) Sound_Effect(VOC_SCOLD);
  881. IsNewNavCom = false;
  882. }
  883. }
  884. /*
  885. ** Since the path was blocked, check to make sure that it was completely
  886. ** blocked. If so and it has a valid TarCom and it is out of range of the
  887. ** TarCom, then give this unit a range limit so that it might not pick
  888. ** a "can't reach" target again.
  889. */
  890. if (!Target_Legal(NavCom) && Target_Legal(TarCom) && !In_Range(TarCom)) {
  891. IsScanLimited = true;
  892. if (Team.Is_Valid()) Team->Scan_Limit();
  893. Assign_Target(TARGET_NONE);
  894. }
  895. /*
  896. ** Stop the movement, for now, and let the subsequent logic in later game
  897. ** frames resume movement as appropriate.
  898. */
  899. Stop_Driver();
  900. TrackNumber = -1;
  901. IsTurretLockedDown = false;
  902. return(false);
  903. }
  904. /*
  905. ** If a basic path could be found, but the immediate move destination is
  906. ** blocked by a friendly temporary blockage, then cause that blockage
  907. ** to scatter.
  908. */
  909. CELL cell = Adjacent_Cell(Coord_Cell(Center_Coord()), Path[0]);
  910. if (Map.In_Radar(cell)) {
  911. MoveType ok = Can_Enter_Cell(cell);
  912. if (ok == MOVE_TEMP) {
  913. CellClass * cellptr = &Map[cell];
  914. TechnoClass * blockage = cellptr->Cell_Techno();
  915. if (blockage && House->Is_Ally(blockage)) {
  916. /*
  917. ** If the target can be told to get out of the way, only bother
  918. ** to do so if we aren't very close to the target and this
  919. ** object can just say "good enough" and stop here.
  920. */
  921. if (Distance(NavCom) < Rule.CloseEnoughDistance && !In_Radio_Contact()) {
  922. Assign_Destination(TARGET_NONE);
  923. return(false);
  924. } else {
  925. cellptr->Incoming(0, true, false);
  926. // cellptr->Incoming(0, true, true);
  927. }
  928. }
  929. }
  930. }
  931. TryTryAgain = PATH_RETRY;
  932. facing = Path[0];
  933. }
  934. /*
  935. ** Determine the coordinate of the next cell to move into.
  936. */
  937. dest = Adjacent_Cell(Coord, facing);
  938. dir = Facing_Dir(facing);
  939. /*
  940. ** Set the facing correctly if it isn't already correct. This
  941. ** means starting a rotation track if necessary.
  942. */
  943. facediff = PrimaryFacing.Difference(dir);
  944. if (facediff) {
  945. /*
  946. ** Request a change of facing.
  947. */
  948. Do_Turn(dir);
  949. return(true);
  950. } else {
  951. /* NOTE: Beyond this point, actual track assignment can begin.
  952. **
  953. ** If the cell to move into is impassable (probably for some unexpected
  954. ** reason), then abort the path list and set the speed to zero. The
  955. ** next time this routine is called, a new path will be generated.
  956. */
  957. destcell = Coord_Cell(dest);
  958. Mark(MARK_UP);
  959. MoveType cando = Can_Enter_Cell(destcell, facing);
  960. Mark(MARK_DOWN);
  961. if (cando != MOVE_OK) {
  962. if (Mission == MISSION_MOVE /*KO&& House->IsHuman */&& Distance(NavCom) < Rule.CloseEnoughDistance) {
  963. Assign_Destination(TARGET_NONE);
  964. if (!IsActive) return(false);//BG
  965. }
  966. /*
  967. ** If a temporary friendly object is blocking the path, then cause it to
  968. ** get out of the way.
  969. */
  970. if (cando == MOVE_TEMP) {
  971. Map[destcell].Incoming(0, true, true);
  972. }
  973. /*
  974. ** If a cloaked object is blocking, then shimmer the cell.
  975. */
  976. if (cando == MOVE_CLOAK) {
  977. Map[destcell].Shimmer();
  978. }
  979. Stop_Driver();
  980. if (cando != MOVE_MOVING_BLOCK) {
  981. Path[0] = FACING_NONE; // Path is blocked!
  982. }
  983. /*
  984. ** If blocked by a moving block then just exit start of move and
  985. ** try again next tick.
  986. */
  987. if (cando == MOVE_DESTROYABLE) {
  988. if (Map[destcell].Cell_Object()) {
  989. if (!House->Is_Ally(Map[destcell].Cell_Object())) {
  990. Override_Mission(MISSION_ATTACK, Map[destcell].Cell_Object()->As_Target(), TARGET_NONE);
  991. }
  992. } else {
  993. if (Map[destcell].Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(Map[destcell].Overlay).IsWall) {
  994. Override_Mission(MISSION_ATTACK, ::As_Target(destcell), TARGET_NONE);
  995. }
  996. }
  997. } else {
  998. if (IsNewNavCom) Sound_Effect(VOC_SCOLD);
  999. }
  1000. IsNewNavCom = false;
  1001. TrackNumber = -1;
  1002. return(true);
  1003. }
  1004. /*
  1005. ** Determine the speed that the unit can travel to the desired square.
  1006. */
  1007. ground = Map[destcell].Land_Type();
  1008. speed = Ground[ground].Cost[Techno_Type_Class()->Speed] * 255;
  1009. /* change speed if it's related to a team move */
  1010. if (IsFormationMove) speed = Ground[ground].Cost[FormationSpeed] * 255;
  1011. if (!speed) speed = 128;
  1012. #ifdef NEVER
  1013. /*
  1014. ** Set the jiggle flag if the terrain would cause the unit
  1015. ** to jiggle when travelled over.
  1016. */
  1017. BaseF &= ~BASEF_JIGGLE;
  1018. if (Ground[ground].Jiggle) {
  1019. BaseF |= BASEF_JIGGLE;
  1020. }
  1021. #endif
  1022. /*
  1023. ** A damaged unit has a reduced speed.
  1024. */
  1025. if (Health_Ratio() <= Rule.ConditionYellow /*(Techno_Type_Class()->MaxStrength>>1) > Strength*/) {
  1026. speed -= (speed/4); // Three quarters speed.
  1027. }
  1028. if ((speed != Speed)/* || !SpeedAdd*/) {
  1029. Set_Speed(speed); // Full speed.
  1030. }
  1031. /*
  1032. ** Reserve the destination cell so that it won't become
  1033. ** occupied AS this unit is moving into it.
  1034. */
  1035. if (cando != MOVE_OK) {
  1036. Path[0] = FACING_NONE; // Path is blocked!
  1037. TrackNumber = -1;
  1038. dest = NULL;
  1039. } else {
  1040. Overrun_Square(Coord_Cell(dest), true);
  1041. /*
  1042. ** Determine which track to use (based on recorded path).
  1043. */
  1044. FacingType nextface = Path[1];
  1045. if (nextface == FACING_NONE) nextface = facing;
  1046. IsOnShortTrack = false;
  1047. TrackNumber = facing * FACING_COUNT + (int)nextface;
  1048. if (TrackControl[TrackNumber].Track == 0) {
  1049. Path[0] = FACING_NONE;
  1050. TrackNumber = -1;
  1051. return(true);
  1052. } else {
  1053. if (TrackControl[TrackNumber].Flag & F_D) {
  1054. /*
  1055. ** If the middle cell of a two cell track contains a crate,
  1056. ** the check for goodies before movement starts.
  1057. */
  1058. if (!Map[destcell].Goodie_Check(this)) {
  1059. cando = MOVE_NO;
  1060. if (!IsActive) return(false);
  1061. } else {
  1062. if (!IsActive) return(false);
  1063. dest = Adjacent_Cell(dest, nextface);
  1064. destcell = Coord_Cell(dest);
  1065. cando = Can_Enter_Cell(destcell);
  1066. }
  1067. if (!IsActive) return(false);
  1068. if (cando != MOVE_OK) {
  1069. /*
  1070. ** If a temporary friendly object is blocking the path, then cause it to
  1071. ** get out of the way.
  1072. */
  1073. if (cando == MOVE_TEMP) {
  1074. Map[destcell].Incoming(0, true, true);
  1075. }
  1076. /*
  1077. ** If a cloaked object is blocking, then shimmer the cell.
  1078. */
  1079. if (cando == MOVE_CLOAK) {
  1080. Map[destcell].Shimmer();
  1081. }
  1082. Path[0] = FACING_NONE; // Path is blocked!
  1083. TrackNumber = -1;
  1084. dest = NULL;
  1085. if (cando == MOVE_DESTROYABLE) {
  1086. if (Map[destcell].Cell_Object()) {
  1087. if (!House->Is_Ally(Map[destcell].Cell_Object())) {
  1088. Override_Mission(MISSION_ATTACK, Map[destcell].Cell_Object()->As_Target(), TARGET_NONE);
  1089. }
  1090. } else {
  1091. if (Map[destcell].Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(Map[destcell].Overlay).IsWall) {
  1092. Override_Mission(MISSION_ATTACK, ::As_Target(destcell), TARGET_NONE);
  1093. }
  1094. }
  1095. IsNewNavCom = false;
  1096. TrackIndex = 0;
  1097. return(true);
  1098. }
  1099. } else {
  1100. memcpy((char*)&Path[0], (char*)&Path[2], CONQUER_PATH_MAX-2);
  1101. Path[CONQUER_PATH_MAX-2] = FACING_NONE;
  1102. IsPlanningToLook = true;
  1103. }
  1104. } else {
  1105. memcpy((char*)&Path[0], (char*)&Path[1], CONQUER_PATH_MAX-1);
  1106. }
  1107. Path[CONQUER_PATH_MAX-1] = FACING_NONE;
  1108. }
  1109. }
  1110. IsNewNavCom = false;
  1111. TrackIndex = 0;
  1112. if (!Start_Driver(dest)) {
  1113. TrackNumber = -1;
  1114. Path[0] = FACING_NONE;
  1115. Set_Speed(0);
  1116. }
  1117. }
  1118. return(false);
  1119. }
  1120. /***********************************************************************************************
  1121. * DriveClass::AI -- Processes unit movement and rotation. *
  1122. * *
  1123. * This routine is used to process unit movement and rotation. It *
  1124. * functions autonomously from the script system. Thus, once a unit *
  1125. * is give rotation command or movement path, it will follow this *
  1126. * until specifically instructed to stop. The advantage of this *
  1127. * method is that it allows smooth movement of units, faster game *
  1128. * execution, and reduced script complexity (since actual movement *
  1129. * dynamics need not be controlled directly by the scripts). *
  1130. * *
  1131. * INPUT: none *
  1132. * *
  1133. * OUTPUT: none *
  1134. * *
  1135. * WARNINGS: This routine relies on the process control bits for the *
  1136. * specified unit (for speed reasons). Thus, only setting *
  1137. * movement, rotation, or path list will the unit perform *
  1138. * any physics. *
  1139. * *
  1140. * HISTORY: *
  1141. * 09/26/1993 JLB : Created. *
  1142. * 04/15/1994 JLB : Converted to member function. *
  1143. *=============================================================================================*/
  1144. void DriveClass::AI(void)
  1145. {
  1146. assert(IsActive);
  1147. FootClass::AI();
  1148. if (!IsActive || Height > 0) return;
  1149. /*
  1150. ** Is this a unit that's been teleported using the chronosphere, and if so,
  1151. ** has his timer expired such that he needs to teleport back?
  1152. */
  1153. if (IsMoebius) {
  1154. #ifdef FIXIT_CSII // checked - ajw 9/28/98
  1155. if (What_Am_I() != RTTI_UNIT || ((UnitClass *)this)->Class->Type != UNIT_CHRONOTANK) {
  1156. #endif
  1157. if (MoebiusCountDown == 0) {
  1158. IsMoebius = false;
  1159. Teleport_To(MoebiusCell);
  1160. MoebiusCell = 0;
  1161. }
  1162. #ifdef FIXIT_CSII // checked - ajw 9/28/98
  1163. }
  1164. #endif
  1165. }
  1166. /*
  1167. ** If the unit is following a track, then continue
  1168. ** to do so -- mindlessly.
  1169. */
  1170. if (TrackNumber != -1) {
  1171. /*
  1172. ** Perform the movement accumulation.
  1173. */
  1174. While_Moving();
  1175. if (!IsActive) return;
  1176. if (TrackNumber == -1 && (Target_Legal(NavCom) || Path[0] != FACING_NONE) && (What_Am_I() != RTTI_UNIT || !((UnitClass*)this)->IsDumping)) {
  1177. Start_Of_Move();
  1178. if (!IsActive) return;
  1179. While_Moving();
  1180. if (!IsActive) return;
  1181. }
  1182. } else {
  1183. /*
  1184. ** For tracked units that are rotating in place, perform the rotation now.
  1185. */
  1186. #ifdef TOFIX
  1187. if ((Class->Speed == SPEED_FLOAT || Class->Speed == SPEED_HOVER || Class->Speed == SPEED_TRACK || (Class->Speed == SPEED_WHEEL && !Special.IsThreePoint)) && PrimaryFacing.Is_Rotating()) {
  1188. if (PrimaryFacing.Rotation_Adjust(Class->ROT)) {
  1189. Mark(MARK_CHANGE);
  1190. }
  1191. #else
  1192. if (PrimaryFacing.Is_Rotating()) {
  1193. Mark(MARK_CHANGE_REDRAW);
  1194. if (PrimaryFacing.Rotation_Adjust(Techno_Type_Class()->ROT * House->GroundspeedBias)) {
  1195. Mark(MARK_CHANGE_REDRAW);
  1196. }
  1197. #endif
  1198. if (!IsRotating) {
  1199. Per_Cell_Process(PCP_ROTATION);
  1200. if (!IsActive) return;
  1201. }
  1202. } else {
  1203. /*
  1204. ** The unit has no track to follow, but if there
  1205. ** is a navigation target or a remaining path,
  1206. ** then start on a new track.
  1207. */
  1208. if ((Mission != MISSION_GUARD || Target_Legal(NavCom)) && Mission != MISSION_UNLOAD) {
  1209. if (Target_Legal(NavCom) || Path[0] != FACING_NONE) {
  1210. /*
  1211. ** Double check to make sure that the movement destination is
  1212. ** in a zone that this unit can travel to. If not, then abort
  1213. ** the navigation target. Exception is to allow units to leave
  1214. ** impassable cells regardless of zone checks.
  1215. */
  1216. LandType land = LAND_NONE;
  1217. if (What_Am_I() == RTTI_INFANTRY || What_Am_I() == RTTI_UNIT) {
  1218. land = Map[Center_Coord()].Land_Type();
  1219. }
  1220. if (IsLocked && Mission != MISSION_ENTER && Target_Legal(NavCom) && !Is_In_Same_Zone(As_Cell(NavCom)) &&
  1221. land != LAND_ROCK && land != LAND_WATER && land != LAND_RIVER && !Team) {
  1222. Stop_Driver();
  1223. Assign_Destination(TARGET_NONE);
  1224. } else {
  1225. Start_Of_Move();
  1226. if (!IsActive) return;
  1227. While_Moving();
  1228. if (!IsActive) return;
  1229. }
  1230. } else {
  1231. Stop_Driver();
  1232. }
  1233. }
  1234. }
  1235. }
  1236. }
  1237. /***********************************************************************************************
  1238. * DriveClass::Fixup_Path -- Adds smooth start path to normal movement path. *
  1239. * *
  1240. * This routine modifies the path of the specified unit so that it *
  1241. * will not start out with a rotation. This is necessary for those *
  1242. * vehicles that have difficulty with rotating in place. Typically, *
  1243. * this includes wheeled vehicles. *
  1244. * *
  1245. * INPUT: unit -- Pointer to the unit to adjust. *
  1246. * *
  1247. * path -- Pointer to path structure. *
  1248. * *
  1249. * OUTPUT: none *
  1250. * *
  1251. * WARNINGS: Only units that require a fixup get modified. The *
  1252. * modification only occurs, if there is a legal path to *
  1253. * do so. *
  1254. * *
  1255. * HISTORY: *
  1256. * 04/03/1994 JLB : Created. *
  1257. * 04/06/1994 JLB : Uses path structure. *
  1258. * 04/10/1994 JLB : Diagonal smooth turn added. *
  1259. * 04/15/1994 JLB : Converted to member function. *
  1260. *=============================================================================================*/
  1261. void DriveClass::Fixup_Path(PathType * path)
  1262. {
  1263. assert(IsActive);
  1264. FacingType stage[6]={FACING_N,FACING_N,FACING_N,FACING_N,FACING_N,FACING_N}; // Prefix path elements.
  1265. int facediff; // The facing difference value (0..4 | 0..-4).
  1266. static FacingType _path[4][6] = {
  1267. {(FacingType)2,(FacingType)0,(FacingType)2,(FacingType)0,(FacingType)0,(FacingType)0},
  1268. {(FacingType)3,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)0,(FacingType)0},
  1269. {(FacingType)4,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)0,(FacingType)0},
  1270. {(FacingType)4,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)1,(FacingType)0}
  1271. };
  1272. static FacingType _dpath[4][6] = {
  1273. {(FacingType)0,(FacingType)0,(FacingType)0,(FacingType)0,(FacingType)0,(FacingType)0},
  1274. {(FacingType)3,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)0,(FacingType)0},
  1275. {(FacingType)4,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)1,(FacingType)0},
  1276. {(FacingType)5,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)1,(FacingType)0}
  1277. };
  1278. int index;
  1279. int counter; // Path addition
  1280. FacingType * ptr; // Path list pointer.
  1281. FacingType * ptr2; // Copy of new path list pointer.
  1282. FacingType nextpath; // Next path value.
  1283. CELL cell; // Working cell value.
  1284. bool ok;
  1285. /*
  1286. ** Verify that the unit is valid and there is a path problem to resolve.
  1287. */
  1288. if (!path || path->Command[0] == FACING_NONE) {
  1289. return;
  1290. }
  1291. /*
  1292. ** Only wheeled vehicles need a path fixup -- to avoid 3 point turns.
  1293. */
  1294. #ifdef TOFIX
  1295. if (!Special.IsThreePoint || Class->Speed != SPEED_WHEEL) {
  1296. #else
  1297. if (What_Am_I() == RTTI_UNIT || What_Am_I() == RTTI_VESSEL) {
  1298. // if (What_Am_I() == RTTI_UNIT) {
  1299. #endif
  1300. return;
  1301. }
  1302. /*
  1303. ** If the original path starts in the same direction as the unit, then
  1304. ** there is no problem to resolve -- abort.
  1305. */
  1306. facediff = PrimaryFacing.Difference((DirType)(path->Command[0]<<5)) >> 5;
  1307. if (!facediff) return;
  1308. if (Dir_Facing(PrimaryFacing) & FACING_NE) {
  1309. ptr = &_dpath[(FacingType)ABS((int)facediff)-FACING_NE][1]; // Pointer to path adjust list.
  1310. counter = (int)_dpath[(FacingType)ABS((int)facediff)-FACING_NE][0]; // Number of path adjusts.
  1311. } else {
  1312. ptr = &_path[(FacingType)ABS((int)facediff)-FACING_NE][1]; // Pointer to path adjust list.
  1313. counter = (int)_path[(FacingType)ABS((int)facediff)-FACING_NE][0]; // Number of path adjusts.
  1314. }
  1315. ptr2 = ptr;
  1316. ok = true; // Presume adjustment is all ok.
  1317. cell = Coord_Cell(Coord); // Starting cell.
  1318. nextpath = Dir_Facing(PrimaryFacing); // Starting path.
  1319. for (index = 0; index < counter; index++) {
  1320. /*
  1321. ** Determine next path element and add it to the
  1322. ** working path list.
  1323. */
  1324. if (facediff > 0) {
  1325. nextpath = nextpath + *ptr++;
  1326. } else {
  1327. nextpath = nextpath - *ptr++;
  1328. }
  1329. stage[index] = nextpath;
  1330. cell = Adjacent_Cell(cell, nextpath);
  1331. //cell = Coord_Cell(Adjacent_Cell(Cell_Coord(cell), nextpath));
  1332. /*
  1333. ** If it can't enter this cell, then abort the path
  1334. ** building operation without adjusting the unit's
  1335. ** path.
  1336. */
  1337. if (Can_Enter_Cell(cell, nextpath) != MOVE_OK) {
  1338. ok = false;
  1339. break;
  1340. }
  1341. }
  1342. /*
  1343. ** If veering to the left was not successful, then try veering
  1344. ** to the right. This only makes sense if the vehicle is trying
  1345. ** to turn 180 degrees.
  1346. */
  1347. if (!ok && ABS(facediff) == 4) {
  1348. ptr = ptr2; // Pointer to path adjust list.
  1349. facediff = -facediff;
  1350. ok = true; // Presume adjustment is all ok.
  1351. cell = Coord_Cell(Coord); // Starting cell.
  1352. nextpath = Dir_Facing(PrimaryFacing); // Starting path.
  1353. for (index = 0; index < counter; index++) {
  1354. /*
  1355. ** Determine next path element and add it to the
  1356. ** working path list.
  1357. */
  1358. if (facediff > 0) {
  1359. nextpath = nextpath + *ptr++;
  1360. } else {
  1361. nextpath = nextpath - *ptr++;
  1362. }
  1363. stage[index] = nextpath;
  1364. cell = Coord_Cell(Adjacent_Cell(Cell_Coord(cell), nextpath));
  1365. /*
  1366. ** If it can't enter this cell, then abort the path
  1367. ** building operation without adjusting the unit's
  1368. ** path.
  1369. */
  1370. if (Can_Enter_Cell(cell, nextpath) != MOVE_OK) {
  1371. ok = false;
  1372. break;
  1373. }
  1374. }
  1375. }
  1376. /*
  1377. ** If a legal path addition was created, then install it in place
  1378. ** of the first path value. The initial path entry is to be replaced
  1379. ** with a sequence of path entries that create smooth turning.
  1380. */
  1381. if (ok) {
  1382. if (path->Length <= 1) {
  1383. memmove((char *)&stage[0], (char*)path->Command, max(counter, 1));
  1384. path->Length = counter;
  1385. } else {
  1386. /*
  1387. ** Optimize the transition path step from the smooth turn
  1388. ** first part as it joins with the rest of the normal
  1389. ** path. The normal prefix path steps are NOT to be optimized.
  1390. */
  1391. if (counter) {
  1392. counter--;
  1393. path->Command[0] = stage[counter];
  1394. Optimize_Moves(path, MOVE_OK);
  1395. }
  1396. /*
  1397. ** If there is more than one prefix path element, then
  1398. ** insert the rest now.
  1399. */
  1400. if (counter) {
  1401. memmove((char*)&path->Command[0], (char*)&path->Command[counter], 40-counter);
  1402. memmove((char*)&stage[0], (char*)&path->Command[0], counter);
  1403. path->Length += counter;
  1404. }
  1405. }
  1406. path->Command[path->Length] = FACING_NONE;
  1407. }
  1408. }
  1409. /***********************************************************************************************
  1410. * DriveClass::Lay_Track -- Handles track laying logic for the unit. *
  1411. * *
  1412. * This routine handles the track laying for the unit. This entails examining the unit's *
  1413. * current location as well as the direction and whether this unit is allowed to lay *
  1414. * tracks in the first place. *
  1415. * *
  1416. * INPUT: none *
  1417. * *
  1418. * OUTPUT: none *
  1419. * *
  1420. * WARNINGS: none *
  1421. * *
  1422. * HISTORY: *
  1423. * 05/28/1994 JLB : Created. *
  1424. *=============================================================================================*/
  1425. void DriveClass::Lay_Track(void)
  1426. {
  1427. assert(IsActive);
  1428. #ifdef NEVER
  1429. static IconCommandType * _trackdirs[8] = {
  1430. TrackN_S,
  1431. TrackNE_SW,
  1432. TrackE_W,
  1433. TrackNW_SE,
  1434. TrackN_S,
  1435. TrackNE_SW,
  1436. TrackE_W,
  1437. TrackNW_SE
  1438. };
  1439. if (!(ClassF & CLASSF_TRACKS)) return;
  1440. Icon_Install(Coord_Cell(Coord), _trackdirs[Facing_To_8(BodyFacing)]);
  1441. #endif
  1442. }
  1443. /***********************************************************************************************
  1444. * DriveClass::Mark_Track -- Marks the midpoint of the track as occupied. *
  1445. * *
  1446. * This routine will ensure that the midpoint (if any) of the track that the unit is *
  1447. * following, will be marked according to the mark type specified. *
  1448. * *
  1449. * INPUT: headto -- The head to coordinate. *
  1450. * *
  1451. * type -- The type of marking to perform. *
  1452. * *
  1453. * OUTPUT: none *
  1454. * *
  1455. * WARNINGS: none *
  1456. * *
  1457. * HISTORY: *
  1458. * 07/30/1995 JLB : Created. *
  1459. *=============================================================================================*/
  1460. void DriveClass::Mark_Track(COORDINATE headto, MarkType type)
  1461. {
  1462. assert(IsActive);
  1463. int value;
  1464. if (type == MARK_UP) {
  1465. value = false;
  1466. } else {
  1467. value = true;
  1468. }
  1469. if (headto) {
  1470. if (!IsOnShortTrack && TrackNumber != -1) {
  1471. /*
  1472. ** If we have not passed the per cell process point we need
  1473. ** to deal with it.
  1474. */
  1475. int tracknum = TrackControl[TrackNumber].Track;
  1476. if (tracknum) {
  1477. TrackType const * ptr = RawTracks[tracknum - 1].Track;
  1478. int cellidx = RawTracks[tracknum - 1].Cell;
  1479. if (cellidx > -1) {
  1480. DirType dir = ptr[cellidx].Facing;
  1481. if (TrackIndex < cellidx && cellidx != -1) {
  1482. COORDINATE offset = Smooth_Turn(ptr[cellidx].Offset, dir);
  1483. Map[offset].Flag.Occupy.Vehicle = value;
  1484. }
  1485. }
  1486. }
  1487. }
  1488. Map[headto].Flag.Occupy.Vehicle = value;
  1489. }
  1490. }
  1491. /***********************************************************************************************
  1492. * DriveClass::Ok_To_Move -- Checks to see if this object can begin moving. *
  1493. * *
  1494. * This routine is used to verify that this object is allowed to move. Some objects can *
  1495. * be temporarily occupied and thus cannot move until the situation permits. *
  1496. * *
  1497. * INPUT: direction -- The direction that movement would be desired. *
  1498. * *
  1499. * OUTPUT: Can the unit move in the direction specified? *
  1500. * *
  1501. * WARNINGS: none *
  1502. * *
  1503. * HISTORY: *
  1504. * 07/29/1995 JLB : Created. *
  1505. *=============================================================================================*/
  1506. bool DriveClass::Ok_To_Move(DirType ) const
  1507. {
  1508. assert(IsActive);
  1509. return true;
  1510. }
  1511. /***************************************************************************
  1512. ** Smooth turn track tables. These are coordinate offsets from the center
  1513. ** of the destination cell. These are the raw tracks that are modified
  1514. ** by negating the X and Y portions as necessary. Also for reverse travelling
  1515. ** direction, the track list can be processed backward.
  1516. **
  1517. ** Track 1 = N
  1518. ** Track 2 = NE
  1519. ** Track 3 = N->NE 45 deg (double path consumption)
  1520. ** Track 4 = N->E 90 deg (double path consumption)
  1521. ** Track 5 = NE->SE 90 deg (double path consumption)
  1522. ** Track 6 = NE->N 45 deg (double path consumption)
  1523. ** Track 7 = N->NE (facing change only)
  1524. ** Track 8 = NE->E (facing change only)
  1525. ** Track 9 = N->E (facing change only)
  1526. ** Track 10= NE->SE (facing change only)
  1527. ** Track 11= back up into refinery
  1528. ** Track 12= drive out of refinery
  1529. */
  1530. //#pragma warn -ias
  1531. DriveClass::TrackType const DriveClass::Track1[24] = {
  1532. {0x00F50000L,(DirType)0},
  1533. {0x00EA0000L,(DirType)0},
  1534. {0x00DF0000L,(DirType)0},
  1535. {0x00D40000L,(DirType)0},
  1536. {0x00C90000L,(DirType)0},
  1537. {0x00BE0000L,(DirType)0},
  1538. {0x00B30000L,(DirType)0},
  1539. {0x00A80000L,(DirType)0},
  1540. {0x009D0000L,(DirType)0},
  1541. {0x00920000L,(DirType)0},
  1542. {0x00870000L,(DirType)0},
  1543. {0x007C0000L,(DirType)0}, // Track jump check here.
  1544. {0x00710000L,(DirType)0},
  1545. {0x00660000L,(DirType)0},
  1546. {0x005B0000L,(DirType)0},
  1547. {0x00500000L,(DirType)0},
  1548. {0x00450000L,(DirType)0},
  1549. {0x003A0000L,(DirType)0},
  1550. {0x002F0000L,(DirType)0},
  1551. {0x00240000L,(DirType)0},
  1552. {0x00190000L,(DirType)0},
  1553. {0x000E0000L,(DirType)0},
  1554. {0x00030000L,(DirType)0},
  1555. {0x00000000L,(DirType)0}
  1556. };
  1557. DriveClass::TrackType const DriveClass::Track2[] = {
  1558. {0x00F8FF08L,(DirType)32},
  1559. {0x00F0FF10L,(DirType)32},
  1560. {0x00E8FF18L,(DirType)32},
  1561. {0x00E0FF20L,(DirType)32},
  1562. {0x00D8FF28L,(DirType)32},
  1563. {0x00D0FF30L,(DirType)32},
  1564. {0x00C8FF38L,(DirType)32},
  1565. {0x00C0FF40L,(DirType)32},
  1566. {0x00B8FF48L,(DirType)32},
  1567. {0x00B0FF50L,(DirType)32},
  1568. {0x00A8FF58L,(DirType)32},
  1569. {0x00A0FF60L,(DirType)32},
  1570. {0x0098FF68L,(DirType)32},
  1571. {0x0090FF70L,(DirType)32},
  1572. {0x0088FF78L,(DirType)32},
  1573. {0x0080FF80L,(DirType)32}, // Track jump check here.
  1574. {0x0078FF88L,(DirType)32},
  1575. {0x0070FF90L,(DirType)32},
  1576. {0x0068FF98L,(DirType)32},
  1577. {0x0060FFA0L,(DirType)32},
  1578. {0x0058FFA8L,(DirType)32},
  1579. {0x0050FFB0L,(DirType)32},
  1580. {0x0048FFB8L,(DirType)32},
  1581. {0x0040FFC0L,(DirType)32},
  1582. {0x0038FFC8L,(DirType)32},
  1583. {0x0030FFD0L,(DirType)32},
  1584. {0x0028FFD8L,(DirType)32},
  1585. {0x0020FFE0L,(DirType)32},
  1586. {0x0018FFE8L,(DirType)32},
  1587. {0x0010FFF0L,(DirType)32},
  1588. {0x0008FFF8L,(DirType)32},
  1589. {0x00000000L,(DirType)32}
  1590. };
  1591. DriveClass::TrackType const DriveClass::Track3[] = {
  1592. {0x01F5FF00L,(DirType)0},
  1593. {0x01EAFF00L,(DirType)0},
  1594. {0x01DFFF00L,(DirType)0},
  1595. {0x01D4FF00L,(DirType)0},
  1596. {0x01C9FF00L,(DirType)0},
  1597. {0x01BEFF00L,(DirType)0},
  1598. {0x01B3FF00L,(DirType)0},
  1599. {0x01A8FF00L,(DirType)0},
  1600. {0x019DFF00L,(DirType)0},
  1601. {0x0192FF00L,(DirType)0},
  1602. {0x0187FF00L,(DirType)0},
  1603. {0x0180FF00L,(DirType)0},
  1604. {0x0175FF00L,(DirType)0}, // Jump entry point here.
  1605. {0x016BFF00L,(DirType)0},
  1606. {0x0160FF02L,(DirType)1},
  1607. {0x0155FF04L,(DirType)3},
  1608. {0x014CFF06L,(DirType)4},
  1609. {0x0141FF08L,(DirType)5},
  1610. {0x0137FF0BL,(DirType)7},
  1611. {0x012EFF0FL,(DirType)8},
  1612. {0x0124FF13L,(DirType)9},
  1613. {0x011AFF17L,(DirType)11},
  1614. {0x0110FF1BL,(DirType)12},
  1615. {0x0107FF1FL,(DirType)13}, // Center cell processing here.
  1616. {0x00FCFF24L,(DirType)15},
  1617. {0x00F3FF28L,(DirType)16},
  1618. {0x00ECFF2CL,(DirType)17},
  1619. {0x00E0FF32L,(DirType)19},
  1620. {0x00D7FF36L,(DirType)20},
  1621. {0x00CFFF3DL,(DirType)21},
  1622. {0x00C6FF42L,(DirType)23},
  1623. {0x00BAFF49L,(DirType)24},
  1624. {0x00B0FF4DL,(DirType)25},
  1625. {0x00A8FF58L,(DirType)27},
  1626. {0x00A0FF60L,(DirType)28},
  1627. {0x0098FF68L,(DirType)29},
  1628. {0x0090FF70L,(DirType)31},
  1629. {0x0088FF78L,(DirType)32},
  1630. {0x0080FF80L,(DirType)32}, // Track jump check here.
  1631. {0x0078FF88L,(DirType)32},
  1632. {0x0070FF90L,(DirType)32},
  1633. {0x0068FF98L,(DirType)32},
  1634. {0x0060FFA0L,(DirType)32},
  1635. {0x0058FFA8L,(DirType)32},
  1636. {0x0050FFB0L,(DirType)32},
  1637. {0x0048FFB8L,(DirType)32},
  1638. {0x0040FFC0L,(DirType)32},
  1639. {0x0038FFC8L,(DirType)32},
  1640. {0x0030FFD0L,(DirType)32},
  1641. {0x0028FFD8L,(DirType)32},
  1642. {0x0020FFE0L,(DirType)32},
  1643. {0x0018FFE8L,(DirType)32},
  1644. {0x0010FFF0L,(DirType)32},
  1645. {0x0008FFF8L,(DirType)32},
  1646. {0x00000000L,(DirType)32}
  1647. };
  1648. DriveClass::TrackType const DriveClass::Track4[] = {
  1649. {0x00F5FF00L,(DirType)0},
  1650. {0x00EBFF00L,(DirType)0},
  1651. {0x00E0FF00L,(DirType)0},
  1652. {0x00D5FF00L,(DirType)0},
  1653. {0x00CBFF01L,(DirType)0},
  1654. {0x00C0FF03L,(DirType)0},
  1655. {0x00B5FF05L,(DirType)1},
  1656. {0x00ABFF07L,(DirType)1},
  1657. {0x00A0FF0AL,(DirType)2},
  1658. {0x0095FF0DL,(DirType)3},
  1659. {0x008BFF10L,(DirType)4},
  1660. {0x0080FF14L,(DirType)5}, // Track entry here.
  1661. {0x0075FF18L,(DirType)8},
  1662. {0x006DFF1CL,(DirType)12},
  1663. {0x0063FF22L,(DirType)16},
  1664. {0x005AFF25L,(DirType)20},
  1665. {0x0052FF2BL,(DirType)23},
  1666. {0x0048FF32L,(DirType)27},
  1667. {0x0040FF37L,(DirType)32},
  1668. {0x0038FF3DL,(DirType)36},
  1669. {0x0030FF46L,(DirType)39},
  1670. {0x002BFF4FL,(DirType)43},
  1671. {0x0024FF58L,(DirType)47},
  1672. {0x0020FF60L,(DirType)51},
  1673. {0x001BFF6DL,(DirType)54},
  1674. {0x0017FF79L,(DirType)57},
  1675. {0x0014FF82L,(DirType)60}, // Track jump here.
  1676. {0x0011FF8FL,(DirType)62},
  1677. {0x000DFF98L,(DirType)63},
  1678. {0x0009FFA2L,(DirType)64},
  1679. {0x0006FFACL,(DirType)64},
  1680. {0x0004FFB5L,(DirType)66},
  1681. {0x0003FFC0L,(DirType)64},
  1682. {0x0002FFCBL,(DirType)64},
  1683. {0x0001FFD5L,(DirType)64},
  1684. {0x0000FFE0L,(DirType)64},
  1685. {0x0000FFEBL,(DirType)64},
  1686. {0x0000FFF5L,(DirType)64},
  1687. {0x00000000L,(DirType)64}
  1688. };
  1689. DriveClass::TrackType const DriveClass::Track5[] = {
  1690. {0xFFF8FE08L,(DirType)32},
  1691. {0xFFF0FE10L,(DirType)32},
  1692. {0xFFE8FE18L,(DirType)32},
  1693. {0xFFE0FE20L,(DirType)32},
  1694. {0xFFD8FE28L,(DirType)32},
  1695. {0xFFD0FE30L,(DirType)32},
  1696. {0xFFC8FE38L,(DirType)32},
  1697. {0xFFC0FE40L,(DirType)32},
  1698. {0xFFB8FE48L,(DirType)32},
  1699. {0xFFB0FE50L,(DirType)32},
  1700. {0xFFA8FE58L,(DirType)32},
  1701. {0xFFA0FE60L,(DirType)32},
  1702. {0xFF98FE68L,(DirType)32},
  1703. {0xFF90FE70L,(DirType)32},
  1704. {0xFF88FE78L,(DirType)32},
  1705. {0xFF80FE80L,(DirType)32}, // Track entry here.
  1706. {0xFF78FE88L,(DirType)32},
  1707. {0xFF71FE90L,(DirType)32},
  1708. {0xFF6AFE97L,(DirType)32},
  1709. {0xFF62FE9FL,(DirType)32},
  1710. {0xFF5AFEA8L,(DirType)32},
  1711. {0xFF53FEB0L,(DirType)35},
  1712. {0xFF4BFEB7L,(DirType)38},
  1713. {0xFF44FEBEL,(DirType)41},
  1714. {0xFF3EFEC4L,(DirType)44},
  1715. {0xFF39FECEL,(DirType)47},
  1716. {0xFF34FED8L,(DirType)50},
  1717. {0xFF30FEE0L,(DirType)53},
  1718. {0xFF2DFEEBL,(DirType)56},
  1719. {0xFF2CFEF5L,(DirType)59},
  1720. {0xFF2BFF00L,(DirType)62},
  1721. {0xFF2CFF0BL,(DirType)66},
  1722. {0xFF2DFF15L,(DirType)69},
  1723. {0xFF30FF1FL,(DirType)72},
  1724. {0xFF34FF28L,(DirType)75},
  1725. {0xFF39FF30L,(DirType)78},
  1726. {0xFF3EFF3AL,(DirType)81},
  1727. {0xFF44FF44L,(DirType)84},
  1728. {0xFF4BFF4BL,(DirType)87},
  1729. {0xFF53FF50L,(DirType)90},
  1730. {0xFF5AFF58L,(DirType)93},
  1731. {0xFF62FF60L,(DirType)96},
  1732. {0xFF6AFF68L,(DirType)96},
  1733. {0xFF71FF70L,(DirType)96},
  1734. {0xFF78FF78L,(DirType)96},
  1735. {0xFF80FF80L,(DirType)96}, // Track jump check here.
  1736. {0xFF88FF88L,(DirType)96},
  1737. {0xFF90FF90L,(DirType)96},
  1738. {0xFF98FF98L,(DirType)96},
  1739. {0xFFA0FFA0L,(DirType)96},
  1740. {0xFFA8FFA8L,(DirType)96},
  1741. {0xFFB0FFB0L,(DirType)96},
  1742. {0xFFB8FFB8L,(DirType)96},
  1743. {0xFFC0FFC0L,(DirType)96},
  1744. {0xFFC8FFC8L,(DirType)96},
  1745. {0xFFD0FFD0L,(DirType)96},
  1746. {0xFFD8FFD8L,(DirType)96},
  1747. {0xFFE0FFE0L,(DirType)96},
  1748. {0xFFE8FFE8L,(DirType)96},
  1749. {0xFFF0FFF0L,(DirType)96},
  1750. {0xFFF8FFF8L,(DirType)96},
  1751. {0x00000000L,(DirType)96}
  1752. };
  1753. DriveClass::TrackType const DriveClass::Track6[] = {
  1754. {0x0100FE00L,(DirType)32},
  1755. {0x00F8FE08L,(DirType)32},
  1756. {0x00F0FE10L,(DirType)32},
  1757. {0x00E8FE18L,(DirType)32},
  1758. {0x00E0FE20L,(DirType)32},
  1759. {0x00D8FE28L,(DirType)32},
  1760. {0x00D0FE30L,(DirType)32},
  1761. {0x00C8FE38L,(DirType)32},
  1762. {0x00C0FE40L,(DirType)32},
  1763. {0x00B8FE48L,(DirType)32},
  1764. {0x00B0FE50L,(DirType)32},
  1765. {0x00A8FE58L,(DirType)32},
  1766. {0x00A0FE60L,(DirType)32},
  1767. {0x0098FE68L,(DirType)32},
  1768. {0x0090FE70L,(DirType)32},
  1769. {0x0088FE78L,(DirType)32},
  1770. {0x0080FE80L,(DirType)32}, // Jump entry point here.
  1771. {0x0078FE88L,(DirType)32},
  1772. {0x0070FE90L,(DirType)32},
  1773. {0x0068FE98L,(DirType)32},
  1774. {0x0060FEA0L,(DirType)32},
  1775. {0x0058FEA8L,(DirType)32},
  1776. {0x0055FEAEL,(DirType)32},
  1777. {0x004EFEB8L,(DirType)35},
  1778. {0x0048FEC0L,(DirType)37},
  1779. {0x0042FEC9L,(DirType)40},
  1780. {0x003BFED2L,(DirType)43},
  1781. {0x0037FEDAL,(DirType)45},
  1782. {0x0032FEE3L,(DirType)48},
  1783. {0x002BFEEBL,(DirType)51},
  1784. {0x0026FEF5L,(DirType)53},
  1785. {0x0022FEFEL,(DirType)56},
  1786. {0x001CFF08L,(DirType)59},
  1787. {0x0019FF12L,(DirType)61},
  1788. {0x0015FF1BL,(DirType)64},
  1789. {0x0011FF26L,(DirType)64},
  1790. {0x000EFF30L,(DirType)64},
  1791. {0x000BFF39L,(DirType)64},
  1792. {0x0009FF43L,(DirType)64},
  1793. {0x0007FF4EL,(DirType)64},
  1794. {0x0005FF57L,(DirType)64},
  1795. {0x0003FF62L,(DirType)64},
  1796. {0x0001FF6DL,(DirType)64},
  1797. {0x0000FF77L,(DirType)64},
  1798. {0x0000FF80L,(DirType)64}, // Track jump check here.
  1799. {0x0000FF8BL,(DirType)64},
  1800. {0x0000FF95L,(DirType)64},
  1801. {0x0000FFA0L,(DirType)64},
  1802. {0x0000FFABL,(DirType)64},
  1803. {0x0000FFB5L,(DirType)64},
  1804. {0x0000FFC0L,(DirType)64},
  1805. {0x0000FFCBL,(DirType)64},
  1806. {0x0000FFD5L,(DirType)64},
  1807. {0x0000FFE0L,(DirType)64},
  1808. {0x0000FFEBL,(DirType)64},
  1809. {0x0000FFF5L,(DirType)64},
  1810. {0x00000000L,(DirType)64}
  1811. };
  1812. DriveClass::TrackType const DriveClass::Track7[] = {
  1813. {0x0006FFFFL,(DirType)0},
  1814. {0x000CFFFEL,(DirType)4},
  1815. {0x0011FFFCL,(DirType)8},
  1816. {0x0018FFFAL,(DirType)12},
  1817. {0x001FFFF6L,(DirType)16},
  1818. {0x0024FFF3L,(DirType)19},
  1819. {0x002BFFF0L,(DirType)22},
  1820. {0x0030FFFDL,(DirType)23},
  1821. {0x0035FFEBL,(DirType)24},
  1822. {0x0038FFE8L,(DirType)25},
  1823. {0x003CFFE6L,(DirType)26},
  1824. {0x0040FFE3L,(DirType)27},
  1825. {0x0043FFE0L,(DirType)28},
  1826. {0x0046FFDDL,(DirType)29},
  1827. {0x0043FFDFL,(DirType)30},
  1828. {0x0040FFE1L,(DirType)30},
  1829. {0x003CFFE3L,(DirType)30},
  1830. {0x0038FFE5L,(DirType)30},
  1831. {0x0035FFE7L,(DirType)31},
  1832. {0x0030FFE9L,(DirType)31},
  1833. {0x002BFFEBL,(DirType)31},
  1834. {0x0024FFEDL,(DirType)31},
  1835. {0x001FFFF1L,(DirType)31},
  1836. {0x0018FFF4L,(DirType)32},
  1837. {0x0011FFF7L,(DirType)32},
  1838. {0x000CFFFAL,(DirType)32},
  1839. {0x0006FFFDL,(DirType)32},
  1840. {0x00000000L,(DirType)32}
  1841. };
  1842. DriveClass::TrackType const DriveClass::Track8[] = {
  1843. {0x0003FFFCL,(DirType)32},
  1844. {0x0006FFF7L,(DirType)36},
  1845. {0x000AFFF1L,(DirType)40},
  1846. {0x000CFFEBL,(DirType)44},
  1847. {0x000DFFE4L,(DirType)46},
  1848. {0x000EFFDCL,(DirType)48},
  1849. {0x000FFFD5L,(DirType)50},
  1850. {0x0010FFD0L,(DirType)52},
  1851. {0x0011FFC9L,(DirType)54},
  1852. {0x0012FFC2L,(DirType)56},
  1853. {0x0011FFC0L,(DirType)58},
  1854. {0x0010FFC2L,(DirType)60},
  1855. {0x000EFFC9L,(DirType)62},
  1856. {0x000CFFCFL,(DirType)64},
  1857. {0x000AFFD5L,(DirType)64},
  1858. {0x0008FFDAL,(DirType)64},
  1859. {0x0006FFE2L,(DirType)64},
  1860. {0x0004FFE9L,(DirType)64},
  1861. {0x0002FFEFL,(DirType)64},
  1862. {0x0001FFF5L,(DirType)64},
  1863. {0x0000FFF9L,(DirType)64},
  1864. {0x00000000L,(DirType)64}
  1865. };
  1866. DriveClass::TrackType const DriveClass::Track9[] = {
  1867. {0xFFF50002L,(DirType)0},
  1868. {0xFFEB0004L,(DirType)2},
  1869. {0xFFE00006L,(DirType)4},
  1870. {0xFFD50009L,(DirType)6},
  1871. {0xFFCE000CL,(DirType)9},
  1872. {0xFFC8000FL,(DirType)11},
  1873. {0xFFC00012L,(DirType)13},
  1874. {0xFFB80015L,(DirType)16},
  1875. {0xFFC00012L,(DirType)18},
  1876. {0xFFC8000EL,(DirType)20},
  1877. {0xFFCE000AL,(DirType)22},
  1878. {0xFFD50004L,(DirType)24},
  1879. {0xFFDE0000L,(DirType)26},
  1880. {0xFFE9FFF8L,(DirType)28},
  1881. {0xFFEEFFF2L,(DirType)30},
  1882. {0xFFF5FFEBL,(DirType)32},
  1883. {0xFFFDFFE1L,(DirType)34},
  1884. {0x0002FFD8L,(DirType)36},
  1885. {0x0007FFD2L,(DirType)39},
  1886. {0x000BFFCBL,(DirType)41},
  1887. {0x0010FFC5L,(DirType)43},
  1888. {0x0013FFBEL,(DirType)45},
  1889. {0x0015FFB7L,(DirType)48},
  1890. {0x0013FFBEL,(DirType)50},
  1891. {0x0011FFC5L,(DirType)52},
  1892. {0x000BFFCCL,(DirType)54},
  1893. {0x0008FFD4L,(DirType)56},
  1894. {0x0005FFDFL,(DirType)58},
  1895. {0x0003FFEBL,(DirType)62},
  1896. {0x0001FFF5L,(DirType)64},
  1897. {0x00000000L,(DirType)64}
  1898. };
  1899. DriveClass::TrackType const DriveClass::Track10[] = {
  1900. {0xFFF6000BL,(DirType)32},
  1901. {0xFFF00015L,(DirType)37},
  1902. {0xFFEB0020L,(DirType)42},
  1903. {0xFFE9002BL,(DirType)47},
  1904. {0xFFE50032L,(DirType)52},
  1905. {0xFFE30038L,(DirType)57},
  1906. {0xFFE00040L,(DirType)60},
  1907. {0xFFE20038L,(DirType)62},
  1908. {0xFFE40032L,(DirType)64},
  1909. {0xFFE5002AL,(DirType)68},
  1910. {0xFFE6001EL,(DirType)70},
  1911. {0xFFE70015L,(DirType)72},
  1912. {0xFFE8000BL,(DirType)74},
  1913. {0xFFE90000L,(DirType)76},
  1914. {0xFFE8FFF5L,(DirType)78},
  1915. {0xFFE7FFEBL,(DirType)80},
  1916. {0xFFE6FFE0L,(DirType)82},
  1917. {0xFFE5FFD5L,(DirType)84},
  1918. {0xFFE4FFCEL,(DirType)86},
  1919. {0xFFE2FFC5L,(DirType)88},
  1920. {0xFFE0FFC0L,(DirType)90},
  1921. {0xFFE3FFC5L,(DirType)92},
  1922. {0xFFE5FFCEL,(DirType)94},
  1923. {0xFFE9FFD5L,(DirType)95},
  1924. {0xFFEBFFE0L,(DirType)96},
  1925. {0xFFF0FFEBL,(DirType)96},
  1926. {0xFFF6FFF5L,(DirType)96},
  1927. {0x00000000L,(DirType)96}
  1928. };
  1929. DriveClass::TrackType const DriveClass::Track11[] = {
  1930. {0x01000000L,DIR_SW},
  1931. {0x00F30008L,DIR_SW},
  1932. {0x00E50010L,DIR_SW_X1},
  1933. {0x00D60018L,DIR_SW_X1},
  1934. {0x00C80020L,DIR_SW_X1},
  1935. {0x00B90028L,DIR_SW_X1},
  1936. {0x00AB0030L,DIR_SW_X2},
  1937. {0x009C0038L,DIR_SW_X2},
  1938. {0x008D0040L,DIR_SW_X2},
  1939. {0x007F0048L,DIR_SW_X2},
  1940. {0x00710050L,DIR_SW_X2},
  1941. {0x00640058L,DIR_SW_X2},
  1942. {0x00550060L,DIR_SW_X2},
  1943. {0x00000000L,DIR_SW_X2}
  1944. };
  1945. DriveClass::TrackType const DriveClass::Track12[] = {
  1946. {0xFF550060L,DIR_SW_X2},
  1947. {0xFF640058L,DIR_SW_X2},
  1948. {0xFF710050L,DIR_SW_X2},
  1949. {0xFF7F0048L,DIR_SW_X2},
  1950. {0xFF8D0040L,DIR_SW_X2},
  1951. {0xFF9C0038L,DIR_SW_X2},
  1952. {0xFFAB0030L,DIR_SW_X2},
  1953. {0xFFB90028L,DIR_SW_X1},
  1954. {0xFFC80020L,DIR_SW_X1},
  1955. {0xFFD60018L,DIR_SW_X1},
  1956. {0xFFE50010L,DIR_SW_X1},
  1957. {0xFFF30008L,DIR_SW},
  1958. {0x00000000L,DIR_SW}
  1959. };
  1960. #if(1)
  1961. /*
  1962. ** Drive out of weapon's factory.
  1963. */
  1964. DriveClass::TrackType const DriveClass::Track13[] = {
  1965. {XYP_COORD(0,-35),DIR_S},
  1966. {XYP_COORD(0,-34),DIR_S},
  1967. {XYP_COORD(0,-33),DIR_S},
  1968. {XYP_COORD(0,-32),DIR_S},
  1969. {XYP_COORD(0,-31),DIR_S},
  1970. {XYP_COORD(0,-30),DIR_S},
  1971. {XYP_COORD(0,-29),DIR_S},
  1972. {XYP_COORD(0,-28),DIR_S},
  1973. {XYP_COORD(0,-27),DIR_S},
  1974. {XYP_COORD(0,-26),DIR_S},
  1975. {XYP_COORD(0,-25),DIR_S},
  1976. {XYP_COORD(0,-24),DIR_S},
  1977. {XYP_COORD(0,-23),DIR_S},
  1978. {XYP_COORD(0,-22),DIR_S},
  1979. {XYP_COORD(0,-21),DIR_S},
  1980. {XYP_COORD(0,-20),DIR_S},
  1981. {XYP_COORD(0,-19),DIR_S},
  1982. {XYP_COORD(0,-18),DIR_S},
  1983. {XYP_COORD(0,-17),DIR_S},
  1984. {XYP_COORD(0,-16),DIR_S},
  1985. {XYP_COORD(0,-15),DIR_S},
  1986. {XYP_COORD(0,-14),DIR_S},
  1987. {XYP_COORD(0,-13),DIR_S},
  1988. {XYP_COORD(0,-12),DIR_S},
  1989. {XYP_COORD(0,-11),DIR_S},
  1990. {XYP_COORD(0,-10),DIR_S},
  1991. {XYP_COORD(0,-9),DIR_S},
  1992. {XYP_COORD(0,-8),DIR_S},
  1993. {XYP_COORD(0,-7),DIR_S},
  1994. {XYP_COORD(0,-6),DIR_S},
  1995. {XYP_COORD(0,-5),DIR_S},
  1996. {XYP_COORD(0,-4),DIR_S},
  1997. {XYP_COORD(0,-3),DIR_S},
  1998. {XYP_COORD(0,-2),DIR_S},
  1999. {XYP_COORD(0,-1),DIR_S},
  2000. {0x00000000L,DIR_S}
  2001. };
  2002. #else
  2003. /*
  2004. ** Drive out of weapon's factory.
  2005. */
  2006. DriveClass::TrackType const DriveClass::Track13[] = {
  2007. {XYP_COORD(10,-21),(DirType)(DIR_SW-10)},
  2008. {XYP_COORD(10,-21),(DirType)(DIR_SW-10)},
  2009. {XYP_COORD(10,-20),(DirType)(DIR_SW-10)},
  2010. {XYP_COORD(10,-20),(DirType)(DIR_SW-10)},
  2011. {XYP_COORD(9,-18),(DirType)(DIR_SW-10)},
  2012. {XYP_COORD(9,-18),(DirType)(DIR_SW-10)},
  2013. {XYP_COORD(9,-17),(DirType)(DIR_SW-10)},
  2014. {XYP_COORD(8,-16),(DirType)(DIR_SW-10)},
  2015. {XYP_COORD(8,-15),(DirType)(DIR_SW-10)},
  2016. {XYP_COORD(7,-14),(DirType)(DIR_SW-10)},
  2017. {XYP_COORD(7,-13),(DirType)(DIR_SW-10)},
  2018. {XYP_COORD(6,-12),(DirType)(DIR_SW-10)},
  2019. {XYP_COORD(6,-11),(DirType)(DIR_SW-10)},
  2020. {XYP_COORD(5,-10),(DirType)(DIR_SW-10)},
  2021. {XYP_COORD(5,-9),(DirType)(DIR_SW-10)},
  2022. {XYP_COORD(4,-8),(DirType)(DIR_SW-10)},
  2023. {XYP_COORD(4,-7),(DirType)(DIR_SW-10)},
  2024. {XYP_COORD(3,-6),(DirType)(DIR_SW-10)},
  2025. {XYP_COORD(3,-5),(DirType)(DIR_SW-9)},
  2026. {XYP_COORD(2,-4),(DirType)(DIR_SW-7)},
  2027. {XYP_COORD(2,-3),(DirType)(DIR_SW-5)},
  2028. {XYP_COORD(1,-2),(DirType)(DIR_SW-3)},
  2029. {XYP_COORD(1,-1),(DirType)(DIR_SW-1)},
  2030. {0x00000000L,DIR_SW}
  2031. };
  2032. #endif
  2033. /*
  2034. ** There are a limited basic number of tracks that a vehicle can follow. These
  2035. ** are they. Each track can be interpreted differently but this is controlled
  2036. ** by the TrackControl structure elaborated elsewhere.
  2037. */
  2038. DriveClass::RawTrackType const DriveClass::RawTracks[13] = {
  2039. {Track1, -1, 0, -1},
  2040. {Track2, -1, 0, -1},
  2041. {Track3, 37, 12, 22},
  2042. {Track4, 26, 11, 19},
  2043. {Track5, 45, 15, 31},
  2044. {Track6, 44, 16, 27},
  2045. {Track7, -1, 0, -1},
  2046. {Track8, -1, 0, -1},
  2047. {Track9, -1, 0, -1},
  2048. {Track10, -1, 0, -1},
  2049. {Track11, -1, 0, -1},
  2050. {Track12, -1, 0, -1},
  2051. {Track13, -1, 0, -1}
  2052. };
  2053. /***************************************************************************
  2054. ** Smooth turning control table. Given two directions in a path list, this
  2055. ** table determines which track to use and what modifying operations need
  2056. ** be performed on the track data.
  2057. */
  2058. DriveClass::TurnTrackType const DriveClass::TrackControl[67] = {
  2059. {1, 0, DIR_N, F_}, // 0-0
  2060. {3, 7, DIR_NE, F_D}, // 0-1 (raw chart)
  2061. {4, 9, DIR_E, F_D}, // 0-2 (raw chart)
  2062. {0, 0, DIR_SE, F_}, // 0-3 !
  2063. {0, 0, DIR_S, F_}, // 0-4 !
  2064. {0, 0, DIR_SW, F_}, // 0-5 !
  2065. {4, 9, DIR_W, (DriveClass::TrackControlType)(F_X|F_D)}, // 0-6
  2066. {3, 7, DIR_NW, (DriveClass::TrackControlType)(F_X|F_D)}, // 0-7
  2067. {6, 8, DIR_N, (DriveClass::TrackControlType)(F_T|F_X|F_Y|F_D)}, // 1-0
  2068. {2, 0, DIR_NE, F_}, // 1-1 (raw chart)
  2069. {6, 8, DIR_E, F_D}, // 1-2 (raw chart)
  2070. {5, 10, DIR_SE, F_D}, // 1-3 (raw chart)
  2071. {0, 0, DIR_S, F_}, // 1-4 !
  2072. {0, 0, DIR_SW, F_}, // 1-5 !
  2073. {0, 0, DIR_W, F_}, // 1-6 !
  2074. {5, 10, DIR_NW, (DriveClass::TrackControlType)(F_T|F_X|F_Y|F_D)}, // 1-7
  2075. {4, 9, DIR_N, (DriveClass::TrackControlType)(F_T|F_X|F_Y|F_D)}, // 2-0
  2076. {3, 7, DIR_NE, (DriveClass::TrackControlType)(F_T|F_X|F_Y|F_D)}, // 2-1
  2077. {1, 0, DIR_E, (DriveClass::TrackControlType)(F_T|F_X)}, // 2-2
  2078. {3, 7, DIR_SE, (DriveClass::TrackControlType)(F_T|F_X|F_D)}, // 2-3
  2079. {4, 9, DIR_S, (DriveClass::TrackControlType)(F_T|F_X|F_D)}, // 2-4
  2080. {0, 0, DIR_SW, F_}, // 2-5 !
  2081. {0, 0, DIR_W, F_}, // 2-6 !
  2082. {0, 0, DIR_NW, F_}, // 2-7 !
  2083. {0, 0, DIR_N, F_}, // 3-0 !
  2084. {5, 10, DIR_NE, (DriveClass::TrackControlType)(F_Y|F_D)}, // 3-1
  2085. {6, 8, DIR_E, (DriveClass::TrackControlType)(F_Y|F_D)}, // 3-2
  2086. {2, 0, DIR_SE, F_Y}, // 3-3
  2087. {6, 8, DIR_S, (DriveClass::TrackControlType)(F_T|F_X|F_D)}, // 3-4
  2088. {5, 10, DIR_SW, (DriveClass::TrackControlType)(F_T|F_X|F_D)}, // 3-5
  2089. {0, 0, DIR_W, F_}, // 3-6 !
  2090. {0, 0, DIR_NW, F_}, // 3-7 !
  2091. {0, 0, DIR_N, F_}, // 4-0 !
  2092. {0, 0, DIR_NE, F_}, // 4-1 !
  2093. {4, 9, DIR_E, (DriveClass::TrackControlType)(F_Y|F_D)}, // 4-2
  2094. {3, 7, DIR_SE, (DriveClass::TrackControlType)(F_Y|F_D)}, // 4-3
  2095. {1, 0, DIR_S, F_Y}, // 4-4
  2096. {3, 7, DIR_SW, (DriveClass::TrackControlType)(F_X|F_Y|F_D)}, // 4-5
  2097. {4, 9, DIR_W, (DriveClass::TrackControlType)(F_X|F_Y|F_D)}, // 4-6
  2098. {0, 0, DIR_NW, F_}, // 4-7 !
  2099. {0, 0, DIR_N, F_}, // 5-0 !
  2100. {0, 0, DIR_NE, F_}, // 5-1 !
  2101. {0, 0, DIR_E, F_}, // 5-2 !
  2102. {5, 10, DIR_SE, (DriveClass::TrackControlType)(F_T|F_D)}, // 5-3
  2103. {6, 8, DIR_S, (DriveClass::TrackControlType)(F_T|F_D)}, // 5-4
  2104. {2, 0, DIR_SW, F_T}, // 5-5
  2105. {6, 8, DIR_W, (DriveClass::TrackControlType)(F_X|F_Y|F_D)}, // 5-6
  2106. {5, 10, DIR_NW, (DriveClass::TrackControlType)(F_X|F_Y|F_D)}, // 5-7
  2107. {4, 9, DIR_N, (DriveClass::TrackControlType)(F_T|F_Y|F_D)}, // 6-0
  2108. {0, 0, DIR_NE, F_}, // 6-1 !
  2109. {0, 0, DIR_E, F_}, // 6-2 !
  2110. {0, 0, DIR_SE, F_}, // 6-3 !
  2111. {4, 9, DIR_S, (DriveClass::TrackControlType)(F_T|F_D)}, // 6-4
  2112. {3, 7, DIR_SW, (DriveClass::TrackControlType)(F_T|F_D)}, // 6-5
  2113. {1, 0, DIR_W, F_T}, // 6-6
  2114. {3, 7, DIR_NW, (DriveClass::TrackControlType)(F_T|F_Y|F_D)}, // 6-7
  2115. {6, 8, DIR_N, (DriveClass::TrackControlType)(F_T|F_Y|F_D)}, // 7-0
  2116. {5, 10, DIR_NE, (DriveClass::TrackControlType)(F_T|F_Y|F_D)}, // 7-1
  2117. {0, 0, DIR_E, F_}, // 7-2 !
  2118. {0, 0, DIR_SE, F_}, // 7-3 !
  2119. {0, 0, DIR_S, F_}, // 7-4 !
  2120. {5, 10, DIR_SW, (DriveClass::TrackControlType)(F_X|F_D)}, // 7-5
  2121. {6, 8, DIR_W, (DriveClass::TrackControlType)(F_X|F_D)}, // 7-6
  2122. {2, 0, DIR_NW, F_X}, // 7-7
  2123. {11, 11, DIR_SW, F_}, // Backup harvester into refinery.
  2124. {12, 12, DIR_SW_X2, F_}, // Drive back into refinery.
  2125. {13, 13, DIR_SW, F_} // Drive out of weapons factory.
  2126. };