1 /* $Id: fuelcen.c,v 1.9 2004-05-15 17:16:34 schaffner Exp $ */
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
17 * Functions for refueling centers.
20 * Revision 1.2 1995/10/31 10:23:40 allender
23 * Revision 1.1 1995/05/16 15:24:50 allender
26 * Revision 2.3 1995/03/21 14:38:40 john
27 * Ifdef'd out the NETWORK code.
29 * Revision 2.2 1995/03/06 15:23:09 john
30 * New screen techniques.
32 * Revision 2.1 1995/02/27 13:13:26 john
33 * Removed floating point.
35 * Revision 2.0 1995/02/27 11:27:20 john
36 * New version 2.0, which has no anonymous unions, builds with
37 * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
39 * Revision 1.159 1995/02/22 13:48:10 allender
40 * remove anonymous unions in object structure
42 * Revision 1.158 1995/02/08 11:37:48 mike
43 * Check for failures in call to obj_create.
45 * Revision 1.157 1995/02/07 20:39:39 mike
46 * fix toasters in multiplayer
49 * Revision 1.156 1995/02/02 18:40:10 john
50 * Fixed bug with full screen cockpit flashing non-white.
52 * Revision 1.155 1995/01/28 15:27:22 yuan
53 * Make sure fuelcen nums are valid.
55 * Revision 1.154 1995/01/03 14:26:23 rob
56 * Better ifdef for robot centers.
58 * Revision 1.153 1995/01/03 11:27:49 rob
59 * Added include of fuelcen.c
61 * Revision 1.152 1995/01/03 09:47:22 john
62 * Some ifdef SHAREWARE lines.
64 * Revision 1.151 1995/01/02 21:02:07 rob
65 * added matcen support for coop/multirobot.
67 * Revision 1.150 1994/12/15 18:31:22 mike
68 * fix confusing precedence problems.
70 * Revision 1.149 1994/12/15 13:04:22 mike
71 * Replace Players[Player_num].time_total references with GameTime.
73 * Revision 1.148 1994/12/15 03:05:18 matt
74 * Added error checking for NULL return from object_create_explosion()
76 * Revision 1.147 1994/12/13 19:49:12 rob
77 * Made the fuelcen noise quieter.
79 * Revision 1.146 1994/12/13 12:03:18 john
80 * Made the warning sirens not start until after "desccruction
81 * secquence activated voice".
83 * Revision 1.145 1994/12/12 17:18:30 mike
84 * make warning siren louder.
86 * Revision 1.144 1994/12/11 23:18:04 john
88 * Added RealFrameTime.
89 * Put in a pause when sound initialization error.
90 * Made controlcen countdown and framerate use RealFrameTime.
92 * Revision 1.143 1994/12/11 14:10:16 mike
95 * Revision 1.142 1994/12/06 11:33:19 yuan
96 * Fixed bug with fueling when above 100.
98 * Revision 1.141 1994/12/05 23:37:14 matt
99 * Took out calls to warning() function
101 * Revision 1.140 1994/12/05 23:19:18 yuan
102 * Fixed fuel center refuelers..
104 * Revision 1.139 1994/12/03 12:48:12 mike
105 * diminish rocking due to control center destruction.
107 * Revision 1.138 1994/12/02 23:30:32 mike
108 * fix bumpiness after toasting control center.
110 * Revision 1.137 1994/12/02 22:48:14 mike
111 * rock the ship after toasting the control center!
113 * Revision 1.136 1994/12/02 17:12:11 rob
114 * Fixed countdown sounds.
116 * Revision 1.135 1994/11/29 20:59:43 rob
117 * Don't run out of fuel in net games (don't want to sync it between machines)
119 * Revision 1.134 1994/11/29 19:10:57 john
120 * Took out debugging mprintf.
122 * Revision 1.133 1994/11/29 13:19:40 john
123 * Made voice for "destruction actived in t-"
126 * Revision 1.132 1994/11/29 12:19:46 john
127 * MAde the "Mine desctruction will commence"
128 * voice play at 12.5 secs.
130 * Revision 1.131 1994/11/29 12:12:54 adam
131 * *** empty log message ***
133 * Revision 1.130 1994/11/28 21:04:26 rob
134 * Added code to cast noise when player refuels.
136 * Revision 1.129 1994/11/27 23:15:04 matt
137 * Made changes for new mprintf calling convention
139 * Revision 1.128 1994/11/21 16:27:51 mike
140 * debug code for morphing.
142 * Revision 1.127 1994/11/21 12:33:50 matt
143 * For control center explosions, use small fireball, not pseudo-random vclip
145 * Revision 1.126 1994/11/20 22:12:15 mike
146 * Fix bug in initializing materialization centers.
148 * Revision 1.125 1994/11/19 15:18:22 mike
149 * rip out unused code and data.
151 * Revision 1.124 1994/11/08 12:18:59 mike
152 * Initialize Fuelcen_seconds_left.
154 * Revision 1.123 1994/10/30 14:12:33 mike
155 * rip out repair center stuff
157 * Revision 1.122 1994/10/28 14:42:45 john
158 * Added sound volumes to all sound calls.
160 * Revision 1.121 1994/10/16 12:44:02 mike
161 * Make time to exit mine after control center destruction diff level dependent.
163 * Revision 1.120 1994/10/09 22:03:26 mike
164 * Adapt to new create_n_segment_path parameters.
166 * Revision 1.119 1994/10/06 14:52:42 mike
167 * Remove last of ability to damage fuel centers.
169 * Revision 1.118 1994/10/06 14:08:45 matt
170 * Made morph flash effect get orientation from segment
172 * Revision 1.117 1994/10/05 16:09:03 mike
173 * Put debugging code into matcen/fuelcen synchronization problem.
175 * Revision 1.116 1994/10/04 15:32:41 john
176 * Took out the old PLAY_SOUND??? code and replaced it
177 * with direct calls into digi_link_??? so that all sounds
180 * Revision 1.115 1994/10/03 23:37:57 mike
181 * Clean up this mess of confusion to the point where maybe matcens actually work.
183 * Revision 1.114 1994/10/03 13:34:40 matt
184 * Added new (and hopefully better) game sequencing functions
186 * Revision 1.113 1994/09/30 14:41:57 matt
187 * Fixed bug as per Mike's instructions
189 * Revision 1.112 1994/09/30 00:37:33 mike
190 * Balance materialization centers.
192 * Revision 1.111 1994/09/28 23:12:52 matt
193 * Macroized palette flash system
195 * Revision 1.110 1994/09/27 15:42:31 mike
196 * Add names of Specials.
198 * Revision 1.109 1994/09/27 00:02:23 mike
199 * Yet more materialization center stuff.
201 * Revision 1.108 1994/09/26 11:26:23 mike
202 * Balance materialization centers.
204 * Revision 1.107 1994/09/25 23:40:47 matt
205 * Changed the object load & save code to read/write the structure fields one
206 * at a time (rather than the whole structure at once). This mean that the
207 * object structure can be changed without breaking the load/save functions.
208 * As a result of this change, the local_object data can be and has been
209 * incorporated into the object array. Also, timeleft is now a property
210 * of all objects, and the object structure has been otherwise cleaned up.
212 * Revision 1.106 1994/09/25 15:55:58 mike
213 * Balance materialization centers, make them emit light, make them re-triggerable after awhile.
215 * Revision 1.105 1994/09/24 17:42:33 mike
216 * Making materialization centers be activated by triggers and balancing them.
218 * Revision 1.104 1994/09/24 14:16:06 mike
219 * Support new network constants.
221 * Revision 1.103 1994/09/20 19:14:40 john
222 * Massaged the sound system; used a better formula for determining
223 * which l/r balance, also, put in Mike's stuff that searches for a connection
224 * between the 2 sounds' segments, stopping for closed doors, etc.
226 * Revision 1.102 1994/09/17 01:40:51 matt
227 * Added status bar/sizable window mode, and in the process revamped the
228 * whole cockpit mode system.
230 * Revision 1.101 1994/08/31 20:57:25 matt
231 * Cleaned up endlevel/death code
233 * Revision 1.100 1994/08/30 17:54:20 mike
234 * Slow down rate of creation of objects by materialization centers.
236 * Revision 1.99 1994/08/29 11:47:01 john
237 * Added warning if no control centers in mine.
246 static char rcsid[] = "$Id: fuelcen.c,v 1.9 2004-05-15 17:16:34 schaffner Exp $";
256 #include "game.h" // For FrameTime
261 #include "fireball.h"
272 #include "gamemine.h"
273 #include "gamesave.h"
281 #include "multibot.h"
284 // The max number of fuel stations per mine.
286 fix Fuelcen_refill_speed = i2f(1);
287 fix Fuelcen_give_amount = i2f(25);
288 fix Fuelcen_max_amount = i2f(100);
290 // Every time a robot is created in the morphing code, it decreases capacity of the morpher
291 // by this amount... when capacity gets to 0, no more morphers...
292 fix EnergyToCreateOneRobot = i2f(1);
294 #define MATCEN_HP_DEFAULT F1_0*500; // Hitpoints
295 #define MATCEN_INTERVAL_DEFAULT F1_0*5; // 5 seconds
297 matcen_info RobotCenters[MAX_ROBOT_CENTERS];
298 int Num_robot_centers;
300 FuelCenter Station[MAX_NUM_FUELCENS];
301 int Num_fuelcenters = 0;
303 segment * PlayerSegment= NULL;
306 char Special_names[MAX_CENTER_TYPES][11] = {
317 //------------------------------------------------------------
318 // Resets all fuel center info
324 //mprintf( (0, "All fuel centers reset.\n"));
326 for(i=0; i<MAX_SEGMENTS; i++ )
327 Segment2s[i].special = SEGMENT_IS_NOTHING;
329 Num_robot_centers = 0;
333 #ifndef NDEBUG //this is sometimes called by people from the debugger
334 void reset_all_robot_centers()
338 // Remove all materialization centers
339 for (i=0; i<Num_segments; i++)
340 if (Segment2s[i].special == SEGMENT_IS_ROBOTMAKER) {
341 Segment2s[i].special = SEGMENT_IS_NOTHING;
342 Segment2s[i].matcen_num = -1;
347 //------------------------------------------------------------
348 // Turns a segment into a fully charged up fuel center...
349 void fuelcen_create( segment *segp)
351 segment2 *seg2p = &Segment2s[segp-Segments];
355 station_type = seg2p->special;
357 switch( station_type ) {
358 case SEGMENT_IS_NOTHING:
359 case SEGMENT_IS_GOAL_BLUE:
360 case SEGMENT_IS_GOAL_RED:
362 case SEGMENT_IS_FUELCEN:
363 case SEGMENT_IS_REPAIRCEN:
364 case SEGMENT_IS_CONTROLCEN:
365 case SEGMENT_IS_ROBOTMAKER:
368 Error( "Invalid station type %d in fuelcen.c\n", station_type );
371 Assert( (seg2p != NULL) );
372 if ( seg2p == NULL ) return;
374 Assert( Num_fuelcenters < MAX_NUM_FUELCENS );
375 Assert( Num_fuelcenters > -1 );
377 seg2p->value = Num_fuelcenters;
378 Station[Num_fuelcenters].Type = station_type;
379 Station[Num_fuelcenters].MaxCapacity = Fuelcen_max_amount;
380 Station[Num_fuelcenters].Capacity = Station[Num_fuelcenters].MaxCapacity;
381 Station[Num_fuelcenters].segnum = seg2p-Segment2s;
382 Station[Num_fuelcenters].Timer = -1;
383 Station[Num_fuelcenters].Flag = 0;
384 // Station[Num_fuelcenters].NextRobotType = -1;
385 // Station[Num_fuelcenters].last_created_obj=NULL;
386 // Station[Num_fuelcenters].last_created_sig = -1;
387 compute_segment_center(&Station[Num_fuelcenters].Center, segp);
389 // if (station_type == SEGMENT_IS_ROBOTMAKER)
390 // Station[Num_fuelcenters].Capacity = i2f(Difficulty_level + 3);
392 //mprintf( (0, "Segment %d is assigned to be fuel center %d.\n", Station[Num_fuelcenters].segnum, Num_fuelcenters ));
396 //------------------------------------------------------------
397 // Adds a matcen that already is a special type into the Station array.
398 // This function is separate from other fuelcens because we don't want values reset.
399 void matcen_create( segment *segp)
401 segment2 *seg2p = &Segment2s[segp-Segments];
403 int station_type = seg2p->special;
405 Assert( (seg2p != NULL) );
406 Assert(station_type == SEGMENT_IS_ROBOTMAKER);
407 if ( seg2p == NULL ) return;
409 Assert( Num_fuelcenters < MAX_NUM_FUELCENS );
410 Assert( Num_fuelcenters > -1 );
412 seg2p->value = Num_fuelcenters;
413 Station[Num_fuelcenters].Type = station_type;
414 Station[Num_fuelcenters].Capacity = i2f(Difficulty_level + 3);
415 Station[Num_fuelcenters].MaxCapacity = Station[Num_fuelcenters].Capacity;
417 Station[Num_fuelcenters].segnum = seg2p-Segment2s;
418 Station[Num_fuelcenters].Timer = -1;
419 Station[Num_fuelcenters].Flag = 0;
420 // Station[Num_fuelcenters].NextRobotType = -1;
421 // Station[Num_fuelcenters].last_created_obj=NULL;
422 // Station[Num_fuelcenters].last_created_sig = -1;
423 compute_segment_center(&Station[Num_fuelcenters].Center, &Segments[seg2p-Segment2s] );
425 seg2p->matcen_num = Num_robot_centers;
428 RobotCenters[seg2p->matcen_num].hit_points = MATCEN_HP_DEFAULT;
429 RobotCenters[seg2p->matcen_num].interval = MATCEN_INTERVAL_DEFAULT;
430 RobotCenters[seg2p->matcen_num].segnum = seg2p-Segment2s;
431 RobotCenters[seg2p->matcen_num].fuelcen_num = Num_fuelcenters;
433 //mprintf( (0, "Segment %d is assigned to be fuel center %d.\n", Station[Num_fuelcenters].segnum, Num_fuelcenters ));
437 //------------------------------------------------------------
438 // Adds a segment that already is a special type into the Station array.
439 void fuelcen_activate( segment * segp, int station_type )
441 segment2 *seg2p = &Segment2s[segp-Segments];
443 seg2p->special = station_type;
445 if (seg2p->special == SEGMENT_IS_ROBOTMAKER)
446 matcen_create( segp);
448 fuelcen_create( segp);
452 // The lower this number is, the more quickly the center can be re-triggered.
453 // If it's too low, it can mean all the robots won't be put out, but for about 5
454 // robots, that's not real likely.
455 #define MATCEN_LIFE (i2f(30-2*Difficulty_level))
457 //------------------------------------------------------------
458 // Trigger (enable) the materialization center in segment segnum
459 void trigger_matcen(int segnum)
461 // -- segment *segp = &Segments[segnum];
462 segment2 *seg2p = &Segment2s[segnum];
463 vms_vector pos, delta;
464 FuelCenter *robotcen;
467 mprintf((0, "Trigger matcen, segment %i\n", segnum));
469 Assert(seg2p->special == SEGMENT_IS_ROBOTMAKER);
470 Assert(seg2p->matcen_num < Num_fuelcenters);
471 Assert((seg2p->matcen_num >= 0) && (seg2p->matcen_num <= Highest_segment_index));
473 robotcen = &Station[RobotCenters[seg2p->matcen_num].fuelcen_num];
475 if (robotcen->Enabled == 1)
478 if (!robotcen->Lives)
481 // MK: 11/18/95, At insane, matcens work forever!
482 if (Difficulty_level+1 < NDL)
485 robotcen->Timer = F1_0*1000; // Make sure the first robot gets emitted right away.
486 robotcen->Enabled = 1; // Say this center is enabled, it can create robots.
487 robotcen->Capacity = i2f(Difficulty_level + 3);
488 robotcen->Disable_time = MATCEN_LIFE;
490 // Create a bright object in the segment.
491 pos = robotcen->Center;
492 vm_vec_sub(&delta, &Vertices[Segments[segnum].verts[0]], &robotcen->Center);
493 vm_vec_scale_add2(&pos, &delta, F1_0/2);
494 objnum = obj_create( OBJ_LIGHT, 0, segnum, &pos, NULL, 0, CT_LIGHT, MT_NONE, RT_NONE );
496 Objects[objnum].lifeleft = MATCEN_LIFE;
497 Objects[objnum].ctype.light_info.intensity = i2f(8); // Light cast by a fuelcen.
499 mprintf((1, "Can't create invisible flare for matcen.\n"));
502 // 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)));
506 //------------------------------------------------------------
507 // Takes away a segment's fuel center properties.
508 // Deletes the segment point entry in the FuelCenter list.
509 void fuelcen_delete( segment * segp )
511 segment2 *seg2p = &Segment2s[segp-Segments];
518 for (i=0; i<Num_fuelcenters; i++ ) {
519 if ( Station[i].segnum == segp-Segments ) {
521 // If Robot maker is deleted, fix Segments and RobotCenters.
522 if (Station[i].Type == SEGMENT_IS_ROBOTMAKER) {
524 Assert(Num_robot_centers >= 0);
526 for (j=seg2p->matcen_num; j<Num_robot_centers; j++)
527 RobotCenters[j] = RobotCenters[j+1];
529 for (j=0; j<Num_fuelcenters; j++) {
530 if ( Station[j].Type == SEGMENT_IS_ROBOTMAKER )
531 if ( Segment2s[Station[j].segnum].matcen_num > seg2p->matcen_num )
532 Segment2s[Station[j].segnum].matcen_num--;
536 //fix RobotCenters so they point to correct fuelcenter
537 for (j=0; j<Num_robot_centers; j++ )
538 if (RobotCenters[j].fuelcen_num > i) //this robotcenter's fuelcen is changing
539 RobotCenters[j].fuelcen_num--;
542 Assert(Num_fuelcenters >= 0);
543 for (j=i; j<Num_fuelcenters; j++ ) {
544 Station[j] = Station[j+1];
545 Segment2s[Station[j].segnum].value = j;
554 #define ROBOT_GEN_TIME (i2f(5))
556 object * create_morph_robot( segment *segp, vms_vector *object_pos, int object_id)
560 int default_behavior;
562 Players[Player_num].num_robots_level++;
563 Players[Player_num].num_robots_total++;
565 objnum = obj_create(OBJ_ROBOT, object_id, segp-Segments, object_pos,
566 &vmd_identity_matrix, Polygon_models[Robot_info[object_id].model_num].rad,
567 CT_AI, MT_PHYSICS, RT_POLYOBJ);
570 mprintf((1, "Can't create morph robot. Aborting morph.\n"));
575 obj = &Objects[objnum];
577 //Set polygon-object-specific data
579 obj->rtype.pobj_info.model_num = Robot_info[obj->id].model_num;
580 obj->rtype.pobj_info.subobj_flags = 0;
584 obj->mtype.phys_info.mass = Robot_info[obj->id].mass;
585 obj->mtype.phys_info.drag = Robot_info[obj->id].drag;
587 obj->mtype.phys_info.flags |= (PF_LEVELLING);
589 obj->shields = Robot_info[obj->id].strength;
591 default_behavior = Robot_info[obj->id].behavior;
593 init_ai_object(obj-Objects, default_behavior, -1 ); // Note, -1 = segment this robot goes to to hide, should probably be something useful
595 create_n_segment_path(obj, 6, -1); // Create a 6 segment path from creation point.
597 Ai_local_info[objnum].mode = ai_behavior_to_mode(default_behavior);
602 int Num_extry_robots = 15;
605 int FrameCount_last_msg = 0;
608 // ----------------------------------------------------------------------------------------------------------
609 void robotmaker_proc( FuelCenter * robotcen )
612 vms_vector cur_object_loc; //, direction;
613 int matcen_num, segnum, objnum;
616 vms_vector direction;
618 if (robotcen->Enabled == 0)
621 if (robotcen->Disable_time > 0) {
622 robotcen->Disable_time -= FrameTime;
623 if (robotcen->Disable_time <= 0) {
624 mprintf((0, "Robot center #%i gets disabled due to time running out.\n", robotcen-Station));
625 robotcen->Enabled = 0;
629 // mprintf((0, "Capacity of robot maker #%i is %i\n", robotcen - Station, robotcen->Capacity));
631 // No robot making in multiplayer mode.
634 if ((Game_mode & GM_MULTI) && (!(Game_mode & GM_MULTI_ROBOTS) || !network_i_am_master()))
637 if (Game_mode & GM_MULTI)
642 // Wait until transmorgafier has capacity to make a robot...
643 if ( robotcen->Capacity <= 0 ) {
647 matcen_num = Segment2s[robotcen->segnum].matcen_num;
648 //mprintf((0, "Robotmaker #%i flags = %8x\n", matcen_num, RobotCenters[matcen_num].robot_flags));
650 if ( matcen_num == -1 ) {
651 mprintf((0, "Non-functional robotcen at %d\n", robotcen->segnum));
655 if (RobotCenters[matcen_num].robot_flags[0]==0 && RobotCenters[matcen_num].robot_flags[1]==0) {
656 //mprintf((0, "robot_flags = 0 at robot maker #%i\n", RobotCenters[matcen_num].robot_flags));
660 // Wait until we have a free slot for this puppy...
661 // <<<<<<<<<<<<<<<< Num robots in mine >>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<< Max robots in mine >>>>>>>>>>>>>>>
662 if ( (Players[Player_num].num_robots_level - Players[Player_num].num_kills_level) >= (Gamesave_num_org_robots + Num_extry_robots ) ) {
664 if (FrameCount > FrameCount_last_msg + 20) {
665 mprintf((0, "Cannot morph until you kill one!\n"));
666 FrameCount_last_msg = FrameCount;
672 robotcen->Timer += FrameTime;
674 switch( robotcen->Flag ) {
675 case 0: // Wait until next robot can generate
676 if (Game_mode & GM_MULTI)
678 top_time = ROBOT_GEN_TIME;
682 dist_to_player = vm_vec_dist_quick( &ConsoleObject->pos, &robotcen->Center );
683 top_time = dist_to_player/64 + d_rand() * 2 + F1_0*2;
684 if ( top_time > ROBOT_GEN_TIME )
685 top_time = ROBOT_GEN_TIME + d_rand();
686 if ( top_time < F1_0*2 )
687 top_time = F1_0*3/2 + d_rand()*2;
690 // mprintf( (0, "Time between morphs %d seconds, dist_to_player = %7.3f\n", f2i(top_time), f2fl(dist_to_player) ));
692 if (robotcen->Timer > top_time ) {
694 int i, my_station_num = robotcen-Station;
697 // Make sure this robotmaker hasn't put out its max without having any of them killed.
698 for (i=0; i<=Highest_object_index; i++)
699 if (Objects[i].type == OBJ_ROBOT)
700 if ((Objects[i].matcen_creator^0x80) == my_station_num)
702 if (count > Difficulty_level + 3) {
703 mprintf((0, "Cannot morph: center %i has already put out %i robots.\n", my_station_num, count));
704 robotcen->Timer /= 2;
708 // Whack on any robot or player in the matcen segment.
710 segnum = robotcen->segnum;
711 for (objnum=Segments[segnum].objects;objnum!=-1;objnum=Objects[objnum].next) {
713 if ( count > MAX_OBJECTS ) {
714 mprintf((0, "Object list in segment %d is circular.", segnum ));
718 if (Objects[objnum].type==OBJ_ROBOT) {
719 collide_robot_and_materialization_center(&Objects[objnum]);
720 robotcen->Timer = top_time/2;
722 } else if (Objects[objnum].type==OBJ_PLAYER ) {
723 collide_player_and_materialization_center(&Objects[objnum]);
724 robotcen->Timer = top_time/2;
729 compute_segment_center(&cur_object_loc, &Segments[robotcen->segnum]);
730 // HACK!!! The 10 under here should be something equal to the 1/2 the size of the segment.
731 obj = object_create_explosion(robotcen->segnum, &cur_object_loc, i2f(10), VCLIP_MORPHING_ROBOT );
734 extract_orient_from_segment(&obj->orient,&Segments[robotcen->segnum]);
736 if ( Vclip[VCLIP_MORPHING_ROBOT].sound_num > -1 ) {
737 digi_link_sound_to_pos( Vclip[VCLIP_MORPHING_ROBOT].sound_num, robotcen->segnum, 0, &cur_object_loc, 0, F1_0 );
744 case 1: // Wait until 1/2 second after VCLIP started.
745 if (robotcen->Timer > (Vclip[VCLIP_MORPHING_ROBOT].play_time/2) ) {
747 robotcen->Capacity -= EnergyToCreateOneRobot;
751 compute_segment_center(&cur_object_loc, &Segments[robotcen->segnum]);
753 // If this is the first materialization, set to valid robot.
754 if (RobotCenters[matcen_num].robot_flags[0] != 0 || RobotCenters[matcen_num].robot_flags[1] != 0) {
757 sbyte legal_types[64]; // 64 bits, the width of robot_flags[].
758 int num_types, robot_index, i;
763 flags = RobotCenters[matcen_num].robot_flags[i];
766 legal_types[num_types++] = robot_index;
772 //mprintf((0, "Flags = %08x, %2i legal types to morph: \n", RobotCenters[matcen_num].robot_flags, num_types));
773 //for (i=0; i<num_types; i++)
774 // mprintf((0, "%2i ", legal_types[i]));
775 //mprintf((0, "\n"));
778 type = legal_types[0];
780 type = legal_types[(d_rand() * num_types) / 32768];
782 mprintf((0, "Morph: (type = %i) (seg = %i) (capacity = %08x)\n", type, robotcen->segnum, robotcen->Capacity));
783 obj = create_morph_robot(&Segments[robotcen->segnum], &cur_object_loc, type );
787 if (Game_mode & GM_MULTI)
788 multi_send_create_robot(robotcen-Station, obj-Objects, type);
791 obj->matcen_creator = (robotcen-Station) | 0x80;
793 // Make object faces player...
794 vm_vec_sub( &direction, &ConsoleObject->pos,&obj->pos );
795 vm_vector_2_matrix( &obj->orient, &direction, &obj->orient.uvec, NULL);
798 //robotcen->last_created_obj = obj;
799 //robotcen->last_created_sig = robotcen->last_created_obj->signature;
801 mprintf((0, "Warning: create_morph_robot returned NULL (no objects left?)\n"));
814 //-------------------------------------------------------------
815 // Called once per frame, replenishes fuel supply.
816 void fuelcen_update_all()
819 fix AmountToreplenish;
821 AmountToreplenish = fixmul(FrameTime,Fuelcen_refill_speed);
823 for (i=0; i<Num_fuelcenters; i++ ) {
824 if ( Station[i].Type == SEGMENT_IS_ROBOTMAKER ) {
825 if (! (Game_suspended & SUSP_ROBOTS))
826 robotmaker_proc( &Station[i] );
827 } else if ( Station[i].Type == SEGMENT_IS_CONTROLCEN ) {
828 //controlcen_proc( &Station[i] );
830 } else if ( (Station[i].MaxCapacity > 0) && (PlayerSegment!=&Segments[Station[i].segnum]) ) {
831 if ( Station[i].Capacity < Station[i].MaxCapacity ) {
832 Station[i].Capacity += AmountToreplenish;
833 //mprintf( (0, "Fuel center %d replenished to %d.\n", i, f2i(Station[i].Capacity) ));
834 if ( Station[i].Capacity >= Station[i].MaxCapacity ) {
835 Station[i].Capacity = Station[i].MaxCapacity;
836 //gauge_message( "Fuel center is fully recharged! " );
843 //--unused-- //-------------------------------------------------------------
844 //--unused-- // replenishes all fuel supplies.
845 //--unused-- void fuelcen_replenish_all()
849 //--unused-- for (i=0; i<Num_fuelcenters; i++ ) {
850 //--unused-- Station[i].Capacity = Station[i].MaxCapacity;
852 //--unused-- //mprintf( (0, "All fuel centers are replenished\n" ));
856 #define FUELCEN_SOUND_DELAY (f1_0/4) //play every half second
858 //-------------------------------------------------------------
859 fix fuelcen_give_fuel(segment *segp, fix MaxAmountCanTake )
861 segment2 *seg2p = &Segment2s[segp-Segments];
863 static fix last_play_time=0;
865 Assert( segp != NULL );
867 PlayerSegment = segp;
869 if ( (segp) && (seg2p->special==SEGMENT_IS_FUELCEN) ) {
872 detect_escort_goal_accomplished(-4); // UGLY! Hack! -4 means went through fuelcen.
874 // if (Station[segp->value].MaxCapacity<=0) {
875 // HUD_init_message( "Fuelcenter %d is destroyed.", segp->value );
879 // if (Station[segp->value].Capacity<=0) {
880 // HUD_init_message( "Fuelcenter %d is empty.", segp->value );
884 if (MaxAmountCanTake <= 0 ) {
885 // //gauge_message( "Fueled up!");
889 amount = fixmul(FrameTime,Fuelcen_give_amount);
891 if (amount > MaxAmountCanTake )
892 amount = MaxAmountCanTake;
894 // if (!(Game_mode & GM_MULTI))
895 // if ( Station[segp->value].Capacity < amount ) {
896 // amount = Station[segp->value].Capacity;
897 // Station[segp->value].Capacity = 0;
899 // Station[segp->value].Capacity -= amount;
902 if (last_play_time > GameTime)
905 if (GameTime > last_play_time+FUELCEN_SOUND_DELAY) {
907 digi_play_sample( SOUND_REFUEL_STATION_GIVING_FUEL, F1_0/2 );
909 if (Game_mode & GM_MULTI)
910 multi_send_play_sound(SOUND_REFUEL_STATION_GIVING_FUEL, F1_0/2);
913 last_play_time = GameTime;
917 //HUD_init_message( "Fuelcen %d has %d/%d fuel", segp->value,f2i(Station[segp->value].Capacity),f2i(Station[segp->value].MaxCapacity) );
925 //-------------------------------------------------------------
928 // use same values as fuel centers
929 fix repaircen_give_shields(segment *segp, fix MaxAmountCanTake )
931 segment2 *seg2p = &Segment2s[segp-Segments];
932 static fix last_play_time=0;
934 Assert( segp != NULL );
935 PlayerSegment = segp;
936 if ( (segp) && (seg2p->special==SEGMENT_IS_REPAIRCEN) ) {
938 // detect_escort_goal_accomplished(-4); // UGLY! Hack! -4 means went through fuelcen.
939 // if (Station[segp->value].MaxCapacity<=0) {
940 // HUD_init_message( "Repaircenter %d is destroyed.", segp->value );
943 // if (Station[segp->value].Capacity<=0) {
944 // HUD_init_message( "Repaircenter %d is empty.", segp->value );
947 if (MaxAmountCanTake <= 0 ) {
948 //gauge_message( "Shields restored!");
951 amount = fixmul(FrameTime,Fuelcen_give_amount);
952 if (amount > MaxAmountCanTake )
953 amount = MaxAmountCanTake;
954 // if (!(Game_mode & GM_MULTI))
955 // if ( Station[segp->value].Capacity < amount ) {
956 // amount = Station[segp->value].Capacity;
957 // Station[segp->value].Capacity = 0;
959 // Station[segp->value].Capacity -= amount;
961 if (last_play_time > GameTime)
963 if (GameTime > last_play_time+FUELCEN_SOUND_DELAY) {
964 digi_play_sample( SOUND_REFUEL_STATION_GIVING_FUEL, F1_0/2 );
966 if (Game_mode & GM_MULTI)
967 multi_send_play_sound(SOUND_REFUEL_STATION_GIVING_FUEL, F1_0/2);
969 last_play_time = GameTime;
971 //HUD_init_message( "Fuelcen %d has %d/%d fuel", segp->value,f2i(Station[segp->value].Capacity),f2i(Station[segp->value].MaxCapacity) );
978 //--unused-- //-----------------------------------------------------------
979 //--unused-- // Damages a fuel center
980 //--unused-- void fuelcen_damage(segment *segp, fix damage )
982 //--unused-- //int i;
983 //--unused-- // int station_num = segp->value;
985 //--unused-- Assert( segp != NULL );
986 //--unused-- if ( segp == NULL ) return;
988 //--unused-- mprintf((0, "Obsolete function fuelcen_damage() called with seg=%i, damage=%7.3f\n", segp-Segments, f2fl(damage)));
989 //--unused-- switch( segp->special ) {
990 //--unused-- case SEGMENT_IS_NOTHING:
992 //--unused-- case SEGMENT_IS_ROBOTMAKER:
993 //--unused-- //-- // Robotmaker hit by laser
994 //--unused-- //-- if (Station[station_num].MaxCapacity<=0 ) {
995 //--unused-- //-- // Shooting a already destroyed materializer
996 //--unused-- //-- } else {
997 //--unused-- //-- Station[station_num].MaxCapacity -= damage;
998 //--unused-- //-- if (Station[station_num].Capacity > Station[station_num].MaxCapacity ) {
999 //--unused-- //-- Station[station_num].Capacity = Station[station_num].MaxCapacity;
1001 //--unused-- //-- if (Station[station_num].MaxCapacity <= 0 ) {
1002 //--unused-- //-- Station[station_num].MaxCapacity = 0;
1003 //--unused-- //-- // Robotmaker dead
1004 //--unused-- //-- for (i=0; i<6; i++ )
1005 //--unused-- //-- segp->sides[i].tmap_num2 = 0;
1008 //--unused-- //-- //mprintf( (0, "Materializatormografier has %x capacity left\n", Station[station_num].MaxCapacity ));
1010 //--unused-- case SEGMENT_IS_FUELCEN:
1011 //--unused-- //-- digi_play_sample( SOUND_REFUEL_STATION_HIT );
1012 //--unused-- //-- if (Station[station_num].MaxCapacity>0 ) {
1013 //--unused-- //-- Station[station_num].MaxCapacity -= damage;
1014 //--unused-- //-- if (Station[station_num].Capacity > Station[station_num].MaxCapacity ) {
1015 //--unused-- //-- Station[station_num].Capacity = Station[station_num].MaxCapacity;
1017 //--unused-- //-- if (Station[station_num].MaxCapacity <= 0 ) {
1018 //--unused-- //-- Station[station_num].MaxCapacity = 0;
1019 //--unused-- //-- digi_play_sample( SOUND_REFUEL_STATION_DESTROYED );
1021 //--unused-- //-- } else {
1022 //--unused-- //-- Station[station_num].MaxCapacity = 0;
1024 //--unused-- //-- HUD_init_message( "Fuelcenter %d damaged", station_num );
1026 //--unused-- case SEGMENT_IS_REPAIRCEN:
1028 //--unused-- case SEGMENT_IS_CONTROLCEN:
1030 //--unused-- default:
1031 //--unused-- Error( "Invalid type in fuelcen.c" );
1035 //--unused-- // ----------------------------------------------------------------------------------------------------------
1036 //--unused-- fixang my_delta_ang(fixang a,fixang b)
1038 //--unused-- fixang delta0,delta1;
1040 //--unused-- return (abs(delta0 = a - b) < abs(delta1 = b - a)) ? delta0 : delta1;
1044 //--unused-- // ----------------------------------------------------------------------------------------------------------
1045 //--unused-- //return though which side of seg0 is seg1
1046 //--unused-- int john_find_connect_side(int seg0,int seg1)
1048 //--unused-- segment *Seg=&Segments[seg0];
1051 //--unused-- for (i=MAX_SIDES_PER_SEGMENT;i--;) if (Seg->children[i]==seg1) return i;
1053 //--unused-- return -1;
1056 // ----------------------------------------------------------------------------------------------------------
1057 //--unused-- vms_angvec start_angles, delta_angles, goal_angles;
1058 //--unused-- vms_vector start_pos, delta_pos, goal_pos;
1059 //--unused-- int FuelStationSeg;
1060 //--unused-- fix current_time,delta_time;
1061 //--unused-- int next_side, side_index;
1062 //--unused-- int * sidelist;
1064 //--repair-- int Repairing;
1065 //--repair-- vms_vector repair_save_uvec; //the player's upvec when enter repaircen
1066 //--repair-- object *RepairObj=NULL; //which object getting repaired
1067 //--repair-- int disable_repair_center=0;
1068 //--repair-- fix repair_rate;
1069 //--repair-- #define FULL_REPAIR_RATE i2f(10)
1071 //--unused-- ubyte save_control_type,save_movement_type;
1073 //--unused-- int SideOrderBack[] = {WFRONT, WRIGHT, WTOP, WLEFT, WBOTTOM, WBACK};
1074 //--unused-- int SideOrderFront[] = {WBACK, WLEFT, WTOP, WRIGHT, WBOTTOM, WFRONT};
1075 //--unused-- int SideOrderLeft[] = { WRIGHT, WBACK, WTOP, WFRONT, WBOTTOM, WLEFT };
1076 //--unused-- int SideOrderRight[] = { WLEFT, WFRONT, WTOP, WBACK, WBOTTOM, WRIGHT };
1077 //--unused-- int SideOrderTop[] = { WBOTTOM, WLEFT, WBACK, WRIGHT, WFRONT, WTOP };
1078 //--unused-- int SideOrderBottom[] = { WTOP, WLEFT, WFRONT, WRIGHT, WBACK, WBOTTOM };
1080 //--unused-- int SideUpVector[] = {WBOTTOM, WFRONT, WBOTTOM, WFRONT, WBOTTOM, WBOTTOM };
1082 //--repair-- // ----------------------------------------------------------------------------------------------------------
1083 //--repair-- void refuel_calc_deltas(object *obj, int next_side, int repair_seg)
1085 //--repair-- vms_vector nextcenter, headfvec, *headuvec;
1086 //--repair-- vms_matrix goal_orient;
1088 //--repair-- // Find time for this movement
1089 //--repair-- delta_time = F1_0; // one second...
1091 //--repair-- // Find start and goal position
1092 //--repair-- start_pos = obj->pos;
1094 //--repair-- // Find delta position to get to goal position
1095 //--repair-- compute_segment_center(&goal_pos,&Segments[repair_seg]);
1096 //--repair-- vm_vec_sub( &delta_pos,&goal_pos,&start_pos);
1098 //--repair-- // Find start angles
1099 //--repair-- //angles_from_vector(&start_angles,&obj->orient.fvec);
1100 //--repair-- vm_extract_angles_matrix(&start_angles,&obj->orient);
1102 //--repair-- // Find delta angles to get to goal orientation
1103 //--repair-- med_compute_center_point_on_side(&nextcenter,&Segments[repair_seg],next_side);
1104 //--repair-- vm_vec_sub(&headfvec,&nextcenter,&goal_pos);
1105 //--repair-- //mprintf( (0, "Next_side = %d, Head fvec = %d,%d,%d\n", next_side, headfvec.x, headfvec.y, headfvec.z ));
1107 //--repair-- if (next_side == 5) //last side
1108 //--repair-- headuvec = &repair_save_uvec;
1110 //--repair-- headuvec = &Segments[repair_seg].sides[SideUpVector[next_side]].normals[0];
1112 //--repair-- vm_vector_2_matrix(&goal_orient,&headfvec,headuvec,NULL);
1113 //--repair-- vm_extract_angles_matrix(&goal_angles,&goal_orient);
1114 //--repair-- delta_angles.p = my_delta_ang(start_angles.p,goal_angles.p);
1115 //--repair-- delta_angles.b = my_delta_ang(start_angles.b,goal_angles.b);
1116 //--repair-- delta_angles.h = my_delta_ang(start_angles.h,goal_angles.h);
1117 //--repair-- current_time = 0;
1118 //--repair-- Repairing = 0;
1121 //--repair-- // ----------------------------------------------------------------------------------------------------------
1122 //--repair-- //if repairing, cut it short
1123 //--repair-- abort_repair_center()
1125 //--repair-- if (!RepairObj || side_index==5)
1126 //--repair-- return;
1128 //--repair-- current_time = 0;
1129 //--repair-- side_index = 5;
1130 //--repair-- next_side = sidelist[side_index];
1131 //--repair-- refuel_calc_deltas(RepairObj, next_side, FuelStationSeg);
1134 //--repair-- // ----------------------------------------------------------------------------------------------------------
1135 //--repair-- void repair_ship_damage()
1137 //--repair-- //mprintf((0,"Repairing ship damage\n"));
1140 //--repair-- // ----------------------------------------------------------------------------------------------------------
1141 //--repair-- int refuel_do_repair_effect( object * obj, int first_time, int repair_seg ) {
1143 //--repair-- obj->mtype.phys_info.velocity.x = 0;
1144 //--repair-- obj->mtype.phys_info.velocity.y = 0;
1145 //--repair-- obj->mtype.phys_info.velocity.z = 0;
1147 //--repair-- if (first_time) {
1148 //--repair-- int entry_side;
1149 //--repair-- current_time = 0;
1151 //--repair-- digi_play_sample( SOUND_REPAIR_STATION_PLAYER_ENTERING, F1_0 );
1153 //--repair-- entry_side = john_find_connect_side(repair_seg,obj->segnum );
1154 //--repair-- Assert( entry_side > -1 );
1156 //--repair-- switch( entry_side ) {
1157 //--repair-- case WBACK: sidelist = SideOrderBack; break;
1158 //--repair-- case WFRONT: sidelist = SideOrderFront; break;
1159 //--repair-- case WLEFT: sidelist = SideOrderLeft; break;
1160 //--repair-- case WRIGHT: sidelist = SideOrderRight; break;
1161 //--repair-- case WTOP: sidelist = SideOrderTop; break;
1162 //--repair-- case WBOTTOM: sidelist = SideOrderBottom; break;
1164 //--repair-- side_index = 0;
1165 //--repair-- next_side = sidelist[side_index];
1167 //--repair-- refuel_calc_deltas(obj,next_side, repair_seg);
1170 //--repair-- //update shields
1171 //--repair-- if (Players[Player_num].shields < MAX_SHIELDS) { //if above max, don't mess with it
1173 //--repair-- Players[Player_num].shields += fixmul(FrameTime,repair_rate);
1175 //--repair-- if (Players[Player_num].shields > MAX_SHIELDS)
1176 //--repair-- Players[Player_num].shields = MAX_SHIELDS;
1179 //--repair-- current_time += FrameTime;
1181 //--repair-- if (current_time >= delta_time ) {
1182 //--repair-- vms_angvec av;
1183 //--repair-- obj->pos = goal_pos;
1184 //--repair-- av = goal_angles;
1185 //--repair-- vm_angles_2_matrix(&obj->orient,&av);
1187 //--repair-- if (side_index >= 5 )
1188 //--repair-- return 1; // Done being repaired...
1190 //--repair-- if (Repairing==0) {
1191 //--repair-- //mprintf( (0, "<MACHINE EFFECT ON SIDE %d>\n", next_side ));
1192 //--repair-- //digi_play_sample( SOUND_REPAIR_STATION_FIXING );
1193 //--repair-- Repairing=1;
1195 //--repair-- switch( next_side ) {
1196 //--repair-- case 0: digi_play_sample( SOUND_REPAIR_STATION_FIXING_1,F1_0 ); break;
1197 //--repair-- case 1: digi_play_sample( SOUND_REPAIR_STATION_FIXING_2,F1_0 ); break;
1198 //--repair-- case 2: digi_play_sample( SOUND_REPAIR_STATION_FIXING_3,F1_0 ); break;
1199 //--repair-- case 3: digi_play_sample( SOUND_REPAIR_STATION_FIXING_4,F1_0 ); break;
1200 //--repair-- case 4: digi_play_sample( SOUND_REPAIR_STATION_FIXING_1,F1_0 ); break;
1201 //--repair-- case 5: digi_play_sample( SOUND_REPAIR_STATION_FIXING_2,F1_0 ); break;
1204 //--repair-- repair_ship_damage();
1208 //--repair-- if (current_time >= (delta_time+(F1_0/2)) ) {
1209 //--repair-- current_time = 0;
1210 //--repair-- // Find next side...
1211 //--repair-- side_index++;
1212 //--repair-- if (side_index >= 6 ) return 1;
1213 //--repair-- next_side = sidelist[side_index];
1215 //--repair-- refuel_calc_deltas(obj, next_side, repair_seg);
1218 //--repair-- } else {
1219 //--repair-- fix factor, p,b,h;
1220 //--repair-- vms_angvec av;
1222 //--repair-- factor = fixdiv( current_time,delta_time );
1224 //--repair-- // Find object's current position
1225 //--repair-- obj->pos = delta_pos;
1226 //--repair-- vm_vec_scale( &obj->pos, factor );
1227 //--repair-- vm_vec_add2( &obj->pos, &start_pos );
1229 //--repair-- // Find object's current orientation
1230 //--repair-- p = fixmul(delta_angles.p,factor);
1231 //--repair-- b = fixmul(delta_angles.b,factor);
1232 //--repair-- h = fixmul(delta_angles.h,factor);
1233 //--repair-- av.p = (fixang)p + start_angles.p;
1234 //--repair-- av.b = (fixang)b + start_angles.b;
1235 //--repair-- av.h = (fixang)h + start_angles.h;
1236 //--repair-- vm_angles_2_matrix(&obj->orient,&av);
1240 //--repair-- update_object_seg(obj); //update segment
1242 //--repair-- return 0;
1245 //--repair-- // ----------------------------------------------------------------------------------------------------------
1246 //--repair-- //do the repair center for this frame
1247 //--repair-- void do_repair_sequence(object *obj)
1249 //--repair-- Assert(obj == RepairObj);
1251 //--repair-- if (refuel_do_repair_effect( obj, 0, FuelStationSeg )) {
1252 //--repair-- if (Players[Player_num].shields < MAX_SHIELDS)
1253 //--repair-- Players[Player_num].shields = MAX_SHIELDS;
1254 //--repair-- obj->control_type = save_control_type;
1255 //--repair-- obj->movement_type = save_movement_type;
1256 //--repair-- disable_repair_center=1;
1257 //--repair-- RepairObj = NULL;
1260 //--repair-- //the two lines below will spit the player out of the rapair center,
1261 //--repair-- //but what happen is that the ship just bangs into the door
1262 //--repair-- //if (obj->movement_type == MT_PHYSICS)
1263 //--repair-- // vm_vec_copy_scale(&obj->mtype.phys_info.velocity,&obj->orient.fvec,i2f(200));
1268 //--repair-- // ----------------------------------------------------------------------------------------------------------
1269 //--repair-- //see if we should start the repair center
1270 //--repair-- void check_start_repair_center(object *obj)
1272 //--repair-- if (RepairObj != NULL) return; //already in repair center
1274 //--repair-- if (Lsegments[obj->segnum].special_type & SS_REPAIR_CENTER) {
1276 //--repair-- if (!disable_repair_center) {
1277 //--repair-- //have just entered repair center
1279 //--repair-- RepairObj = obj;
1280 //--repair-- repair_save_uvec = obj->orient.uvec;
1282 //--repair-- repair_rate = fixmuldiv(FULL_REPAIR_RATE,(MAX_SHIELDS - Players[Player_num].shields),MAX_SHIELDS);
1284 //--repair-- save_control_type = obj->control_type;
1285 //--repair-- save_movement_type = obj->movement_type;
1287 //--repair-- obj->control_type = CT_REPAIRCEN;
1288 //--repair-- obj->movement_type = MT_NONE;
1290 //--repair-- FuelStationSeg = Lsegments[obj->segnum].special_segment;
1291 //--repair-- Assert(FuelStationSeg != -1);
1293 //--repair-- if (refuel_do_repair_effect( obj, 1, FuelStationSeg )) {
1294 //--repair-- Int3(); //can this happen?
1295 //--repair-- obj->control_type = CT_FLYING;
1296 //--repair-- obj->movement_type = MT_PHYSICS;
1301 //--repair-- disable_repair_center=0;
1305 // --------------------------------------------------------------------------------------------
1306 void disable_matcens(void)
1310 for (i=0; i<Num_robot_centers; i++) {
1311 Station[i].Enabled = 0;
1312 Station[i].Disable_time = 0;
1316 // --------------------------------------------------------------------------------------------
1317 // Initialize all materialization centers.
1318 // Give them all the right number of lives.
1319 void init_all_matcens(void)
1323 for (i=0; i<Num_fuelcenters; i++)
1324 if (Station[i].Type == SEGMENT_IS_ROBOTMAKER) {
1325 Station[i].Lives = 3;
1326 Station[i].Enabled = 0;
1327 Station[i].Disable_time = 0;
1330 // Make sure this fuelcen is pointed at by a matcen.
1332 for (j=0; j<Num_robot_centers; j++) {
1333 if (RobotCenters[j].fuelcen_num == i)
1336 Assert(j != Num_robot_centers);
1343 // Make sure all matcens point at a fuelcen
1344 for (i=0; i<Num_robot_centers; i++) {
1345 int fuelcen_num = RobotCenters[i].fuelcen_num;
1347 Assert(fuelcen_num < Num_fuelcenters);
1348 Assert(Station[fuelcen_num].Type == SEGMENT_IS_ROBOTMAKER);
1355 extern void multi_send_capture_bonus (char);
1357 void fuelcen_check_for_goal(segment *segp)
1359 segment2 *seg2p = &Segment2s[segp-Segments];
1361 Assert( segp != NULL );
1362 Assert (Game_mode & GM_CAPTURE);
1364 if (seg2p->special==SEGMENT_IS_GOAL_BLUE ) {
1366 if ((get_team(Player_num)==TEAM_BLUE) && (Players[Player_num].flags & PLAYER_FLAGS_FLAG))
1368 mprintf ((0,"In goal segment BLUE\n"));
1370 multi_send_capture_bonus (Player_num);
1371 Players[Player_num].flags &=(~(PLAYER_FLAGS_FLAG));
1372 maybe_drop_net_powerup (POW_FLAG_RED);
1375 if ( seg2p->special==SEGMENT_IS_GOAL_RED) {
1377 if ((get_team(Player_num)==TEAM_RED) && (Players[Player_num].flags & PLAYER_FLAGS_FLAG))
1379 mprintf ((0,"In goal segment RED\n"));
1380 multi_send_capture_bonus (Player_num);
1381 Players[Player_num].flags &=(~(PLAYER_FLAGS_FLAG));
1382 maybe_drop_net_powerup (POW_FLAG_BLUE);
1387 void fuelcen_check_for_hoard_goal(segment *segp)
1389 segment2 *seg2p = &Segment2s[segp-Segments];
1391 Assert( segp != NULL );
1392 Assert (Game_mode & GM_HOARD);
1397 if (seg2p->special==SEGMENT_IS_GOAL_BLUE || seg2p->special==SEGMENT_IS_GOAL_RED )
1399 if (Players[Player_num].secondary_ammo[PROXIMITY_INDEX])
1401 mprintf ((0,"In orb goal!\n"));
1402 multi_send_orb_bonus (Player_num);
1403 Players[Player_num].flags &=(~(PLAYER_FLAGS_FLAG));
1404 Players[Player_num].secondary_ammo[PROXIMITY_INDEX]=0;
1412 #ifndef FAST_FILE_IO
1414 * reads an old_matcen_info structure from a CFILE
1416 void old_matcen_info_read(old_matcen_info *mi, CFILE *fp)
1418 mi->robot_flags = cfile_read_int(fp);
1419 mi->hit_points = cfile_read_fix(fp);
1420 mi->interval = cfile_read_fix(fp);
1421 mi->segnum = cfile_read_short(fp);
1422 mi->fuelcen_num = cfile_read_short(fp);
1426 * reads a matcen_info structure from a CFILE
1428 void matcen_info_read(matcen_info *mi, CFILE *fp)
1430 mi->robot_flags[0] = cfile_read_int(fp);
1431 mi->robot_flags[1] = cfile_read_int(fp);
1432 mi->hit_points = cfile_read_fix(fp);
1433 mi->interval = cfile_read_fix(fp);
1434 mi->segnum = cfile_read_short(fp);
1435 mi->fuelcen_num = cfile_read_short(fp);