FUELCEN.C 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329
  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
  12. */
  13. /*
  14. * $Source: f:/miner/source/main/rcs/fuelcen.c $
  15. * $Revision: 2.3 $
  16. * $Author: john $
  17. * $Date: 1995/03/21 14:38:40 $
  18. *
  19. * Functions for refueling centers.
  20. *
  21. * $Log: fuelcen.c $
  22. * Revision 2.3 1995/03/21 14:38:40 john
  23. * Ifdef'd out the NETWORK code.
  24. *
  25. * Revision 2.2 1995/03/06 15:23:09 john
  26. * New screen techniques.
  27. *
  28. * Revision 2.1 1995/02/27 13:13:26 john
  29. * Removed floating point.
  30. *
  31. * Revision 2.0 1995/02/27 11:27:20 john
  32. * New version 2.0, which has no anonymous unions, builds with
  33. * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
  34. *
  35. * Revision 1.159 1995/02/22 13:48:10 allender
  36. * remove anonymous unions in object structure
  37. *
  38. * Revision 1.158 1995/02/08 11:37:48 mike
  39. * Check for failures in call to obj_create.
  40. *
  41. * Revision 1.157 1995/02/07 20:39:39 mike
  42. * fix toasters in multiplayer
  43. *
  44. *
  45. * Revision 1.156 1995/02/02 18:40:10 john
  46. * Fixed bug with full screen cockpit flashing non-white.
  47. *
  48. * Revision 1.155 1995/01/28 15:27:22 yuan
  49. * Make sure fuelcen nums are valid.
  50. *
  51. * Revision 1.154 1995/01/03 14:26:23 rob
  52. * Better ifdef for robot centers.
  53. *
  54. * Revision 1.153 1995/01/03 11:27:49 rob
  55. * Added include of fuelcen.c
  56. *
  57. * Revision 1.152 1995/01/03 09:47:22 john
  58. * Some ifdef SHAREWARE lines.
  59. *
  60. * Revision 1.151 1995/01/02 21:02:07 rob
  61. * added matcen support for coop/multirobot.
  62. *
  63. * Revision 1.150 1994/12/15 18:31:22 mike
  64. * fix confusing precedence problems.
  65. *
  66. * Revision 1.149 1994/12/15 13:04:22 mike
  67. * Replace Players[Player_num].time_total references with GameTime.
  68. *
  69. * Revision 1.148 1994/12/15 03:05:18 matt
  70. * Added error checking for NULL return from object_create_explosion()
  71. *
  72. * Revision 1.147 1994/12/13 19:49:12 rob
  73. * Made the fuelcen noise quieter.
  74. *
  75. * Revision 1.146 1994/12/13 12:03:18 john
  76. * Made the warning sirens not start until after "desccruction
  77. * secquence activated voice".
  78. *
  79. * Revision 1.145 1994/12/12 17:18:30 mike
  80. * make warning siren louder.
  81. *
  82. * Revision 1.144 1994/12/11 23:18:04 john
  83. * Added -nomusic.
  84. * Added RealFrameTime.
  85. * Put in a pause when sound initialization error.
  86. * Made controlcen countdown and framerate use RealFrameTime.
  87. *
  88. * Revision 1.143 1994/12/11 14:10:16 mike
  89. * louder sounds.
  90. *
  91. * Revision 1.142 1994/12/06 11:33:19 yuan
  92. * Fixed bug with fueling when above 100.
  93. *
  94. * Revision 1.141 1994/12/05 23:37:14 matt
  95. * Took out calls to warning() function
  96. *
  97. * Revision 1.140 1994/12/05 23:19:18 yuan
  98. * Fixed fuel center refuelers..
  99. *
  100. * Revision 1.139 1994/12/03 12:48:12 mike
  101. * diminish rocking due to control center destruction.
  102. *
  103. * Revision 1.138 1994/12/02 23:30:32 mike
  104. * fix bumpiness after toasting control center.
  105. *
  106. * Revision 1.137 1994/12/02 22:48:14 mike
  107. * rock the ship after toasting the control center!
  108. *
  109. * Revision 1.136 1994/12/02 17:12:11 rob
  110. * Fixed countdown sounds.
  111. *
  112. * Revision 1.135 1994/11/29 20:59:43 rob
  113. * Don't run out of fuel in net games (don't want to sync it between machines)
  114. *
  115. * Revision 1.134 1994/11/29 19:10:57 john
  116. * Took out debugging mprintf.
  117. *
  118. * Revision 1.133 1994/11/29 13:19:40 john
  119. * Made voice for "destruction actived in t-"
  120. * be at 12.75 secs.
  121. *
  122. * Revision 1.132 1994/11/29 12:19:46 john
  123. * MAde the "Mine desctruction will commence"
  124. * voice play at 12.5 secs.
  125. *
  126. * Revision 1.131 1994/11/29 12:12:54 adam
  127. * *** empty log message ***
  128. *
  129. * Revision 1.130 1994/11/28 21:04:26 rob
  130. * Added code to cast noise when player refuels.
  131. *
  132. * Revision 1.129 1994/11/27 23:15:04 matt
  133. * Made changes for new mprintf calling convention
  134. *
  135. * Revision 1.128 1994/11/21 16:27:51 mike
  136. * debug code for morphing.
  137. *
  138. * Revision 1.127 1994/11/21 12:33:50 matt
  139. * For control center explosions, use small fireball, not pseudo-random vclip
  140. *
  141. * Revision 1.126 1994/11/20 22:12:15 mike
  142. * Fix bug in initializing materialization centers.
  143. *
  144. * Revision 1.125 1994/11/19 15:18:22 mike
  145. * rip out unused code and data.
  146. *
  147. * Revision 1.124 1994/11/08 12:18:59 mike
  148. * Initialize Fuelcen_seconds_left.
  149. *
  150. * Revision 1.123 1994/10/30 14:12:33 mike
  151. * rip out repair center stuff
  152. *
  153. * Revision 1.122 1994/10/28 14:42:45 john
  154. * Added sound volumes to all sound calls.
  155. *
  156. * Revision 1.121 1994/10/16 12:44:02 mike
  157. * Make time to exit mine after control center destruction diff level dependent.
  158. *
  159. * Revision 1.120 1994/10/09 22:03:26 mike
  160. * Adapt to new create_n_segment_path parameters.
  161. *
  162. * Revision 1.119 1994/10/06 14:52:42 mike
  163. * Remove last of ability to damage fuel centers.
  164. *
  165. * Revision 1.118 1994/10/06 14:08:45 matt
  166. * Made morph flash effect get orientation from segment
  167. *
  168. * Revision 1.117 1994/10/05 16:09:03 mike
  169. * Put debugging code into matcen/fuelcen synchronization problem.
  170. *
  171. * Revision 1.116 1994/10/04 15:32:41 john
  172. * Took out the old PLAY_SOUND??? code and replaced it
  173. * with direct calls into digi_link_??? so that all sounds
  174. * can be made 3d.
  175. *
  176. * Revision 1.115 1994/10/03 23:37:57 mike
  177. * Clean up this mess of confusion to the point where maybe matcens actually work.
  178. *
  179. * Revision 1.114 1994/10/03 13:34:40 matt
  180. * Added new (and hopefully better) game sequencing functions
  181. *
  182. * Revision 1.113 1994/09/30 14:41:57 matt
  183. * Fixed bug as per Mike's instructions
  184. *
  185. * Revision 1.112 1994/09/30 00:37:33 mike
  186. * Balance materialization centers.
  187. *
  188. * Revision 1.111 1994/09/28 23:12:52 matt
  189. * Macroized palette flash system
  190. *
  191. * Revision 1.110 1994/09/27 15:42:31 mike
  192. * Add names of Specials.
  193. *
  194. * Revision 1.109 1994/09/27 00:02:23 mike
  195. * Yet more materialization center stuff.
  196. *
  197. * Revision 1.108 1994/09/26 11:26:23 mike
  198. * Balance materialization centers.
  199. *
  200. * Revision 1.107 1994/09/25 23:40:47 matt
  201. * Changed the object load & save code to read/write the structure fields one
  202. * at a time (rather than the whole structure at once). This mean that the
  203. * object structure can be changed without breaking the load/save functions.
  204. * As a result of this change, the local_object data can be and has been
  205. * incorporated into the object array. Also, timeleft is now a property
  206. * of all objects, and the object structure has been otherwise cleaned up.
  207. *
  208. * Revision 1.106 1994/09/25 15:55:58 mike
  209. * Balance materialization centers, make them emit light, make them re-triggerable after awhile.
  210. *
  211. * Revision 1.105 1994/09/24 17:42:33 mike
  212. * Making materialization centers be activated by triggers and balancing them.
  213. *
  214. * Revision 1.104 1994/09/24 14:16:06 mike
  215. * Support new network constants.
  216. *
  217. * Revision 1.103 1994/09/20 19:14:40 john
  218. * Massaged the sound system; used a better formula for determining
  219. * which l/r balance, also, put in Mike's stuff that searches for a connection
  220. * between the 2 sounds' segments, stopping for closed doors, etc.
  221. *
  222. * Revision 1.102 1994/09/17 01:40:51 matt
  223. * Added status bar/sizable window mode, and in the process revamped the
  224. * whole cockpit mode system.
  225. *
  226. * Revision 1.101 1994/08/31 20:57:25 matt
  227. * Cleaned up endlevel/death code
  228. *
  229. * Revision 1.100 1994/08/30 17:54:20 mike
  230. * Slow down rate of creation of objects by materialization centers.
  231. *
  232. * Revision 1.99 1994/08/29 11:47:01 john
  233. * Added warning if no control centers in mine.
  234. *
  235. */
  236. #pragma off (unreferenced)
  237. static char rcsid[] = "$Id: fuelcen.c 2.3 1995/03/21 14:38:40 john Exp $";
  238. #pragma on (unreferenced)
  239. #include <stdio.h>
  240. #include <stdlib.h>
  241. #include <math.h>
  242. #include <string.h>
  243. #include "fuelcen.h"
  244. #include "gameseg.h"
  245. #include "game.h" // For FrameTime
  246. #include "error.h"
  247. #include "mono.h"
  248. #include "gauges.h"
  249. #include "vclip.h"
  250. #include "fireball.h"
  251. #include "robot.h"
  252. #include "wall.h"
  253. #include "sounds.h"
  254. #include "morph.h"
  255. #include "3d.h"
  256. #include "bm.h"
  257. #include "polyobj.h"
  258. #include "ai.h"
  259. #include "gamemine.h"
  260. #include "gamesave.h"
  261. #include "player.h"
  262. #include "collide.h"
  263. #include "laser.h"
  264. #include "network.h"
  265. #include "multi.h"
  266. #include "multibot.h"
  267. // The max number of fuel stations per mine.
  268. fix Fuelcen_refill_speed = i2f(1);
  269. fix Fuelcen_give_amount = i2f(25);
  270. fix Fuelcen_max_amount = i2f(100);
  271. // Every time a robot is created in the morphing code, it decreases capacity of the morpher
  272. // by this amount... when capacity gets to 0, no more morphers...
  273. fix EnergyToCreateOneRobot = i2f(1);
  274. int Fuelcen_control_center_destroyed = 0;
  275. int Fuelcen_seconds_left = 0;
  276. #define MATCEN_HP_DEFAULT F1_0*500; // Hitpoints
  277. #define MATCEN_INTERVAL_DEFAULT F1_0*5; // 5 seconds
  278. matcen_info RobotCenters[MAX_ROBOT_CENTERS];
  279. int Num_robot_centers;
  280. control_center_triggers ControlCenterTriggers;
  281. FuelCenter Station[MAX_NUM_FUELCENS];
  282. int Num_fuelcenters = 0;
  283. segment * PlayerSegment= NULL;
  284. #ifdef EDITOR
  285. char Special_names[MAX_CENTER_TYPES][11] = {
  286. "NOTHING ",
  287. "FUELCEN ",
  288. "REPAIRCEN ",
  289. "CONTROLCEN",
  290. "ROBOTMAKER",
  291. };
  292. #endif
  293. //------------------------------------------------------------
  294. // Resets all fuel center info
  295. void fuelcen_reset()
  296. {
  297. int i;
  298. Num_fuelcenters = 0;
  299. //mprintf( (0, "All fuel centers reset.\n"));
  300. for(i=0; i<MAX_SEGMENTS; i++ )
  301. Segments[i].special = SEGMENT_IS_NOTHING;
  302. Fuelcen_control_center_destroyed = 0;
  303. Num_robot_centers = 0;
  304. }
  305. #ifndef NDEBUG //this is sometimes called by people from the debugger
  306. void reset_all_robot_centers()
  307. {
  308. int i;
  309. // Remove all materialization centers
  310. for (i=0; i<Num_segments; i++)
  311. if (Segments[i].special == SEGMENT_IS_ROBOTMAKER) {
  312. Segments[i].special = SEGMENT_IS_NOTHING;
  313. Segments[i].matcen_num = -1;
  314. }
  315. }
  316. #endif
  317. //------------------------------------------------------------
  318. // Turns a segment into a fully charged up fuel center...
  319. void fuelcen_create( segment * segp)
  320. {
  321. int station_type;
  322. station_type = segp->special;
  323. switch( station_type ) {
  324. case SEGMENT_IS_NOTHING:
  325. return;
  326. case SEGMENT_IS_FUELCEN:
  327. case SEGMENT_IS_REPAIRCEN:
  328. case SEGMENT_IS_CONTROLCEN:
  329. case SEGMENT_IS_ROBOTMAKER:
  330. break;
  331. default:
  332. Error( "Invalid station type %d in fuelcen.c\n", station_type );
  333. }
  334. Assert( (segp != NULL) );
  335. if ( segp == NULL ) return;
  336. Assert( Num_fuelcenters < MAX_NUM_FUELCENS );
  337. Assert( Num_fuelcenters > -1 );
  338. segp->value = Num_fuelcenters;
  339. Station[Num_fuelcenters].Type = station_type;
  340. Station[Num_fuelcenters].MaxCapacity = Fuelcen_max_amount;
  341. Station[Num_fuelcenters].Capacity = Station[Num_fuelcenters].MaxCapacity;
  342. Station[Num_fuelcenters].segnum = segp-Segments;
  343. Station[Num_fuelcenters].Timer = -1;
  344. Station[Num_fuelcenters].Flag = 0;
  345. // Station[Num_fuelcenters].NextRobotType = -1;
  346. // Station[Num_fuelcenters].last_created_obj=NULL;
  347. // Station[Num_fuelcenters].last_created_sig = -1;
  348. compute_segment_center(&Station[Num_fuelcenters].Center, segp );
  349. // if (station_type == SEGMENT_IS_ROBOTMAKER)
  350. // Station[Num_fuelcenters].Capacity = i2f(Difficulty_level + 3);
  351. //mprintf( (0, "Segment %d is assigned to be fuel center %d.\n", Station[Num_fuelcenters].segnum, Num_fuelcenters ));
  352. Num_fuelcenters++;
  353. }
  354. //------------------------------------------------------------
  355. // Adds a matcen that already is a special type into the Station array.
  356. // This function is separate from other fuelcens because we don't want values reset.
  357. void matcen_create( segment * segp)
  358. {
  359. int station_type = segp->special;
  360. Assert( (segp != NULL) );
  361. Assert(station_type == SEGMENT_IS_ROBOTMAKER);
  362. if ( segp == NULL ) return;
  363. Assert( Num_fuelcenters < MAX_NUM_FUELCENS );
  364. Assert( Num_fuelcenters > -1 );
  365. segp->value = Num_fuelcenters;
  366. Station[Num_fuelcenters].Type = station_type;
  367. Station[Num_fuelcenters].Capacity = i2f(Difficulty_level + 3);
  368. Station[Num_fuelcenters].MaxCapacity = Station[Num_fuelcenters].Capacity;
  369. Station[Num_fuelcenters].segnum = segp-Segments;
  370. Station[Num_fuelcenters].Timer = -1;
  371. Station[Num_fuelcenters].Flag = 0;
  372. // Station[Num_fuelcenters].NextRobotType = -1;
  373. // Station[Num_fuelcenters].last_created_obj=NULL;
  374. // Station[Num_fuelcenters].last_created_sig = -1;
  375. compute_segment_center(&Station[Num_fuelcenters].Center, segp );
  376. segp->matcen_num = Num_robot_centers;
  377. Num_robot_centers++;
  378. RobotCenters[segp->matcen_num].hit_points = MATCEN_HP_DEFAULT;
  379. RobotCenters[segp->matcen_num].interval = MATCEN_INTERVAL_DEFAULT;
  380. RobotCenters[segp->matcen_num].segnum = segp-Segments;
  381. RobotCenters[segp->matcen_num].fuelcen_num = Num_fuelcenters;
  382. //mprintf( (0, "Segment %d is assigned to be fuel center %d.\n", Station[Num_fuelcenters].segnum, Num_fuelcenters ));
  383. Num_fuelcenters++;
  384. }
  385. //------------------------------------------------------------
  386. // Adds a segment that already is a special type into the Station array.
  387. void fuelcen_activate( segment * segp, int station_type )
  388. {
  389. segp->special = station_type;
  390. if (segp->special == SEGMENT_IS_ROBOTMAKER)
  391. matcen_create( segp);
  392. else
  393. fuelcen_create( segp);
  394. }
  395. // The lower this number is, the more quickly the center can be re-triggered.
  396. // If it's too low, it can mean all the robots won't be put out, but for about 5
  397. // robots, that's not real likely.
  398. #define MATCEN_LIFE (i2f(30-2*Difficulty_level))
  399. //------------------------------------------------------------
  400. // Trigger (enable) the materialization center in segment segnum
  401. void trigger_matcen(int segnum)
  402. {
  403. segment *segp = &Segments[segnum];
  404. vms_vector pos, delta;
  405. FuelCenter *robotcen;
  406. int objnum;
  407. mprintf((0, "Trigger matcen, segment %i\n", segnum));
  408. Assert(segp->special == SEGMENT_IS_ROBOTMAKER);
  409. Assert(segp->matcen_num < Num_fuelcenters);
  410. Assert((segp->matcen_num >= 0) && (segp->matcen_num <= Highest_segment_index));
  411. robotcen = &Station[RobotCenters[segp->matcen_num].fuelcen_num];
  412. if (robotcen->Enabled == 1)
  413. return;
  414. if (!robotcen->Lives)
  415. return;
  416. robotcen->Lives--;
  417. robotcen->Timer = F1_0*1000; // Make sure the first robot gets emitted right away.
  418. robotcen->Enabled = 1; // Say this center is enabled, it can create robots.
  419. robotcen->Capacity = i2f(Difficulty_level + 3);
  420. robotcen->Disable_time = MATCEN_LIFE;
  421. // Create a bright object in the segment.
  422. pos = robotcen->Center;
  423. vm_vec_sub(&delta, &Vertices[Segments[segnum].verts[0]], &robotcen->Center);
  424. vm_vec_scale_add2(&pos, &delta, F1_0/2);
  425. objnum = obj_create( OBJ_LIGHT, 0, segnum, &pos, NULL, 0, CT_LIGHT, MT_NONE, RT_NONE );
  426. if (objnum != -1) {
  427. Objects[objnum].lifeleft = MATCEN_LIFE;
  428. Objects[objnum].ctype.light_info.intensity = i2f(8); // Light cast by a fuelcen.
  429. } else {
  430. mprintf((1, "Can't create invisible flare for matcen.\n"));
  431. Int3();
  432. }
  433. // mprintf((0, "Created invisibile flare, object=%i, segment=%i, pos=%7.3f %7.3f%7.3f\n", objnum, segnum, f2fl(pos.x), f2fl(pos.y), f2fl(pos.z)));
  434. }
  435. #ifdef EDITOR
  436. //------------------------------------------------------------
  437. // Takes away a segment's fuel center properties.
  438. // Deletes the segment point entry in the FuelCenter list.
  439. void fuelcen_delete( segment * segp )
  440. {
  441. int i, j;
  442. Restart: ;
  443. for (i=0; i<Num_fuelcenters; i++ ) {
  444. if ( Station[i].segnum == segp-Segments ) {
  445. // If Robot maker is deleted, fix Segments and RobotCenters.
  446. if (Station[i].Type == SEGMENT_IS_ROBOTMAKER) {
  447. Num_robot_centers--;
  448. for (j=segp->matcen_num; j<Num_robot_centers; j++)
  449. RobotCenters[j] = RobotCenters[j+1];
  450. for (j=0; j<Num_fuelcenters; j++) {
  451. if ( Station[j].Type == SEGMENT_IS_ROBOTMAKER )
  452. if ( Segments[Station[j].segnum].matcen_num > segp->matcen_num )
  453. Segments[Station[j].segnum].matcen_num--;
  454. }
  455. }
  456. Num_fuelcenters--;
  457. for (j=i; j<Num_fuelcenters; j++ ) {
  458. Station[i] = Station[i+1];
  459. Segments[Station[i].segnum].value = i;
  460. }
  461. segp->special = 0;
  462. goto Restart;
  463. }
  464. }
  465. }
  466. #endif
  467. #define ROBOT_GEN_TIME (i2f(5))
  468. object * create_morph_robot( segment *segp, vms_vector *object_pos, int object_id)
  469. {
  470. short objnum;
  471. object *obj;
  472. int default_behavior;
  473. Players[Player_num].num_robots_level++;
  474. Players[Player_num].num_robots_total++;
  475. objnum = obj_create(OBJ_ROBOT, object_id, segp-Segments, object_pos,
  476. &vmd_identity_matrix, Polygon_models[Robot_info[object_id].model_num].rad,
  477. CT_AI, MT_PHYSICS, RT_POLYOBJ);
  478. if ( objnum < 0 ) {
  479. mprintf((1, "Can't create morph robot. Aborting morph.\n"));
  480. Int3();
  481. return NULL;
  482. }
  483. obj = &Objects[objnum];
  484. //Set polygon-object-specific data
  485. obj->rtype.pobj_info.model_num = Robot_info[obj->id].model_num;
  486. obj->rtype.pobj_info.subobj_flags = 0;
  487. //set Physics info
  488. obj->mtype.phys_info.mass = Robot_info[obj->id].mass;
  489. obj->mtype.phys_info.drag = Robot_info[obj->id].drag;
  490. obj->mtype.phys_info.flags |= (PF_LEVELLING);
  491. obj->shields = Robot_info[obj->id].strength;
  492. default_behavior = AIB_NORMAL;
  493. if (object_id == 10) // This is a toaster guy!
  494. default_behavior = AIB_RUN_FROM;
  495. init_ai_object(obj-Objects, default_behavior, -1 ); // Note, -1 = segment this robot goes to to hide, should probably be something useful
  496. create_n_segment_path(obj, 6, -1); // Create a 6 segment path from creation point.
  497. if (default_behavior == AIB_RUN_FROM)
  498. Ai_local_info[objnum].mode = AIM_RUN_FROM_OBJECT;
  499. return obj;
  500. }
  501. int Num_extry_robots = 15;
  502. #ifndef NDEBUG
  503. int FrameCount_last_msg = 0;
  504. #endif
  505. // ----------------------------------------------------------------------------------------------------------
  506. void robotmaker_proc( FuelCenter * robotcen )
  507. {
  508. fix dist_to_player;
  509. vms_vector cur_object_loc; //, direction;
  510. int matcen_num, segnum, objnum;
  511. object *obj;
  512. fix top_time;
  513. vms_vector direction;
  514. if (robotcen->Enabled == 0)
  515. return;
  516. if (robotcen->Disable_time > 0) {
  517. robotcen->Disable_time -= FrameTime;
  518. if (robotcen->Disable_time <= 0) {
  519. mprintf((0, "Robot center #%i gets disabled due to time running out.\n", robotcen-Station));
  520. robotcen->Enabled = 0;
  521. }
  522. }
  523. // mprintf((0, "Capacity of robot maker #%i is %i\n", robotcen - Station, robotcen->Capacity));
  524. // No robot making in multiplayer mode.
  525. #ifdef NETWORK
  526. #ifndef SHAREWARE
  527. if ((Game_mode & GM_MULTI) && (!(Game_mode & GM_MULTI_ROBOTS) || !network_i_am_master()))
  528. return;
  529. #else
  530. if (Game_mode & GM_MULTI)
  531. return;
  532. #endif
  533. #endif
  534. // Wait until transmorgafier has capacity to make a robot...
  535. if ( robotcen->Capacity <= 0 ) {
  536. return;
  537. }
  538. matcen_num = Segments[robotcen->segnum].matcen_num;
  539. //mprintf((0, "Robotmaker #%i flags = %8x\n", matcen_num, RobotCenters[matcen_num].robot_flags));
  540. if ( matcen_num == -1 ) {
  541. mprintf((0, "Non-functional robotcen at %d\n", robotcen->segnum));
  542. return;
  543. }
  544. if (RobotCenters[matcen_num].robot_flags == 0) {
  545. //mprintf((0, "robot_flags = 0 at robot maker #%i\n", RobotCenters[matcen_num].robot_flags));
  546. return;
  547. }
  548. // Wait until we have a free slot for this puppy...
  549. // <<<<<<<<<<<<<<<< Num robots in mine >>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<< Max robots in mine >>>>>>>>>>>>>>>
  550. if ( (Players[Player_num].num_robots_level - Players[Player_num].num_kills_level) >= (Gamesave_num_org_robots + Num_extry_robots ) ) {
  551. #ifndef NDEBUG
  552. if (FrameCount > FrameCount_last_msg + 20) {
  553. mprintf((0, "Cannot morph until you kill one!\n"));
  554. FrameCount_last_msg = FrameCount;
  555. }
  556. #endif
  557. return;
  558. }
  559. robotcen->Timer += FrameTime;
  560. switch( robotcen->Flag ) {
  561. case 0: // Wait until next robot can generate
  562. if (Game_mode & GM_MULTI)
  563. {
  564. top_time = ROBOT_GEN_TIME;
  565. }
  566. else
  567. {
  568. dist_to_player = vm_vec_dist_quick( &ConsoleObject->pos, &robotcen->Center );
  569. top_time = dist_to_player/64 + rand() * 2 + F1_0*2;
  570. if ( top_time > ROBOT_GEN_TIME )
  571. top_time = ROBOT_GEN_TIME + rand();
  572. if ( top_time < F1_0*2 )
  573. top_time = F1_0*3/2 + rand()*2;
  574. }
  575. // mprintf( (0, "Time between morphs %d seconds, dist_to_player = %7.3f\n", f2i(top_time), f2fl(dist_to_player) ));
  576. if (robotcen->Timer > top_time ) {
  577. int count=0;
  578. int i, my_station_num = robotcen-Station;
  579. object *obj;
  580. // Make sure this robotmaker hasn't put out its max without having any of them killed.
  581. for (i=0; i<=Highest_object_index; i++)
  582. if (Objects[i].type == OBJ_ROBOT)
  583. if ((Objects[i].matcen_creator^0x80) == my_station_num)
  584. count++;
  585. if (count > Difficulty_level + 3) {
  586. mprintf((0, "Cannot morph: center %i has already put out %i robots.\n", my_station_num, count));
  587. robotcen->Timer /= 2;
  588. return;
  589. }
  590. // Whack on any robot or player in the matcen segment.
  591. count=0;
  592. segnum = robotcen->segnum;
  593. for (objnum=Segments[segnum].objects;objnum!=-1;objnum=Objects[objnum].next) {
  594. count++;
  595. if ( count > MAX_OBJECTS ) {
  596. mprintf((0, "Object list in segment %d is circular.", segnum ));
  597. Int3();
  598. return;
  599. }
  600. if (Objects[objnum].type==OBJ_ROBOT) {
  601. collide_robot_and_materialization_center(&Objects[objnum]);
  602. robotcen->Timer = top_time/2;
  603. return;
  604. } else if (Objects[objnum].type==OBJ_PLAYER ) {
  605. collide_player_and_materialization_center(&Objects[objnum]);
  606. robotcen->Timer = top_time/2;
  607. return;
  608. }
  609. }
  610. compute_segment_center(&cur_object_loc, &Segments[robotcen->segnum]);
  611. // HACK!!! The 10 under here should be something equal to the 1/2 the size of the segment.
  612. obj = object_create_explosion(robotcen->segnum, &cur_object_loc, i2f(10), VCLIP_MORPHING_ROBOT );
  613. if (obj)
  614. extract_orient_from_segment(&obj->orient,&Segments[robotcen->segnum]);
  615. if ( Vclip[VCLIP_MORPHING_ROBOT].sound_num > -1 ) {
  616. digi_link_sound_to_pos( Vclip[VCLIP_MORPHING_ROBOT].sound_num, robotcen->segnum, 0, &cur_object_loc, 0, F1_0 );
  617. }
  618. robotcen->Flag = 1;
  619. robotcen->Timer = 0;
  620. }
  621. break;
  622. case 1: // Wait until 1/2 second after VCLIP started.
  623. if (robotcen->Timer > (Vclip[VCLIP_MORPHING_ROBOT].play_time/2) ) {
  624. robotcen->Capacity -= EnergyToCreateOneRobot;
  625. robotcen->Flag = 0;
  626. robotcen->Timer = 0;
  627. compute_segment_center(&cur_object_loc, &Segments[robotcen->segnum]);
  628. // If this is the first materialization, set to valid robot.
  629. if (RobotCenters[matcen_num].robot_flags != 0) {
  630. int type;
  631. uint flags;
  632. byte legal_types[32]; // 32 bits in a word, the width of robot_flags.
  633. int num_types, robot_index;
  634. robot_index = 0;
  635. num_types = 0;
  636. flags = RobotCenters[matcen_num].robot_flags;
  637. while (flags) {
  638. if (flags & 1)
  639. legal_types[num_types++] = robot_index;
  640. flags >>= 1;
  641. robot_index++;
  642. }
  643. //mprintf((0, "Flags = %08x, %2i legal types to morph: \n", RobotCenters[matcen_num].robot_flags, num_types));
  644. //for (i=0; i<num_types; i++)
  645. // mprintf((0, "%2i ", legal_types[i]));
  646. //mprintf((0, "\n"));
  647. if (num_types == 1)
  648. type = legal_types[0];
  649. else
  650. type = legal_types[(rand() * num_types) / 32768];
  651. mprintf((0, "Morph: (type = %i) (seg = %i) (capacity = %08x)\n", type, robotcen->segnum, robotcen->Capacity));
  652. obj = create_morph_robot(&Segments[robotcen->segnum], &cur_object_loc, type );
  653. if (obj != NULL) {
  654. #ifndef SHAREWARE
  655. #ifdef NETWORK
  656. if (Game_mode & GM_MULTI)
  657. multi_send_create_robot(robotcen-Station, obj-Objects, type);
  658. #endif
  659. #endif
  660. obj->matcen_creator = robotcen-Station | 0x80;
  661. // Make object faces player...
  662. vm_vec_sub( &direction, &ConsoleObject->pos,&obj->pos );
  663. vm_vector_2_matrix( &obj->orient, &direction, &obj->orient.uvec, NULL);
  664. morph_start( obj );
  665. //robotcen->last_created_obj = obj;
  666. //robotcen->last_created_sig = robotcen->last_created_obj->signature;
  667. } else
  668. mprintf((0, "Warning: create_morph_robot returned NULL (no objects left?)\n"));
  669. }
  670. }
  671. break;
  672. default:
  673. robotcen->Flag = 0;
  674. robotcen->Timer = 0;
  675. }
  676. }
  677. #define BASE_CONTROL_CENTER_EXPLOSION_TIME 30
  678. #define DIFF_CONTROL_CENTER_EXPLOSION_TIME (BASE_CONTROL_CENTER_EXPLOSION_TIME + (NDL-Difficulty_level-1)*5)
  679. #define COUNTDOWN_VOICE_TIME (i2f(DIFF_CONTROL_CENTER_EXPLOSION_TIME)-fl2f(12.75))
  680. void controlcen_proc( FuelCenter * controlcen )
  681. {
  682. fix old_time;
  683. int fc;
  684. // mprintf( (0, "CCT: %.1f\n", f2fl(controlcen->Timer)));
  685. if (!Fuelcen_control_center_destroyed) return;
  686. // Control center destroyed, rock the player's ship.
  687. fc = Fuelcen_seconds_left;
  688. if (fc > 16)
  689. fc = 16;
  690. ConsoleObject->mtype.phys_info.rotvel.x += fixmul(rand() - 16384, 3*F1_0/16 + (F1_0*(16-fc))/32);
  691. ConsoleObject->mtype.phys_info.rotvel.z += fixmul(rand() - 16384, 3*F1_0/16 + (F1_0*(16-fc))/32);
  692. // Hook in the rumble sound effect here.
  693. old_time = controlcen->Timer;
  694. controlcen->Timer += RealFrameTime; //timer_get_approx_seconds
  695. Fuelcen_seconds_left = DIFF_CONTROL_CENTER_EXPLOSION_TIME - f2i(controlcen->Timer);
  696. if ( (old_time < COUNTDOWN_VOICE_TIME ) && (controlcen->Timer >= COUNTDOWN_VOICE_TIME) ) {
  697. digi_play_sample( SOUND_COUNTDOWN_13_SECS, F3_0 );
  698. }
  699. if ( f2i(old_time) != f2i(controlcen->Timer) ) {
  700. if ( (Fuelcen_seconds_left>=0) && (Fuelcen_seconds_left<10) )
  701. digi_play_sample( SOUND_COUNTDOWN_0_SECS+Fuelcen_seconds_left, F3_0 );
  702. if ( Fuelcen_seconds_left==DIFF_CONTROL_CENTER_EXPLOSION_TIME-1)
  703. digi_play_sample( SOUND_COUNTDOWN_29_SECS, F3_0 );
  704. }
  705. if (controlcen->Timer < i2f(DIFF_CONTROL_CENTER_EXPLOSION_TIME)) {
  706. vms_vector vp; //,v,c;
  707. fix size;
  708. compute_segment_center(&vp, &Segments[controlcen->segnum]);
  709. size = (0x50000*f2i(controlcen->Timer)*(FrameTime & 0xF))/16;
  710. size = controlcen->Timer / (fl2f(0.65));
  711. old_time = old_time / (fl2f(0.65));
  712. if (size != old_time && (controlcen->Timer > (5*F1_0) )) { // Every 2 seconds!
  713. //@@object_create_explosion( controlcen->segnum, &vp, size*10, FrameTime & 7);
  714. object_create_explosion( controlcen->segnum, &vp, size*10, VCLIP_SMALL_EXPLOSION);
  715. digi_play_sample( SOUND_CONTROL_CENTER_WARNING_SIREN, F3_0 );
  716. }
  717. } else {
  718. int flash_value;
  719. if (old_time < i2f(DIFF_CONTROL_CENTER_EXPLOSION_TIME))
  720. digi_play_sample( SOUND_MINE_BLEW_UP, F1_0 );
  721. flash_value = f2i( (controlcen->Timer-i2f(DIFF_CONTROL_CENTER_EXPLOSION_TIME))*(64/4)); // 4 seconds to total whiteness
  722. PALETTE_FLASH_SET(flash_value,flash_value,flash_value);
  723. //gauge_message( "YOU'RE TOO SLOW! THE MINE BLEW UP!" );
  724. if (PaletteBlueAdd > 64 ) {
  725. gr_set_current_canvas( NULL );
  726. gr_clear_canvas(BM_XRGB(31,31,31)); //make screen all white to match palette effect
  727. reset_cockpit(); //force cockpit redraw next time
  728. reset_palette_add(); //restore palette for death message
  729. controlcen->Timer = -1;
  730. controlcen->MaxCapacity = Fuelcen_max_amount;
  731. //gauge_message( "Control Center Reset" );
  732. DoPlayerDead(); //kill_player();
  733. }
  734. }
  735. }
  736. #define M_PI 3.14159
  737. //-------------------------------------------------------------
  738. // Called once per frame, replenishes fuel supply.
  739. void fuelcen_update_all()
  740. {
  741. int i;
  742. fix AmountToreplenish;
  743. AmountToreplenish = fixmul(FrameTime,Fuelcen_refill_speed);
  744. for (i=0; i<Num_fuelcenters; i++ ) {
  745. if ( Station[i].Type == SEGMENT_IS_ROBOTMAKER ) {
  746. if (! (Game_suspended & SUSP_ROBOTS))
  747. robotmaker_proc( &Station[i] );
  748. } else if ( Station[i].Type == SEGMENT_IS_CONTROLCEN ) {
  749. controlcen_proc( &Station[i] );
  750. } else if ( (Station[i].MaxCapacity > 0) && (PlayerSegment!=&Segments[Station[i].segnum]) ) {
  751. if ( Station[i].Capacity < Station[i].MaxCapacity ) {
  752. Station[i].Capacity += AmountToreplenish;
  753. //mprintf( (0, "Fuel center %d replenished to %d.\n", i, f2i(Station[i].Capacity) ));
  754. if ( Station[i].Capacity >= Station[i].MaxCapacity ) {
  755. Station[i].Capacity = Station[i].MaxCapacity;
  756. //gauge_message( "Fuel center is fully recharged! " );
  757. }
  758. }
  759. }
  760. }
  761. }
  762. //--unused-- //-------------------------------------------------------------
  763. //--unused-- // replenishes all fuel supplies.
  764. //--unused-- void fuelcen_replenish_all()
  765. //--unused-- {
  766. //--unused-- int i;
  767. //--unused--
  768. //--unused-- for (i=0; i<Num_fuelcenters; i++ ) {
  769. //--unused-- Station[i].Capacity = Station[i].MaxCapacity;
  770. //--unused-- }
  771. //--unused-- //mprintf( (0, "All fuel centers are replenished\n" ));
  772. //--unused--
  773. //--unused-- }
  774. //-------------------------------------------------------------
  775. fix fuelcen_give_fuel(segment *segp, fix MaxAmountCanTake )
  776. {
  777. Assert( segp != NULL );
  778. PlayerSegment = segp;
  779. if ( (segp) && (segp->special==SEGMENT_IS_FUELCEN) ) {
  780. fix amount;
  781. // if (Station[segp->value].MaxCapacity<=0) {
  782. // HUD_init_message( "Fuelcenter %d is destroyed.", segp->value );
  783. // return 0;
  784. // }
  785. // if (Station[segp->value].Capacity<=0) {
  786. // HUD_init_message( "Fuelcenter %d is empty.", segp->value );
  787. // return 0;
  788. // }
  789. if (MaxAmountCanTake <= 0 ) {
  790. // //gauge_message( "Fueled up!");
  791. return 0;
  792. }
  793. amount = fixmul(FrameTime,Fuelcen_give_amount);
  794. if (amount > MaxAmountCanTake )
  795. amount = MaxAmountCanTake;
  796. // if (!(Game_mode & GM_MULTI))
  797. // if ( Station[segp->value].Capacity < amount ) {
  798. // amount = Station[segp->value].Capacity;
  799. // Station[segp->value].Capacity = 0;
  800. // } else {
  801. // Station[segp->value].Capacity -= amount;
  802. // }
  803. digi_play_sample( SOUND_REFUEL_STATION_GIVING_FUEL, F1_0/2 );
  804. #ifdef NETWORK
  805. if (Game_mode & GM_MULTI)
  806. multi_send_play_sound(SOUND_REFUEL_STATION_GIVING_FUEL, F1_0/2);
  807. #endif
  808. //HUD_init_message( "Fuelcen %d has %d/%d fuel", segp->value,f2i(Station[segp->value].Capacity),f2i(Station[segp->value].MaxCapacity) );
  809. return amount;
  810. } else {
  811. return 0;
  812. }
  813. }
  814. //--unused-- //-----------------------------------------------------------
  815. //--unused-- // Damages a fuel center
  816. //--unused-- void fuelcen_damage(segment *segp, fix damage )
  817. //--unused-- {
  818. //--unused-- //int i;
  819. //--unused-- // int station_num = segp->value;
  820. //--unused--
  821. //--unused-- Assert( segp != NULL );
  822. //--unused-- if ( segp == NULL ) return;
  823. //--unused--
  824. //--unused-- mprintf((0, "Obsolete function fuelcen_damage() called with seg=%i, damage=%7.3f\n", segp-Segments, f2fl(damage)));
  825. //--unused-- switch( segp->special ) {
  826. //--unused-- case SEGMENT_IS_NOTHING:
  827. //--unused-- return;
  828. //--unused-- case SEGMENT_IS_ROBOTMAKER:
  829. //--unused-- //-- // Robotmaker hit by laser
  830. //--unused-- //-- if (Station[station_num].MaxCapacity<=0 ) {
  831. //--unused-- //-- // Shooting a already destroyed materializer
  832. //--unused-- //-- } else {
  833. //--unused-- //-- Station[station_num].MaxCapacity -= damage;
  834. //--unused-- //-- if (Station[station_num].Capacity > Station[station_num].MaxCapacity ) {
  835. //--unused-- //-- Station[station_num].Capacity = Station[station_num].MaxCapacity;
  836. //--unused-- //-- }
  837. //--unused-- //-- if (Station[station_num].MaxCapacity <= 0 ) {
  838. //--unused-- //-- Station[station_num].MaxCapacity = 0;
  839. //--unused-- //-- // Robotmaker dead
  840. //--unused-- //-- for (i=0; i<6; i++ )
  841. //--unused-- //-- segp->sides[i].tmap_num2 = 0;
  842. //--unused-- //-- }
  843. //--unused-- //-- }
  844. //--unused-- //-- //mprintf( (0, "Materializatormografier has %x capacity left\n", Station[station_num].MaxCapacity ));
  845. //--unused-- break;
  846. //--unused-- case SEGMENT_IS_FUELCEN:
  847. //--unused-- //-- digi_play_sample( SOUND_REFUEL_STATION_HIT );
  848. //--unused-- //-- if (Station[station_num].MaxCapacity>0 ) {
  849. //--unused-- //-- Station[station_num].MaxCapacity -= damage;
  850. //--unused-- //-- if (Station[station_num].Capacity > Station[station_num].MaxCapacity ) {
  851. //--unused-- //-- Station[station_num].Capacity = Station[station_num].MaxCapacity;
  852. //--unused-- //-- }
  853. //--unused-- //-- if (Station[station_num].MaxCapacity <= 0 ) {
  854. //--unused-- //-- Station[station_num].MaxCapacity = 0;
  855. //--unused-- //-- digi_play_sample( SOUND_REFUEL_STATION_DESTROYED );
  856. //--unused-- //-- }
  857. //--unused-- //-- } else {
  858. //--unused-- //-- Station[station_num].MaxCapacity = 0;
  859. //--unused-- //-- }
  860. //--unused-- //-- HUD_init_message( "Fuelcenter %d damaged", station_num );
  861. //--unused-- break;
  862. //--unused-- case SEGMENT_IS_REPAIRCEN:
  863. //--unused-- break;
  864. //--unused-- case SEGMENT_IS_CONTROLCEN:
  865. //--unused-- break;
  866. //--unused-- default:
  867. //--unused-- Error( "Invalid type in fuelcen.c" );
  868. //--unused-- }
  869. //--unused-- }
  870. //--unused-- // ----------------------------------------------------------------------------------------------------------
  871. //--unused-- fixang my_delta_ang(fixang a,fixang b)
  872. //--unused-- {
  873. //--unused-- fixang delta0,delta1;
  874. //--unused--
  875. //--unused-- return (abs(delta0 = a - b) < abs(delta1 = b - a)) ? delta0 : delta1;
  876. //--unused--
  877. //--unused-- }
  878. //--unused-- // ----------------------------------------------------------------------------------------------------------
  879. //--unused-- //return though which side of seg0 is seg1
  880. //--unused-- int john_find_connect_side(int seg0,int seg1)
  881. //--unused-- {
  882. //--unused-- segment *Seg=&Segments[seg0];
  883. //--unused-- int i;
  884. //--unused--
  885. //--unused-- for (i=MAX_SIDES_PER_SEGMENT;i--;) if (Seg->children[i]==seg1) return i;
  886. //--unused--
  887. //--unused-- return -1;
  888. //--unused-- }
  889. // ----------------------------------------------------------------------------------------------------------
  890. //--unused-- vms_angvec start_angles, delta_angles, goal_angles;
  891. //--unused-- vms_vector start_pos, delta_pos, goal_pos;
  892. //--unused-- int FuelStationSeg;
  893. //--unused-- fix current_time,delta_time;
  894. //--unused-- int next_side, side_index;
  895. //--unused-- int * sidelist;
  896. //--repair-- int Repairing;
  897. //--repair-- vms_vector repair_save_uvec; //the player's upvec when enter repaircen
  898. //--repair-- object *RepairObj=NULL; //which object getting repaired
  899. //--repair-- int disable_repair_center=0;
  900. //--repair-- fix repair_rate;
  901. //--repair-- #define FULL_REPAIR_RATE i2f(10)
  902. //--unused-- ubyte save_control_type,save_movement_type;
  903. //--unused-- int SideOrderBack[] = {WFRONT, WRIGHT, WTOP, WLEFT, WBOTTOM, WBACK};
  904. //--unused-- int SideOrderFront[] = {WBACK, WLEFT, WTOP, WRIGHT, WBOTTOM, WFRONT};
  905. //--unused-- int SideOrderLeft[] = { WRIGHT, WBACK, WTOP, WFRONT, WBOTTOM, WLEFT };
  906. //--unused-- int SideOrderRight[] = { WLEFT, WFRONT, WTOP, WBACK, WBOTTOM, WRIGHT };
  907. //--unused-- int SideOrderTop[] = { WBOTTOM, WLEFT, WBACK, WRIGHT, WFRONT, WTOP };
  908. //--unused-- int SideOrderBottom[] = { WTOP, WLEFT, WFRONT, WRIGHT, WBACK, WBOTTOM };
  909. //--unused-- int SideUpVector[] = {WBOTTOM, WFRONT, WBOTTOM, WFRONT, WBOTTOM, WBOTTOM };
  910. //--repair-- // ----------------------------------------------------------------------------------------------------------
  911. //--repair-- void refuel_calc_deltas(object *obj, int next_side, int repair_seg)
  912. //--repair-- {
  913. //--repair-- vms_vector nextcenter, headfvec, *headuvec;
  914. //--repair-- vms_matrix goal_orient;
  915. //--repair--
  916. //--repair-- // Find time for this movement
  917. //--repair-- delta_time = F1_0; // one second...
  918. //--repair--
  919. //--repair-- // Find start and goal position
  920. //--repair-- start_pos = obj->pos;
  921. //--repair--
  922. //--repair-- // Find delta position to get to goal position
  923. //--repair-- compute_segment_center(&goal_pos,&Segments[repair_seg]);
  924. //--repair-- vm_vec_sub( &delta_pos,&goal_pos,&start_pos);
  925. //--repair--
  926. //--repair-- // Find start angles
  927. //--repair-- //angles_from_vector(&start_angles,&obj->orient.fvec);
  928. //--repair-- vm_extract_angles_matrix(&start_angles,&obj->orient);
  929. //--repair--
  930. //--repair-- // Find delta angles to get to goal orientation
  931. //--repair-- med_compute_center_point_on_side(&nextcenter,&Segments[repair_seg],next_side);
  932. //--repair-- vm_vec_sub(&headfvec,&nextcenter,&goal_pos);
  933. //--repair-- //mprintf( (0, "Next_side = %d, Head fvec = %d,%d,%d\n", next_side, headfvec.x, headfvec.y, headfvec.z ));
  934. //--repair--
  935. //--repair-- if (next_side == 5) //last side
  936. //--repair-- headuvec = &repair_save_uvec;
  937. //--repair-- else
  938. //--repair-- headuvec = &Segments[repair_seg].sides[SideUpVector[next_side]].normals[0];
  939. //--repair--
  940. //--repair-- vm_vector_2_matrix(&goal_orient,&headfvec,headuvec,NULL);
  941. //--repair-- vm_extract_angles_matrix(&goal_angles,&goal_orient);
  942. //--repair-- delta_angles.p = my_delta_ang(start_angles.p,goal_angles.p);
  943. //--repair-- delta_angles.b = my_delta_ang(start_angles.b,goal_angles.b);
  944. //--repair-- delta_angles.h = my_delta_ang(start_angles.h,goal_angles.h);
  945. //--repair-- current_time = 0;
  946. //--repair-- Repairing = 0;
  947. //--repair-- }
  948. //--repair--
  949. //--repair-- // ----------------------------------------------------------------------------------------------------------
  950. //--repair-- //if repairing, cut it short
  951. //--repair-- abort_repair_center()
  952. //--repair-- {
  953. //--repair-- if (!RepairObj || side_index==5)
  954. //--repair-- return;
  955. //--repair--
  956. //--repair-- current_time = 0;
  957. //--repair-- side_index = 5;
  958. //--repair-- next_side = sidelist[side_index];
  959. //--repair-- refuel_calc_deltas(RepairObj, next_side, FuelStationSeg);
  960. //--repair-- }
  961. //--repair--
  962. //--repair-- // ----------------------------------------------------------------------------------------------------------
  963. //--repair-- void repair_ship_damage()
  964. //--repair-- {
  965. //--repair-- //mprintf((0,"Repairing ship damage\n"));
  966. //--repair-- }
  967. //--repair--
  968. //--repair-- // ----------------------------------------------------------------------------------------------------------
  969. //--repair-- int refuel_do_repair_effect( object * obj, int first_time, int repair_seg ) {
  970. //--repair--
  971. //--repair-- obj->mtype.phys_info.velocity.x = 0;
  972. //--repair-- obj->mtype.phys_info.velocity.y = 0;
  973. //--repair-- obj->mtype.phys_info.velocity.z = 0;
  974. //--repair--
  975. //--repair-- if (first_time) {
  976. //--repair-- int entry_side;
  977. //--repair-- current_time = 0;
  978. //--repair--
  979. //--repair-- digi_play_sample( SOUND_REPAIR_STATION_PLAYER_ENTERING, F1_0 );
  980. //--repair--
  981. //--repair-- entry_side = john_find_connect_side(repair_seg,obj->segnum );
  982. //--repair-- Assert( entry_side > -1 );
  983. //--repair--
  984. //--repair-- switch( entry_side ) {
  985. //--repair-- case WBACK: sidelist = SideOrderBack; break;
  986. //--repair-- case WFRONT: sidelist = SideOrderFront; break;
  987. //--repair-- case WLEFT: sidelist = SideOrderLeft; break;
  988. //--repair-- case WRIGHT: sidelist = SideOrderRight; break;
  989. //--repair-- case WTOP: sidelist = SideOrderTop; break;
  990. //--repair-- case WBOTTOM: sidelist = SideOrderBottom; break;
  991. //--repair-- }
  992. //--repair-- side_index = 0;
  993. //--repair-- next_side = sidelist[side_index];
  994. //--repair--
  995. //--repair-- refuel_calc_deltas(obj,next_side, repair_seg);
  996. //--repair-- }
  997. //--repair--
  998. //--repair-- //update shields
  999. //--repair-- if (Players[Player_num].shields < MAX_SHIELDS) { //if above max, don't mess with it
  1000. //--repair--
  1001. //--repair-- Players[Player_num].shields += fixmul(FrameTime,repair_rate);
  1002. //--repair--
  1003. //--repair-- if (Players[Player_num].shields > MAX_SHIELDS)
  1004. //--repair-- Players[Player_num].shields = MAX_SHIELDS;
  1005. //--repair-- }
  1006. //--repair--
  1007. //--repair-- current_time += FrameTime;
  1008. //--repair--
  1009. //--repair-- if (current_time >= delta_time ) {
  1010. //--repair-- vms_angvec av;
  1011. //--repair-- obj->pos = goal_pos;
  1012. //--repair-- av = goal_angles;
  1013. //--repair-- vm_angles_2_matrix(&obj->orient,&av);
  1014. //--repair--
  1015. //--repair-- if (side_index >= 5 )
  1016. //--repair-- return 1; // Done being repaired...
  1017. //--repair--
  1018. //--repair-- if (Repairing==0) {
  1019. //--repair-- //mprintf( (0, "<MACHINE EFFECT ON SIDE %d>\n", next_side ));
  1020. //--repair-- //digi_play_sample( SOUND_REPAIR_STATION_FIXING );
  1021. //--repair-- Repairing=1;
  1022. //--repair--
  1023. //--repair-- switch( next_side ) {
  1024. //--repair-- case 0: digi_play_sample( SOUND_REPAIR_STATION_FIXING_1,F1_0 ); break;
  1025. //--repair-- case 1: digi_play_sample( SOUND_REPAIR_STATION_FIXING_2,F1_0 ); break;
  1026. //--repair-- case 2: digi_play_sample( SOUND_REPAIR_STATION_FIXING_3,F1_0 ); break;
  1027. //--repair-- case 3: digi_play_sample( SOUND_REPAIR_STATION_FIXING_4,F1_0 ); break;
  1028. //--repair-- case 4: digi_play_sample( SOUND_REPAIR_STATION_FIXING_1,F1_0 ); break;
  1029. //--repair-- case 5: digi_play_sample( SOUND_REPAIR_STATION_FIXING_2,F1_0 ); break;
  1030. //--repair-- }
  1031. //--repair--
  1032. //--repair-- repair_ship_damage();
  1033. //--repair--
  1034. //--repair-- }
  1035. //--repair--
  1036. //--repair-- if (current_time >= (delta_time+(F1_0/2)) ) {
  1037. //--repair-- current_time = 0;
  1038. //--repair-- // Find next side...
  1039. //--repair-- side_index++;
  1040. //--repair-- if (side_index >= 6 ) return 1;
  1041. //--repair-- next_side = sidelist[side_index];
  1042. //--repair--
  1043. //--repair-- refuel_calc_deltas(obj, next_side, repair_seg);
  1044. //--repair-- }
  1045. //--repair--
  1046. //--repair-- } else {
  1047. //--repair-- fix factor, p,b,h;
  1048. //--repair-- vms_angvec av;
  1049. //--repair--
  1050. //--repair-- factor = fixdiv( current_time,delta_time );
  1051. //--repair--
  1052. //--repair-- // Find object's current position
  1053. //--repair-- obj->pos = delta_pos;
  1054. //--repair-- vm_vec_scale( &obj->pos, factor );
  1055. //--repair-- vm_vec_add2( &obj->pos, &start_pos );
  1056. //--repair--
  1057. //--repair-- // Find object's current orientation
  1058. //--repair-- p = fixmul(delta_angles.p,factor);
  1059. //--repair-- b = fixmul(delta_angles.b,factor);
  1060. //--repair-- h = fixmul(delta_angles.h,factor);
  1061. //--repair-- av.p = (fixang)p + start_angles.p;
  1062. //--repair-- av.b = (fixang)b + start_angles.b;
  1063. //--repair-- av.h = (fixang)h + start_angles.h;
  1064. //--repair-- vm_angles_2_matrix(&obj->orient,&av);
  1065. //--repair--
  1066. //--repair-- }
  1067. //--repair--
  1068. //--repair-- update_object_seg(obj); //update segment
  1069. //--repair--
  1070. //--repair-- return 0;
  1071. //--repair-- }
  1072. //--repair--
  1073. //--repair-- // ----------------------------------------------------------------------------------------------------------
  1074. //--repair-- //do the repair center for this frame
  1075. //--repair-- void do_repair_sequence(object *obj)
  1076. //--repair-- {
  1077. //--repair-- Assert(obj == RepairObj);
  1078. //--repair--
  1079. //--repair-- if (refuel_do_repair_effect( obj, 0, FuelStationSeg )) {
  1080. //--repair-- if (Players[Player_num].shields < MAX_SHIELDS)
  1081. //--repair-- Players[Player_num].shields = MAX_SHIELDS;
  1082. //--repair-- obj->control_type = save_control_type;
  1083. //--repair-- obj->movement_type = save_movement_type;
  1084. //--repair-- disable_repair_center=1;
  1085. //--repair-- RepairObj = NULL;
  1086. //--repair--
  1087. //--repair--
  1088. //--repair-- //the two lines below will spit the player out of the rapair center,
  1089. //--repair-- //but what happen is that the ship just bangs into the door
  1090. //--repair-- //if (obj->movement_type == MT_PHYSICS)
  1091. //--repair-- // vm_vec_copy_scale(&obj->mtype.phys_info.velocity,&obj->orient.fvec,i2f(200));
  1092. //--repair-- }
  1093. //--repair--
  1094. //--repair-- }
  1095. //--repair--
  1096. //--repair-- // ----------------------------------------------------------------------------------------------------------
  1097. //--repair-- //see if we should start the repair center
  1098. //--repair-- void check_start_repair_center(object *obj)
  1099. //--repair-- {
  1100. //--repair-- if (RepairObj != NULL) return; //already in repair center
  1101. //--repair--
  1102. //--repair-- if (Lsegments[obj->segnum].special_type & SS_REPAIR_CENTER) {
  1103. //--repair--
  1104. //--repair-- if (!disable_repair_center) {
  1105. //--repair-- //have just entered repair center
  1106. //--repair--
  1107. //--repair-- RepairObj = obj;
  1108. //--repair-- repair_save_uvec = obj->orient.uvec;
  1109. //--repair--
  1110. //--repair-- repair_rate = fixmuldiv(FULL_REPAIR_RATE,(MAX_SHIELDS - Players[Player_num].shields),MAX_SHIELDS);
  1111. //--repair--
  1112. //--repair-- save_control_type = obj->control_type;
  1113. //--repair-- save_movement_type = obj->movement_type;
  1114. //--repair--
  1115. //--repair-- obj->control_type = CT_REPAIRCEN;
  1116. //--repair-- obj->movement_type = MT_NONE;
  1117. //--repair--
  1118. //--repair-- FuelStationSeg = Lsegments[obj->segnum].special_segment;
  1119. //--repair-- Assert(FuelStationSeg != -1);
  1120. //--repair--
  1121. //--repair-- if (refuel_do_repair_effect( obj, 1, FuelStationSeg )) {
  1122. //--repair-- Int3(); //can this happen?
  1123. //--repair-- obj->control_type = CT_FLYING;
  1124. //--repair-- obj->movement_type = MT_PHYSICS;
  1125. //--repair-- }
  1126. //--repair-- }
  1127. //--repair-- }
  1128. //--repair-- else
  1129. //--repair-- disable_repair_center=0;
  1130. //--repair--
  1131. //--repair-- }
  1132. // --------------------------------------------------------------------------------------------
  1133. void disable_matcens(void)
  1134. {
  1135. int i;
  1136. for (i=0; i<Num_robot_centers; i++) {
  1137. Station[i].Enabled = 0;
  1138. Station[i].Disable_time = 0;
  1139. }
  1140. }
  1141. // --------------------------------------------------------------------------------------------
  1142. // Initialize all materialization centers.
  1143. // Give them all the right number of lives.
  1144. void init_all_matcens(void)
  1145. {
  1146. int i;
  1147. for (i=0; i<Num_fuelcenters; i++)
  1148. if (Station[i].Type == SEGMENT_IS_ROBOTMAKER) {
  1149. Station[i].Lives = 3;
  1150. Station[i].Enabled = 0;
  1151. Station[i].Disable_time = 0;
  1152. #ifndef NDEBUG
  1153. {
  1154. // Make sure this fuelcen is pointed at by a matcen.
  1155. int j;
  1156. for (j=0; j<Num_robot_centers; j++) {
  1157. if (RobotCenters[j].fuelcen_num == i)
  1158. break;
  1159. }
  1160. Assert(j != Num_robot_centers);
  1161. }
  1162. #endif
  1163. }
  1164. #ifndef NDEBUG
  1165. // Make sure all matcens point at a fuelcen
  1166. for (i=0; i<Num_robot_centers; i++) {
  1167. int fuelcen_num = RobotCenters[i].fuelcen_num;
  1168. Assert(fuelcen_num < Num_fuelcenters);
  1169. Assert(Station[fuelcen_num].Type == SEGMENT_IS_ROBOTMAKER);
  1170. }
  1171. #endif
  1172. }
  1173.