2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
10 * $Logfile: /Freespace2/code/Object/Object.cpp $
15 * Code to manage objects
18 * Revision 1.3 2002/06/09 04:41:24 relnev
19 * added copyright header
21 * Revision 1.2 2002/05/07 03:16:48 theoddone33
22 * The Great Newline Fix
24 * Revision 1.1.1.1 2002/05/03 03:28:10 root
28 * 33 8/27/99 10:36a Dave
29 * Impose a 2% penalty for hitting the shield balance key.
31 * 32 8/24/99 8:55p Dave
32 * Make sure nondimming pixels work properly in tech menu.
34 * 31 7/26/99 10:24p Anoop
35 * Oops. Don't do anything to checkobjects in a release build.
37 * 30 7/26/99 5:50p Dave
38 * Revised ingame join. Better? We'll see....
40 * 29 7/22/99 3:58p Jefff
41 * Temporarily remove object checking for multiplayer clients.
43 * 28 7/08/99 10:53a Dave
44 * New multiplayer interpolation scheme. Not 100% done yet, but still
45 * better than the old way.
47 * 27 7/03/99 5:50p Dave
48 * Make rotated bitmaps draw properly in padlock views.
50 * 26 7/01/99 11:44a Dave
51 * Updated object sound system to allow multiple obj sounds per ship.
52 * Added hit-by-beam sound. Added killed by beam sound.
54 * 25 5/27/99 6:17p Dave
55 * Added in laser glows.
57 * 24 5/18/99 12:08p Andsager
58 * Added observer_process_post to handle observer too far away
60 * 23 5/18/99 11:50a Andsager
61 * Remove unused object type OBJ_GHOST_SAVE
63 * 22 4/23/99 5:53p Dave
64 * Started putting in new pof nebula support into Fred.
66 * 21 4/21/99 6:15p Dave
67 * Did some serious housecleaning in the beam code. Made it ready to go
68 * for anti-fighter "pulse" weapons. Fixed collision pair creation. Added
69 * a handy macro for recalculating collision pairs for a given object.
71 * 20 4/20/99 6:39p Dave
72 * Almost done with artillery targeting. Added support for downloading
73 * images on the PXO screen.
75 * 19 4/19/99 11:01p Dave
76 * More sophisticated targeting laser support. Temporary checkin.
78 * 18 4/16/99 5:54p Dave
79 * Support for on/off style "stream" weapons. Real early support for
80 * target-painting lasers.
82 * 17 3/29/99 6:17p Dave
83 * More work on demo system. Got just about everything in except for
84 * blowing ships up, secondary weapons and player death/warpout.
86 * 16 3/10/99 6:50p Dave
87 * Changed the way we buffer packets for all clients. Optimized turret
88 * fired packets. Did some weapon firing optimizations.
90 * 15 3/09/99 6:24p Dave
91 * More work on object update revamping. Identified several sources of
92 * unnecessary bandwidth.
94 * 14 3/08/99 7:03p Dave
95 * First run of new object update system. Looks very promising.
97 * 13 1/30/99 5:08p Dave
98 * More new hi-res stuff.Support for nice D3D textures.
100 * 12 1/29/99 2:25p Andsager
101 * Added turret_swarm_missiles
103 * 11 1/25/99 5:03a Dave
104 * First run of stealth, AWACS and TAG missile support. New mission type
107 * 10 1/24/99 11:37p Dave
108 * First full rev of beam weapons. Very customizable. Removed some bogus
109 * Int3()'s in low level net code.
111 * 9 1/14/99 12:48a Dave
112 * Todo list bug fixes. Made a pass at putting briefing icons back into
113 * FRED. Sort of works :(
115 * 8 1/12/99 5:45p Dave
116 * Moved weapon pipeline in multiplayer to almost exclusively client side.
117 * Very good results. Bandwidth goes down, playability goes up for crappy
118 * connections. Fixed object update problem for ship subsystems.
120 * 7 1/12/99 12:53a Dave
121 * More work on beam weapons - made collision detection very efficient -
122 * collide against all object types properly - made 3 movement types
123 * smooth. Put in test code to check for possible non-darkening pixels on
126 * 6 1/08/99 2:08p Dave
127 * Fixed software rendering for pofview. Super early support for AWACS and
130 * 5 11/14/98 5:32p Dave
131 * Lots of nebula work. Put in ship contrails.
133 * 4 11/09/98 2:11p Dave
134 * Nebula optimizations.
136 * 3 11/05/98 4:18p Dave
137 * First run nebula support. Beefed up localization a bit. Removed all
138 * conditional compiles for foreign versions. Modified mission file
141 * 2 10/07/98 10:53a Dave
144 * 1 10/07/98 10:50a Dave
146 * 242 8/28/98 3:29p Dave
147 * EMP effect done. AI effects may need some tweaking as required.
149 * 241 8/07/98 10:13a Allender
150 * new object flag setting code for OF_COULD_BE_PLAYER since it was
151 * getting set incorrectly
153 * 240 7/02/98 6:16p Dave
154 * Make rear facing prediction much better. Tweak update levels and
155 * viewcone values. Make sure observers send targeting info correctly.
157 * 239 6/30/98 2:43p Dave
158 * Fixed merge problems.
160 * 238 6/30/98 2:25p Dave
161 * Revamped object update system
163 * 237 6/22/98 8:36a Allender
164 * revamping of homing weapon system. don't send as object updates
167 * 236 5/25/98 10:58a Allender
168 * more object update stuff -- fix duplicate repair ship messages
170 * 235 5/24/98 10:38a Allender
171 * make docked objects move properly on multiplayer clients
173 * 234 5/20/98 4:32p Allender
174 * changed RELEASE to NDEBUG
176 * 233 5/20/98 10:07a John
177 * put back in object flag checking for DEBUG.
179 * 232 5/18/98 4:21p Frank
180 * AL: fix problem with same vectors in obj_visible_from_eye()
182 * 231 5/18/98 10:05a Lawrance
183 * use old client prediction code for player ships
185 * 230 5/18/98 12:52a Lawrance
186 * Client-side prediction improvements
188 * 229 5/15/98 3:54p John
189 * Added code so that only "perishable" fireballs get removed.
191 * 228 5/15/98 9:59a John
192 * Removed OBJECT_CHECKING. This should be on DEBUG only, but we need to
195 * 227 5/11/98 4:33p Allender
196 * fixed ingame join problems -- started to work on new object updating
197 * code (currently ifdef'ed out)
199 * 226 5/01/98 12:59a Dave
200 * Put in some test code for a new object update system. Found the problem
201 * with the current system (low-level packet buffering). Gonna fix it :)
203 * 225 4/16/98 3:06p Adam
204 * reset net_signature when creating a new object so that the multi code
205 * doesn't see two objects with the same signature
207 * 224 4/14/98 11:11p John
208 * Made ships with < 50% hull left show electrical damage arcs.
210 * 223 4/12/98 9:56a John
211 * Made lighting detail flags work. Made explosions cast light on
214 * 222 4/03/98 12:24a Mike
215 * Comment out nprintfs.
217 * 221 4/01/98 9:21p John
218 * Made NDEBUG, optimized build with no warnings or errors.
220 * 220 4/01/98 1:48p Allender
221 * major changes to ship collision in multiplayer. Clients now do own
222 * ship/ship collisions (with their own ship only) Modifed the hull
223 * update packet to be sent quicker when object is target of player.
225 * 219 4/01/98 9:20a Mike
226 * Reduce MAX_SHIPS, MAX_OBJECTS and make MAX_AI_INFO same as MAX_SHIPS
228 * 217 3/26/98 10:36p Andsager
230 * 216 3/26/98 5:43p Lawrance
231 * rename ship_team_from_obj(), obj_team() and move to object lib
233 * 215 3/23/98 9:20a Andsager
234 * Remove all velocity updates in object code.
236 * 214 3/21/98 7:36p Lawrance
237 * Move jump nodes to own lib.
239 * 213 3/17/98 1:09p Andsager
240 * Don't update debris velocity in object code. was leading to
241 * fluctuating and increasing debris velocity (from numerical imprecision)
243 * 212 3/11/98 5:33p Lawrance
244 * Support rendering and targeting of jump nodes
246 * 211 3/09/98 10:56a Hoffoss
247 * Added jump node objects to Fred.
249 * 210 3/08/98 12:03p Allender
250 * changed how ship network signatures are handed out. Done at mission
251 * load time. Space reserved in wings for all waves/counts for their
252 * signatures. Fixed some secondary firing issues
254 * 209 3/06/98 10:35a Mike
255 * Make ships ramp up their warpout speed.
257 * 208 3/05/98 2:38p Mike
258 * Fix bug in obj_set_flags which didn't properly add collision pairs.
260 * 207 3/04/98 4:38p Mike
261 * Make weapon firing less framerate dependent. Also support cycling
262 * backwards through weapons with debug key.
264 * 206 3/03/98 1:00p John
265 * Fixed bug where asteroids weren't rotating for Glide.
267 * 205 3/02/98 5:42p John
268 * Removed WinAVI stuff from Freespace. Made all HUD gauges wriggle from
269 * afterburner. Made gr_set_clip work good with negative x &y. Made
270 * model_caching be on by default. Made each cached model have it's own
271 * bitmap id. Made asteroids not rotate when model_caching is on.
273 * 204 2/27/98 4:48p John
274 * Made objects keep track of number of pairs they have associated with
275 * them. Then, I can early out of the obj_remove_all which was 2.5% of
276 * frametime at beginning of sm2-2 which then is 0% after this.
278 * 203 2/23/98 8:59p Allender
279 * fixed two docking bugs: 1) don't move cargo when ship it's docked with
280 * is undocking. 2) aigoal code was clearing dock goals when it shouldn't
283 * 202 2/22/98 12:19p John
284 * Externalized some strings
286 * 201 2/19/98 11:18p Mike
287 * Make ships not come to an immediate stop when they have been disabled
288 * while awaiting repair.
290 * 200 2/19/98 10:51p John
291 * Enabled colored lighting for hardware (Glide)
293 * 199 2/19/98 12:46a Lawrance
294 * Further work on asteroids.
296 * 198 2/15/98 10:12p Allender
297 * fix up problems where ship flies away from repair ship too soon after
300 * 197 2/13/98 5:15p Allender
302 * 196 2/12/98 2:41p John
303 * Fixed bug I added the other day that caused all object created on the
304 * same frame to have two pairs.
306 * 195 2/09/98 10:44a John
307 * Made object pairs get created when they get added to the used_list, not
308 * when they get created.
310 * 194 2/06/98 12:00p Allender
311 * fixed some pretty darn embarassing code!
313 * 193 2/06/98 12:25a Mike
314 * More asteroid stuff.
316 * 192 2/05/98 9:41p Mike
317 * Asteroid work, intermediate checkin to resolve compile errors.
319 * 191 2/05/98 9:21p John
320 * Some new Direct3D code. Added code to monitor a ton of stuff in the
323 * 190 2/05/98 12:51a Mike
324 * Early asteroid stuff.
326 * 189 2/02/98 4:36p Mike
327 * Prevent damage from occurring between two ships during very last frame
328 * of warpout if docked and on opposite sides.
330 * 188 1/30/98 11:48a John
331 * Made debris arcs cast light. Added sound effects for them.
333 * 187 1/29/98 8:18a John
334 * Put in some commented out hooks for RGB lighting
336 * 186 1/23/98 5:08p John
337 * Took L out of vertex structure used B (blue) instead. Took all small
338 * fireballs out of fireball types and used particles instead. Fixed some
339 * debris explosion things. Restructured fireball code. Restructured
340 * some lighting code. Made dynamic lighting on by default. Made groups
341 * of lasers only cast one light. Made fireballs not cast light.
343 * 185 1/20/98 3:09p Dave
344 * Fixed a bug in observer movement caused by uninitialized data fix.
346 * 184 1/20/98 9:47a Mike
347 * Suppress optimized compiler warnings.
348 * Some secondary weapon work.
350 * 183 1/19/98 10:01p Lawrance
351 * Implement "Electronics" missiles
353 * 182 1/17/98 4:45p Mike
354 * Better support for AI selection of secondary weapons.
356 * 181 1/16/98 11:43a Mike
357 * Fix countermeasures.
359 * 180 1/14/98 5:21p Allender
360 * system to delete object when buffer is nearly full. System in place to
361 * delete weapons when nearly out of weapons slots
363 * 179 1/13/98 8:09p John
364 * Removed the old collision system that checked all pairs. Added code
365 * to disable collisions and particles.
367 * 178 1/13/98 5:50p Andsager
368 * Deathroll rotvel is now ramped up to using standard physics code.
369 * After death, controls are no longer read and deathroll_rotvel is set in
370 * ship\ship_dying_frame.cpp
372 * 177 1/12/98 5:21p Dave
373 * Put in a bunch of multiplayer sequencing code. Made weapon/ship select
374 * work through the standalone.
376 * 176 12/29/97 9:48p Mike
377 * When two ships of equivalent class are docked together, move according
378 * to the faster moving one.
380 * 175 12/22/97 9:14p Allender
381 * fix up some code relating to afterburners in multiplayer. Clients now
382 * control their own afterburners
384 * 174 12/22/97 1:42a Lawrance
385 * Change in set_shield_strength() avoid weird rounding error
387 * 173 12/12/97 1:43p John
388 * took out old debug light code
390 * 172 12/11/97 5:46p Hoffoss
391 * Changed Fred to not display weapons that are not available to various
394 * 171 12/09/97 11:36p Allender
395 * made clients determine their own positions
397 * 170 12/04/97 9:20a John
399 * 169 12/03/97 3:17p Andsager
400 * Reset of physics flags for engine moved to rearm and repair.
405 #include <string.h> // for memset
412 #include "fireballs.h"
417 #include "linklist.h"
418 #include "freespace.h"
420 #include "objectsnd.h"
423 #include "cmeasure.h"
425 #include "systemvars.h"
427 #include "shockwave.h"
428 #include "afterburner.h"
431 #include "multiutil.h"
432 #include "objcollide.h"
433 #include "lighting.h"
434 #include "observer.h"
435 #include "asteroid.h"
437 #include "jumpnode.h"
447 object obj_free_list;
448 object obj_used_list;
449 object obj_create_list;
451 object *Player_obj = NULL;
452 object *Viewer_obj = NULL;
457 object Objects[MAX_OBJECTS];
460 typedef struct checkobject
468 checkobject CheckObjects[MAX_OBJECTS];
472 int Highest_object_index=-1;
473 int Highest_ever_object_index=0;
474 int Object_next_signature = 1; //0 is bogus, start at 1
475 int Object_next_ship_signature = OBJECT_SIG_SHIP_START;
476 int Object_inited = 0;
477 int Show_waypoints = 0;
480 char *Object_type_names[MAX_OBJECT_TYPES] = {
502 //-----------------------------------------------------------------------------
503 // Scan the object list, freeing down to num_used objects
504 // Returns number of slots freed.
505 int free_object_slots(int num_used)
507 int i, olind, deleted_weapons;
508 int obj_list[MAX_OBJECTS];
509 int num_already_free, num_to_free, original_num_to_free;
514 // calc num_already_free by walking the obj_free_list
515 num_already_free = 0;
516 for ( objp = GET_FIRST(&obj_free_list); objp != END_OF_LIST(&obj_free_list); objp = GET_NEXT(objp) )
519 if (MAX_OBJECTS - num_already_free < num_used)
522 for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
523 if (objp->flags & OF_SHOULD_BE_DEAD) {
525 if (MAX_OBJECTS - num_already_free < num_used)
526 return num_already_free;
528 switch (objp->type) {
531 if (MAX_OBJECTS - num_already_free < num_used)
538 obj_list[olind++] = OBJ_INDEX(objp);
554 Int3(); // Hey, what kind of object is this? Unknown!
560 num_to_free = MAX_OBJECTS - num_used - num_already_free;
561 original_num_to_free = num_to_free;
563 if (num_to_free > olind) {
564 nprintf(("allender", "Warning: Asked to free %i objects, but can only free %i.\n", num_to_free, olind));
568 for (i=0; i<num_to_free; i++)
569 if ( (Objects[obj_list[i]].type == OBJ_DEBRIS) && (Debris[Objects[obj_list[i]].instance].flags & DEBRIS_EXPIRE) ) {
571 nprintf(("allender", "Freeing DEBRIS object %3i\n", obj_list[i]));
572 Objects[obj_list[i]].flags |= OF_SHOULD_BE_DEAD;
576 return original_num_to_free;
578 //JAS - I removed this because small fireballs are now particles, which aren't objects.
579 //JAS for (i=0; i<num_to_free; i++)
580 //JAS if ( (Objects[obj_list[i]].type == OBJ_FIREBALL) && (Fireball_data[Objects[obj_list[i]].instance].type == FIREBALL_TYPE_SMALL) ) {
582 //JAS nprintf(("allender", "Freeing FIREBALL object %3i\n", obj_list[i]));
583 //JAS Objects[obj_list[i]].flags |= OF_SHOULD_BE_DEAD;
586 //JAS if (!num_to_free)
587 //JAS return original_num_to_free;
589 for (i=0; i<num_to_free; i++) {
590 object *tmp_obj = &Objects[obj_list[i]];
591 if ( (tmp_obj->type == OBJ_FIREBALL) && (fireball_is_perishable(tmp_obj)) ) {
593 nprintf(("allender", "Freeing FIREBALL object %3i\n", obj_list[i]));
594 tmp_obj->flags |= OF_SHOULD_BE_DEAD;
599 return original_num_to_free;
602 deleted_weapons = collide_remove_weapons();
603 num_to_free -= deleted_weapons;
605 return original_num_to_free;
608 for (i=0; i<num_to_free; i++){
609 if ( Objects[obj_list[i]].type == OBJ_WEAPON ) {
611 Objects[obj_list[i]].flags |= OF_SHOULD_BE_DEAD;
616 return original_num_to_free;
619 return original_num_to_free - num_to_free;
624 float get_shield_strength(object *objp)
631 // no shield system, no strength!
632 if ( objp->flags & OF_NO_SHIELDS ){
636 for (i=0; i<MAX_SHIELD_SECTIONS; i++){
637 strength += objp->shields[i];
643 void set_shield_strength(object *objp, float strength)
647 if ( (strength - Ship_info[Ships[objp->instance].ship_info_index].shields) > 0.1 ){
651 for (i=0; i<MAX_SHIELD_SECTIONS; i++){
652 objp->shields[i] = strength/MAX_SHIELD_SECTIONS;
656 // Recharge whole shield.
657 // Apply delta/MAX_SHIELD_SECTIONS to each shield section.
658 void add_shield_strength(object *objp, float delta)
663 section_max = Ship_info[Ships[objp->instance].ship_info_index].shields/MAX_SHIELD_SECTIONS;
665 for (i=0; i<MAX_SHIELD_SECTIONS; i++) {
666 objp->shields[i] += delta/MAX_SHIELD_SECTIONS;
667 if (objp->shields[i] > section_max)
668 objp->shields[i] = section_max;
669 else if (objp->shields[i] < 0.0f)
670 objp->shields[i] = 0.0f;
675 //sets up the free list & init player & whatever else
682 memset( Objects, 0, sizeof(object)*MAX_OBJECTS );
685 list_init( &obj_free_list );
686 list_init( &obj_used_list );
687 list_init( &obj_create_list );
689 // Link all object slots into the free list
691 for (i=0; i<MAX_OBJECTS; i++) {
692 objp->type = OBJ_NONE;
693 objp->signature = i + 100;
695 // zero all object sounds
696 for(idx=0; idx<MAX_OBJECT_SOUNDS; idx++){
697 objp->objsnd_num[idx] = -1;
700 list_append(&obj_free_list, objp);
704 Object_next_signature = 1; //0 is invalid, others start at 1
705 Object_next_ship_signature = OBJECT_SIG_SHIP_START;
707 Highest_object_index = 0;
712 int num_objects_hwm = 0;
714 //returns the number of a free object, updating Highest_object_index.
715 //Generally, obj_create() should be called to get an object, since it
716 //fills in important fields and does the linking.
717 //returns -1 if no free objects
718 int obj_allocate(void)
723 if (!Object_inited) obj_init();
725 if ( num_objects >= MAX_OBJECTS-10 ) {
728 num_freed = free_object_slots(MAX_OBJECTS-10);
729 nprintf(("warning", " *** Freed %i objects\n", num_freed));
732 if (num_objects >= MAX_OBJECTS) {
734 mprintf(("Object creation failed - too many objects!\n" ));
739 // Find next available object
740 objp = GET_FIRST(&obj_free_list);
741 Assert ( objp != &obj_free_list ); // shouldn't have the dummy element
743 // remove objp from the free list
744 list_remove( &obj_free_list, objp );
746 // insert objp onto the end of create list
747 list_append( &obj_create_list, objp );
752 if (num_objects > num_objects_hwm) {
753 //nprintf(("AI", "*** MAX Num Objects = %i\n", num_objects));
754 num_objects_hwm = num_objects;
758 objnum = OBJ_INDEX(objp);
760 if (objnum > Highest_object_index) {
761 Highest_object_index = objnum;
762 if (Highest_object_index > Highest_ever_object_index)
763 Highest_ever_object_index = Highest_object_index;
769 //frees up an object. Generally, obj_delete() should be called to get
770 //rid of an object. This function deallocates the object entry after
771 //the object has been unlinked
772 void obj_free(int objnum)
776 if (!Object_inited) obj_init();
778 Assert( objnum >= 0 ); // Trying to free bogus object!!!
780 // get object pointer
781 objp = &Objects[objnum];
783 // remove objp from the used list
784 list_remove( &obj_used_list, objp);
786 // add objp to the end of the free
787 list_append( &obj_free_list, objp );
792 Objects[objnum].type = OBJ_NONE;
794 Assert(num_objects >= 0);
796 if (objnum == Highest_object_index)
797 while (Objects[--Highest_object_index].type == OBJ_NONE);
801 //initialize a new object. adds to the list for the given segment.
802 //returns the object number. The object will be a non-rendering, non-physics
803 //object. Pass -1 if no parent.
804 int obj_create(ubyte type,int parent_obj,int instance, matrix * orient,
805 vector * pos, float radius, uint flags )
810 // Find next free object
811 objnum = obj_allocate();
813 if (objnum == -1) //no free objects
816 obj = &Objects[objnum];
817 Assert(obj->type == OBJ_NONE); //make sure unused
819 // Zero out object structure to keep weird bugs from happening
820 // in uninitialized fields.
821 // memset( obj, 0, sizeof(object) );
823 if(obj->type == OBJ_SHIP){
824 obj->signature = Object_next_ship_signature++;
826 if (!Object_next_ship_signature){
827 Object_next_ship_signature = OBJECT_SIG_SHIP_START; // 0 is bogus!
830 obj->signature = Object_next_signature++;
832 if (!Object_next_signature){
833 Object_next_signature = 1; // 0 is bogus!
838 obj->instance = instance;
839 obj->parent = parent_obj;
840 if (obj->parent != -1) {
841 obj->parent_sig = Objects[parent_obj].signature;
842 obj->parent_type = Objects[parent_obj].type;
844 obj->parent_sig = obj->signature;
845 obj->parent_type = obj->type;
848 obj->flags = flags | OF_NOT_IN_COLL;
851 obj->last_pos = *pos;
854 obj->orient = orient?*orient:vmd_identity_matrix;
855 obj->last_orient = obj->orient;
856 obj->radius = radius;
858 obj->flags &= ~OF_INVULNERABLE; // Make vulnerable.
859 physics_init( &obj->phys_info );
861 for(idx=0; idx<MAX_OBJECT_SOUNDS; idx++){
862 obj->objsnd_num[idx] = -1;
865 obj->net_signature = 0; // be sure to reset this value so new objects don't take on old signatures.
870 //remove object from the world
871 // If Player_obj, don't remove it!
872 void obj_delete(int objnum)
876 Assert(objnum >= 0 && objnum < MAX_OBJECTS);
877 objp = &Objects[objnum];
878 Assert(objp->type != OBJ_NONE);
880 // Remove all object pairs
881 obj_remove_pairs( objp );
883 switch( objp->type ) {
885 weapon_delete( objp );
888 if ((objp == Player_obj) && !Fred_running) {
889 objp->type = OBJ_GHOST;
890 objp->flags &= ~(OF_SHOULD_BE_DEAD);
892 // we have to traverse the ship_obj list and remove this guy from it as well
893 ship_obj *moveup = GET_FIRST(&Ship_obj_list);
894 while(moveup != END_OF_LIST(&Ship_obj_list)){
895 if(OBJ_INDEX(objp) == moveup->objnum){
896 list_remove(&Ship_obj_list,moveup);
899 moveup = GET_NEXT(moveup);
902 physics_init(&objp->phys_info);
904 obj_snd_delete(OBJ_INDEX(objp));
910 fireball_delete( objp );
913 shockwave_delete( objp );
919 Assert(Fred_running);
920 break; // requires no action, handled by the Fred code.
922 debris_delete( objp );
925 asteroid_delete(objp);
928 cmeasure_delete( objp );
931 if((!Game_mode & GM_MULTIPLAYER)){
932 mprintf(("Warning: Tried to delete a ghost!"));
933 objp->flags &= ~OF_SHOULD_BE_DEAD;
936 // we need to be able to delete GHOST objects in multiplayer to allow for player respawns.
937 nprintf(("Network","Deleting GHOST object\n"));
941 observer_delete(objp);
949 Error( LOCATION, "Unhandled object type %d in obj_delete_all_that_should_be_dead", objp->type );
952 // if a persistant sound has been created, delete it
953 obj_snd_delete(OBJ_INDEX(objp));
955 objp->type = OBJ_NONE; //unused!
962 // ------------------------------------------------------------------------------------------------------------------
963 void obj_delete_all_that_should_be_dead()
967 if (!Object_inited) obj_init();
970 objp = GET_FIRST(&obj_used_list);
971 while( objp !=END_OF_LIST(&obj_used_list) ) {
972 temp = GET_NEXT(objp);
973 if ( objp->flags&OF_SHOULD_BE_DEAD )
974 obj_delete( OBJ_INDEX(objp) ); // MWA says that john says that let obj_delete handle everything because of the editor
980 // Add all newly created objects to the end of the used list and create their
981 // object pairs for collision detection
982 void obj_merge_created_list(void)
984 // The old way just merged the two. This code takes one out of the create list,
985 // creates object pairs for it, and then adds it to the used list.
986 // OLD WAY: list_merge( &obj_used_list, &obj_create_list );
987 object *objp = GET_FIRST(&obj_create_list);
988 while( objp !=END_OF_LIST(&obj_create_list) ) {
989 list_remove( obj_create_list, objp );
991 // Add it to the object pairs array
992 obj_add_pairs(OBJ_INDEX(objp));
994 // Then add it to the object used list
995 list_append( &obj_used_list, objp );
997 objp = GET_FIRST(&obj_create_list);
1000 // Make sure the create list is empty.
1001 list_init(&obj_create_list);
1004 int physics_paused = 0, ai_paused = 0;
1006 extern void call_doa(object *obj1, object *obj2, ship_info *sip1);
1008 // If this is a cargo container or a repair ship, move it along with the ship it's docked to.
1009 void move_docked_objects(object *objp)
1014 if (objp->type != OBJ_SHIP)
1017 Assert((objp->instance >= 0) && (objp->instance < MAX_SHIPS));
1019 aip = &Ai_info[Ships[objp->instance].ai_index];
1021 if (aip->ai_flags & AIF_DOCKED) {
1023 sip = &Ship_info[Ships[objp->instance].ship_info_index];
1024 if ((sip->flags & SIF_SUPPORT) || (sip->flags & SIF_CARGO)) {
1025 Assert(!((sip->flags & SIF_SUPPORT) && (sip->flags & SIF_CARGO))); // Ship can't be both repair and cargo
1026 if (aip->dock_objnum != -1) {
1027 if (aip->mode == AIM_DOCK) {
1028 if (aip->submode < AIS_UNDOCK_1)
1029 call_doa(objp, &Objects[aip->dock_objnum], sip);
1031 // if I am not in dock mode then I need to check the guy that I'm docked with
1032 // and only move with him if he isn't undocking.
1033 other_aip = &Ai_info[Ships[Objects[aip->dock_objnum].instance].ai_index];
1034 if ( other_aip->mode == AIM_DOCK ) {
1035 if (other_aip->submode < AIS_UNDOCK_1 )
1036 call_doa(objp, &Objects[aip->dock_objnum], sip);
1038 call_doa(objp, &Objects[aip->dock_objnum], sip);
1043 if (aip->dock_objnum != -1) {
1044 Assert( aip->dock_objnum != -1 );
1045 other_aip = &Ai_info[Ships[Objects[aip->dock_objnum].instance].ai_index];
1047 // if the other object that I am docked with is undocking, then don't do anything.
1048 if ( !((other_aip->mode == AIM_DOCK) && (other_aip->submode >= AIS_UNDOCK_1)) ) {
1049 if ( (aip->mode != AIM_DOCK) && (aip->mode != AIM_WARP_OUT) ) {
1050 object *objp1, *objp2;
1052 objp1 = &Objects[aip->dock_objnum];
1055 if (objp1->phys_info.speed > objp2->phys_info.speed) {
1061 //nprintf(("AI", "Calling doa, frame %i: %s, %s\n", Framecount, Ships[objp1->instance].ship_name, Ships[objp2->instance].ship_name));
1062 call_doa(objp1, objp2, sip);
1071 float Last_fire_time = 0.0f;
1072 int Avg_delay_count = 0;
1073 float Avg_delay_total;
1076 // function to deal with firing player things like lasers, missiles, etc.
1077 // separated out because of multiplayer issues.
1078 void obj_player_fire_stuff( object *objp, control_info ci )
1082 Assert( objp->flags & OF_PLAYER_SHIP);
1084 // try and get the ship pointer
1086 if((objp->type == OBJ_SHIP) && (objp->instance >= 0) && (objp->instance < MAX_SHIPS)){
1087 shipp = &Ships[objp->instance];
1090 // single player pilots, and all players in multiplayer take care of firing their own primaries
1091 if(!(Game_mode & GM_MULTIPLAYER) || (objp == Player_obj)){
1092 if ( ci.fire_primary_count ) {
1093 // flag the ship as having the trigger down
1095 shipp->flags |= SF_TRIGGER_DOWN;
1098 // fire non-streaming primaries here
1099 ship_fire_primary( objp, 0 );
1101 // unflag the ship as having the trigger down
1103 shipp->flags &= ~(SF_TRIGGER_DOWN);
1107 if ( ci.fire_countermeasure_count ){
1108 ship_launch_countermeasure( objp );
1112 // single player and multiplayer masters do all of the following
1113 if ( !MULTIPLAYER_CLIENT ) {
1114 if ( ci.fire_secondary_count ){
1115 ship_fire_secondary( objp );
1117 // kill the secondary count
1118 ci.fire_secondary_count = 0;
1122 // everyone does the following for their own ships.
1123 if ( ci.afterburner_start ){
1124 if (ship_get_subsystem_strength(&Ships[objp->instance], SUBSYSTEM_ENGINE)){
1125 afterburners_start( objp );
1129 if ( ci.afterburner_stop ){
1130 afterburners_stop( objp, 1 );
1134 void obj_move_call_physics(object *objp, float frametime)
1136 // Do physics for objects with OF_PHYSICS flag set and with some engine strength remaining.
1137 if ( objp->flags & OF_PHYSICS ) {
1138 // only set phys info if ship is not dead
1139 if ((objp->type == OBJ_SHIP) && !(Ships[objp->instance].flags & SF_DYING)) {
1140 float engine_strength;
1141 engine_strength = ship_get_subsystem_strength(&Ships[objp->instance], SUBSYSTEM_ENGINE);
1142 if ( ship_subsys_disrupted(&Ships[objp->instance], SUBSYSTEM_ENGINE) ) {
1143 engine_strength=0.0f;
1146 if (engine_strength == 0.0f) { // All this is necessary to make ship gradually come to a stop after engines are blown.
1147 vm_vec_zero(&objp->phys_info.desired_vel);
1148 vm_vec_zero(&objp->phys_info.desired_rotvel);
1149 objp->phys_info.flags |= (PF_REDUCED_DAMP | PF_DEAD_DAMP);
1150 objp->phys_info.side_slip_time_const = Ship_info[Ships[objp->instance].ship_info_index].damp * 4.0f;
1152 // DA: comment out lines that resets PF_DEAD_DAMP after every frame.
1153 // This is now reset during engine repair.
1154 // objp->phys_info.flags &= ~(PF_REDUCED_DAMP | PF_DEAD_DAMP);
1155 // objp->phys_info.side_slip_time_const = Ship_info[Ships[objp->instance].ship_info_index].damp;
1159 // if a weapon is flagged as dead, kill its engines just like a ship
1160 if((objp->type == OBJ_WEAPON) && (Weapons[objp->instance].weapon_flags & WF_DEAD_IN_WATER)){
1161 vm_vec_zero(&objp->phys_info.desired_vel);
1162 vm_vec_zero(&objp->phys_info.desired_rotvel);
1163 objp->phys_info.flags |= (PF_REDUCED_DAMP | PF_DEAD_DAMP);
1164 objp->phys_info.side_slip_time_const = Ship_info[Ships[objp->instance].ship_info_index].damp * 4.0f;
1167 if (physics_paused) {
1168 if (objp==Player_obj){
1169 physics_sim(&objp->pos, &objp->orient, &objp->phys_info, frametime ); // simulate the physics
1172 // Hack for dock mode.
1173 // If docking with a ship, we don't obey the normal ship physics, we can slew about.
1174 if (objp->type == OBJ_SHIP) {
1175 ai_info *aip = &Ai_info[Ships[objp->instance].ai_index];
1177 // Note: This conditional for using PF_USE_VEL (instantaneous acceleration) is probably too loose.
1178 // A ships awaiting support will fly towards the support ship with instantaneous acceleration.
1179 // But we want to have ships in the process of docking have quick acceleration, or they overshoot their goals.
1180 // Probably can not key off dock_objnum, but then need to add some other condition. Live with it for now. -- MK, 2/19/98
1181 if ((aip->dock_objnum != -1) ||
1182 ((aip->mode == AIM_DOCK) && ((aip->submode == AIS_DOCK_2) || (aip->submode == AIS_DOCK_3) || (aip->submode == AIS_UNDOCK_0))) ||
1183 ((aip->mode == AIM_WARP_OUT) && (aip->submode >= AIS_WARP_3))) {
1184 if (ship_get_subsystem_strength(&Ships[objp->instance], SUBSYSTEM_ENGINE) > 0.0f){
1185 objp->phys_info.flags |= PF_USE_VEL;
1187 objp->phys_info.flags &= ~PF_USE_VEL; // If engine blown, don't PF_USE_VEL, or ships stop immediately
1190 objp->phys_info.flags &= ~PF_USE_VEL;
1194 // in multiplayer, if this object was just updatd (i.e. clients send their own positions),
1195 // then reset the flag and don't move the object.
1196 if ( MULTIPLAYER_MASTER && (objp->flags & OF_JUST_UPDATED) ) {
1197 objp->flags &= ~OF_JUST_UPDATED;
1198 goto obj_maybe_fire;
1201 if ( (objp->type == OBJ_ASTEROID) && (Model_caching && (!D3D_enabled) ) ) {
1202 // If we're doing model caching, don't rotate asteroids
1203 vector tmp = objp->phys_info.rotvel;
1205 objp->phys_info.rotvel = vmd_zero_vector;
1206 physics_sim(&objp->pos, &objp->orient, &objp->phys_info, frametime ); // simulate the physics
1207 objp->phys_info.rotvel = tmp;
1209 physics_sim(&objp->pos, &objp->orient, &objp->phys_info, frametime ); // simulate the physics
1212 // This code seems to have no effect - DB 1/12/99
1213 //if ( MULTIPLAYER_CLIENT && (objp != Player_obj) ){
1217 // if the object is the player object, do things that need to be done after the ship
1218 // is moved (like firing weapons, etc). This routine will get called either single
1219 // or multiplayer. We must find the player object to get to the control info field
1221 if ( (objp->flags & OF_PLAYER_SHIP) && (objp->type != OBJ_OBSERVER) && (objp == Player_obj)) {
1225 obj_player_fire_stuff( objp, pp->ci );
1229 // fire streaming weapons for ships in here - ALL PLAYERS, regardless of client, single player, server, whatever.
1230 // do stream weapon firing for all ships themselves.
1231 if(objp->type == OBJ_SHIP){
1232 ship_fire_primary(objp, 1, 0);
1239 #define IMPORTANT_FLAGS (OF_COLLIDES)
1244 void obj_check_object( object *obj )
1246 int objnum = OBJ_INDEX(obj);
1248 // PROGRAMMERS: If one of these Int3() gets hit, then someone
1249 // is changing a value in the object structure that might cause
1250 // collision detection to not work. See John for more info if
1251 // you are hitting one of these.
1253 if ( CheckObjects[objnum].type != obj->type ) {
1254 if ( (obj->type==OBJ_WAYPOINT) && (CheckObjects[objnum].type==OBJ_SHIP) ) {
1255 // We know about ships changing into waypoints and that is
1257 CheckObjects[objnum].type = OBJ_WAYPOINT;
1258 } else if ( (obj->type==OBJ_SHIP) && (CheckObjects[objnum].type==OBJ_GHOST) ) {
1259 // We know about player changing into a ghost after dying and that is
1261 CheckObjects[objnum].type = OBJ_GHOST;
1262 } else if ( (obj->type==OBJ_GHOST) && (CheckObjects[objnum].type==OBJ_SHIP) ) {
1263 // We know about player changing into a ghost after dying and that is
1265 CheckObjects[objnum].type = OBJ_SHIP;
1267 mprintf(( "Object type changed!\n" ));
1271 if ( CheckObjects[objnum].signature != obj->signature ) {
1272 mprintf(( "Object signature changed!\n" ));
1275 if ( (CheckObjects[objnum].flags&IMPORTANT_FLAGS) != (obj->flags&IMPORTANT_FLAGS) ) {
1276 mprintf(( "Object flags changed!\n" ));
1279 if ( CheckObjects[objnum].parent_sig != obj->parent_sig ) {
1280 mprintf(( "Object parent sig changed!\n" ));
1283 if ( CheckObjects[objnum].parent_type != obj->parent_type ) {
1284 mprintf(( "Object's parent type changed!\n" ));
1290 // Call this if you want to change an object flag so that the
1291 // object code knows what's going on. For instance if you turn
1292 // off OF_COLLIDES, the object code needs to know this in order to
1293 // actually turn the object collision detection off. By calling
1294 // this you shouldn't get Int3's in the checkobject code. If you
1295 // do, then put code in here to correctly handle the case.
1296 void obj_set_flags( object *obj, uint new_flags )
1298 int objnum = OBJ_INDEX(obj);
1300 // turning collision detection off
1301 if ( (obj->flags & OF_COLLIDES) && (!(new_flags&OF_COLLIDES))) {
1302 // Remove all object pairs
1303 obj_remove_pairs( obj );
1305 // update object flags properly
1306 obj->flags = new_flags;
1307 obj->flags |= OF_NOT_IN_COLL;
1309 CheckObjects[objnum].flags = new_flags;
1310 CheckObjects[objnum].flags |= OF_NOT_IN_COLL;
1316 // turning collision detection on
1317 if ( (!(obj->flags & OF_COLLIDES)) && (new_flags&OF_COLLIDES) ) {
1319 // observers can't collide or be hit, and they therefore have no hit or collide functions
1320 // So, don't allow this bit to be set
1321 if(obj->type == OBJ_OBSERVER){
1322 mprintf(("Illegal to set collision bit for OBJ_OBSERVER!!\n"));
1326 obj->flags |= OF_COLLIDES;
1328 // Turn on collision detection
1329 obj_add_pairs(objnum);
1331 obj->flags = new_flags;
1332 obj->flags &= ~(OF_NOT_IN_COLL);
1334 CheckObjects[objnum].flags = new_flags;
1335 CheckObjects[objnum].flags &= ~(OF_NOT_IN_COLL);
1340 // for a multiplayer host -- use this debug code to help trap when non-player ships are getting
1341 // marked as OF_COULD_BE_PLAYER
1342 // this code is pretty much debug code and shouldn't be relied on to always do the right thing
1343 // for flags other than
1344 if ( MULTIPLAYER_MASTER && !(obj->flags & OF_COULD_BE_PLAYER) && (new_flags & OF_COULD_BE_PLAYER) ) {
1348 // this flag sometimes gets set for observers.
1349 if ( obj->type == OBJ_OBSERVER ) {
1354 if ( (obj->type != OBJ_SHIP) || (obj->instance < 0) ) {
1356 return; // return because we really don't want to set the flag
1359 // see if this ship is really a player ship (or should be)
1360 shipp = &Ships[obj->instance];
1361 extern void multi_ts_get_team_and_slot(char *, int *, int *);
1362 multi_ts_get_team_and_slot(shipp->ship_name,&team,&slot);
1363 if ( (shipp->wingnum == -1) || (team == -1) || (slot==-1) ) {
1369 obj->flags = new_flags;
1371 CheckObjects[objnum].flags = new_flags;
1377 // Check for unhandled flag changing
1378 if ( (new_flags&IMPORTANT_FLAGS) != (obj->flags&IMPORTANT_FLAGS) ) {
1379 mprintf(( "Unhandled flag changing in obj_set_flags!!\n" ));
1380 mprintf(( "Add code to support it, see John for questions!!\n" ));
1383 // Since it wasn't an important flag, just bash it.
1384 obj->flags = new_flags;
1386 CheckObjects[objnum].flags = new_flags;
1392 void obj_move_all_pre(object *objp, float frametime)
1394 switch( objp->type ) {
1396 if (!physics_paused){
1397 weapon_process_pre( objp, frametime );
1401 if (!physics_paused || (objp==Player_obj )){
1402 ship_process_pre( objp, frametime );
1406 if (!physics_paused){
1407 fireball_process_pre(objp,frametime);
1411 // all shockwaves are moved via shockwave_move_all()
1414 if (!physics_paused){
1415 debris_process_pre(objp,frametime);
1419 if (!physics_paused){
1420 asteroid_process_pre(objp,frametime);
1424 if (!physics_paused){
1425 cmeasure_process_pre(objp, frametime);
1429 break; // waypoints don't move..
1441 Error( LOCATION, "Unhandled object type %d in obj_move_one\n", objp->type );
1445 // Used to tell if a particular group of lasers has cast light yet.
1446 ubyte Obj_weapon_group_id_used[WEAPON_MAX_GROUP_IDS];
1448 // Called once a frame to mark all weapon groups as not having cast light yet.
1449 void obj_clear_weapon_group_id_list()
1451 memset( Obj_weapon_group_id_used, 0, sizeof(Obj_weapon_group_id_used) );
1454 int Arc_light = 1; // If set, electrical arcs on debris cast light
1455 DCF_BOOL(arc_light, Arc_light)
1457 void obj_move_all_post(object *objp, float frametime)
1459 switch( objp->type ) {
1461 if (!physics_paused) {
1462 weapon_process_post( objp, frametime );
1465 if ( Detail.lighting > 2 ) {
1466 // Weapons cast light
1468 int group_id = Weapons[objp->instance].group_id;
1471 if ( (group_id>-1) && (Obj_weapon_group_id_used[group_id]==0) ) {
1472 // Mark this group as done
1473 Obj_weapon_group_id_used[group_id]++;
1475 // This group has already done its light casting
1480 if ( D3D_enabled ) {
1481 weapon_info * wi = &Weapon_info[Weapons[objp->instance].weapon_info_index];
1483 if ( wi->render_type == WRT_LASER ) {
1487 // get the laser color
1488 weapon_get_laser_color(&c, objp);
1490 r = i2fl(c.red)/255.0f;
1491 g = i2fl(c.green)/255.0f;
1492 b = i2fl(c.blue)/255.0f;
1493 light_add_point( &objp->pos, 10.0f, 20.0f, 1.0f, r, g, b, objp->parent );
1494 //light_add_point( &objp->pos, 10.0f, 20.0f, 1.0f, 0.0f, 0.0f, 1.0f, objp->parent );
1496 light_add_point( &objp->pos, 10.0f, 20.0f, 1.0f, 1.0f, 1.0f, 1.0f, objp->parent );
1499 light_add_point( &objp->pos, 10.0f, 20.0f, 1.0f, 1.0f, 1.0f, 1.0f, objp->parent );
1505 if (!physics_paused || (objp==Player_obj ))
1506 ship_process_post( objp, frametime );
1508 // Make any electrical arcs on ships cast light
1510 if ( Detail.lighting > 2 ) {
1513 shipp = &Ships[objp->instance];
1515 for (i=0; i<MAX_SHIP_ARCS; i++ ) {
1516 if ( timestamp_valid( shipp->arc_timestamp[i] ) ) {
1517 // Move arc endpoints into world coordinates
1519 vm_vec_unrotate(&tmp1,&shipp->arc_pts[i][0],&objp->orient);
1520 vm_vec_add2(&tmp1,&objp->pos);
1522 vm_vec_unrotate(&tmp2,&shipp->arc_pts[i][1],&objp->orient);
1523 vm_vec_add2(&tmp2,&objp->pos);
1525 light_add_point( &tmp1, 10.0f, 20.0f, frand(), 1.0f, 1.0f, 1.0f, -1 );
1526 light_add_point( &tmp2, 10.0f, 20.0f, frand(), 1.0f, 1.0f, 1.0f, -1 );
1534 if (!physics_paused) {
1535 fireball_process_post(objp,frametime);
1537 if ( Detail.lighting > 3 ) {
1538 // Make explosions cast light
1539 float p = fireball_lifeleft_percent(objp);
1544 // P goes from 0 to 1 to 0 over the life of the explosion
1545 float rad = p*(1.0f+frand()*0.05f)*objp->radius;
1547 light_add_point( &objp->pos, rad*2.0f, rad*5.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1 );
1551 // all shockwaves are moved via shockwave_move_all()
1554 if (!physics_paused)
1555 debris_process_post(objp,frametime);
1557 // Make any electrical arcs on debris cast light
1559 if ( Detail.lighting > 2 ) {
1562 db = &Debris[objp->instance];
1564 for (i=0; i<MAX_DEBRIS_ARCS; i++ ) {
1565 if ( timestamp_valid( db->arc_timestamp[i] ) ) {
1566 // Move arc endpoints into world coordinates
1568 vm_vec_unrotate(&tmp1,&db->arc_pts[i][0],&objp->orient);
1569 vm_vec_add2(&tmp1,&objp->pos);
1571 vm_vec_unrotate(&tmp2,&db->arc_pts[i][1],&objp->orient);
1572 vm_vec_add2(&tmp2,&objp->pos);
1574 light_add_point( &tmp1, 10.0f, 20.0f, frand(), 1.0f, 1.0f, 1.0f, -1 );
1575 light_add_point( &tmp2, 10.0f, 20.0f, frand(), 1.0f, 1.0f, 1.0f, -1 );
1582 if (!physics_paused)
1583 asteroid_process_post(objp, frametime);
1586 if (!physics_paused)
1587 cmeasure_process_post(objp, frametime);
1590 break; // waypoints don't move..
1594 void observer_process_post(object *objp);
1595 observer_process_post(objp);
1598 radar_plot_object(objp);
1606 Error( LOCATION, "Unhandled object type %d in obj_move_one\n", objp->type );
1611 int Collisions_enabled = 1;
1613 DCF_BOOL( collisions, Collisions_enabled )
1615 MONITOR( NumObjects );
1617 //--------------------------------------------------------------------
1618 //move all objects for the current frame
1619 void obj_move_all(float frametime)
1623 obj_delete_all_that_should_be_dead();
1625 obj_merge_created_list();
1627 // Clear the table that tells which groups of weapons have cast light so far.
1628 if(!(Game_mode & GM_MULTIPLAYER) || (MULTIPLAYER_MASTER)){
1629 obj_clear_weapon_group_id_list();
1632 MONITOR_INC( NumObjects, num_objects );
1634 objp = GET_FIRST(&obj_used_list);
1635 while( objp !=END_OF_LIST(&obj_used_list) ) {
1636 // skip objects which should be dead
1637 if ( !(objp->flags&OF_SHOULD_BE_DEAD) ) {
1638 vector cur_pos = objp->pos; // Save the current position
1640 // if this is an observer object, skip it
1641 if(objp->type == OBJ_OBSERVER){
1642 objp = GET_NEXT(objp);
1646 // if we're playing a demo back, only sim stuff that we're supposed to
1647 if((Game_mode & GM_DEMO_PLAYBACK) && !demo_should_sim(objp)){
1648 objp = GET_NEXT(objp);
1653 // if(! ((Game_mode & GM_MULTIPLAYER) && (Net_player != NULL) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER)) ){
1654 obj_check_object( objp );
1659 obj_move_all_pre(objp, frametime);
1661 // store last pos and orient
1662 objp->last_pos = cur_pos;
1663 objp->last_orient = objp->orient;
1665 // if this is an object which should be interpolated in multiplayer, do so
1666 if(multi_oo_is_interp_object(objp)){
1667 multi_oo_interp(objp);
1670 obj_move_call_physics(objp, frametime);
1674 obj_move_all_post(objp, frametime);
1676 objp = GET_NEXT(objp);
1679 // After all objects have been moved, move all docked objects.
1680 if(!(Game_mode & GM_DEMO_PLAYBACK)){
1681 objp = GET_FIRST(&obj_used_list);
1682 while( objp !=END_OF_LIST(&obj_used_list) ) {
1683 if (objp->type == OBJ_SHIP){
1684 move_docked_objects(objp);
1687 // unflag all objects as being updates
1688 objp->flags &= ~OF_JUST_UPDATED;
1690 objp = GET_NEXT(objp);
1694 // Now that all objects have moved, we should calculate the
1695 // velocities from how far they moved.
1696 // DA: Commented out 2/23, unnecessary since colliding objects calculate their post collision velocities through physics.
1698 objp = GET_FIRST(&obj_used_list);
1699 while( objp !=END_OF_LIST(&obj_used_list) ) {
1700 if ( !(objp->flags&OF_SHOULD_BE_DEAD) && (objp->type != OBJ_OBSERVER) && (objp->type != OBJ_ASTEROID) && (objp->type != OBJ_DEBRIS)) {
1701 objp->phys_info.vel.x = (objp->pos.x - objp->last_pos.x) / frametime;
1702 objp->phys_info.vel.y = (objp->pos.y - objp->last_pos.y) / frametime;
1703 objp->phys_info.vel.z = (objp->pos.z - objp->last_pos.z) / frametime;
1705 objp = GET_NEXT(objp);
1708 if(!(Game_mode & GM_DEMO_PLAYBACK)){
1709 find_homing_object_cmeasures(); // If any cmeasures fired, maybe steer away homing missiles
1712 // do pre-collision stuff for beam weapons
1713 beam_move_all_pre();
1715 if ( Collisions_enabled ) {
1716 obj_check_all_collisions();
1719 if(!(Game_mode & GM_DEMO_PLAYBACK)){
1720 turret_swarm_check_validity();
1723 // do post-collision stuff for beam weapons
1724 beam_move_all_post();
1726 // update artillery locking info now
1727 ship_update_artillery_lock();
1731 MONITOR( NumObjectsRend );
1733 // -----------------------------------------------------------------------------
1734 // Render an object. Calls one of several routines based on type
1735 void obj_render(object *obj)
1737 if ( obj->flags & OF_SHOULD_BE_DEAD ) return;
1738 // if ( obj == Viewer_obj ) return;
1740 MONITOR_INC( NumObjectsRend, 1 );
1742 switch( obj->type ) {
1745 mprintf(( "ERROR!!!! Bogus obj %d is rendering!\n", obj-Objects ));
1756 fireball_render(obj);
1759 shockwave_render(obj);
1765 asteroid_render(obj);
1768 cmeasure_render(obj);
1771 jumpnode_render(obj, &obj->pos, &Eye_position);
1774 if (Show_waypoints) {
1776 gr_set_color( 128, 128, 128 );
1777 g3_draw_sphere_ez( &obj->pos, 5.0f );
1785 Error( LOCATION, "Unhandled obj type %d in obj_render", obj->type );
1789 void obj_init_all_ships_physics()
1793 for ( objp = GET_FIRST(&obj_used_list); objp !=END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
1794 if (objp->type == OBJ_SHIP)
1795 physics_ship_init(objp);
1800 // do client-side pre-interpolation object movement
1801 void obj_client_pre_interpolate()
1806 obj_delete_all_that_should_be_dead();
1808 // client side processing of warping in effect stages
1809 multi_do_client_warp(flFrametime);
1811 // client side movement of an observer
1812 if((Net_player->flags & NETINFO_FLAG_OBSERVER) || (Player_obj->type == OBJ_OBSERVER)){
1813 obj_observer_move(flFrametime);
1816 // run everything except ships through physics (and ourselves of course)
1817 obj_merge_created_list(); // must merge any objects created by the host!
1819 objp = GET_FIRST(&obj_used_list);
1820 for ( objp = GET_FIRST(&obj_used_list); objp !=END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
1821 if((objp != Player_obj) && (objp->type == OBJ_SHIP)){
1825 // for all non-dead object which are _not_ ships
1826 if ( !(objp->flags&OF_SHOULD_BE_DEAD) ) {
1828 obj_move_all_pre(objp, flFrametime);
1830 // store position and orientation
1831 objp->last_pos = objp->pos;
1832 objp->last_orient = objp->orient;
1835 obj_move_call_physics(objp, flFrametime);
1838 obj_move_all_post(objp, flFrametime);
1843 // do client-side post-interpolation object movement
1844 void obj_client_post_interpolate()
1848 // After all objects have been moved, move all docked objects.
1849 objp = GET_FIRST(&obj_used_list);
1850 while( objp !=END_OF_LIST(&obj_used_list) ) {
1851 if ( (objp->type == OBJ_SHIP) || (objp != Player_obj) ) {
1852 move_docked_objects(objp);
1854 objp = GET_NEXT(objp);
1858 obj_check_all_collisions();
1860 // do post-collision stuff for beam weapons
1861 beam_move_all_post();
1865 // following function is used in multiplayer only. It deals with simulating objects on the client
1866 // side. Lasers will always get moved by the client (i.e. no object position info is ever sent for them).
1867 // same for dumb missiles and possibly others. We might move ships based on the last time their posision
1869 void obj_client_simulate(float frametime)
1873 obj_delete_all_that_should_be_dead();
1875 multi_do_client_warp(frametime); // client side processing of warping in effect stages
1877 if(Net_player->flags & NETINFO_FLAG_OBSERVER){
1878 obj_observer_move(frametime); // client side movement of an observer
1882 obj_merge_created_list(); // must merge any objects created by the host!
1883 objp = GET_FIRST(&obj_used_list);
1884 for ( objp = GET_FIRST(&obj_used_list); objp !=END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
1886 if ( !(objp->flags&OF_SHOULD_BE_DEAD) ) {
1887 vector cur_pos = objp->pos; // Save the current position
1889 obj_move_all_pre(objp, frametime);
1891 int predict_from_server_pos = 1;
1893 // If not visible (or not a ship), bash position
1894 if ( (!obj_visible_from_eye(&cur_pos)) || (objp->type != OBJ_SHIP) ) {
1895 predict_from_server_pos = 0;
1898 // If this is a player ship, don't predict from server position
1899 if ( objp->flags & OF_PLAYER_SHIP ) {
1900 predict_from_server_pos = 0;
1903 if ( predict_from_server_pos ) {
1904 obj_client_predict_pos(objp, frametime);
1906 obj_client_bash_pos(objp, frametime);
1909 obj_move_all_post(objp, frametime);
1914 // After all objects have been moved, move all docked objects.
1915 objp = GET_FIRST(&obj_used_list);
1916 while( objp !=END_OF_LIST(&obj_used_list) ) {
1917 if ( (objp->type == OBJ_SHIP) || (objp != Player_obj) ) {
1918 move_docked_objects(objp);
1920 objp = GET_NEXT(objp);
1923 obj_check_all_collisions();
1927 void obj_observer_move(float flFrametime)
1932 // if i'm not in multiplayer, or not an observer, bail
1933 if(!(Game_mode & GM_MULTIPLAYER) || (Net_player == NULL) || !(Net_player->flags & NETINFO_FLAG_OBSERVER) || (Player_obj->type != OBJ_OBSERVER)){
1939 // obj_move_all_pre(objp, flFrametime);
1941 objp->last_pos = objp->pos;
1942 objp->last_orient = objp->orient; // save the orientation -- useful in multiplayer.
1945 obj_move_call_physics( objp, ft );
1946 obj_move_all_post(objp, flFrametime);
1947 objp->flags &= ~OF_JUST_UPDATED;
1950 // function to return a vector of the average position of all ships in the mission.
1951 void obj_get_average_ship_pos( vector *pos )
1958 // average up all ship positions
1960 for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
1961 if ( objp->type != OBJ_SHIP )
1963 vm_vec_add2( pos, &objp->pos );
1968 vm_vec_scale( pos, 1.0f/(float)count );
1972 int obj_get_SIF(object *objp)
1974 if ((objp->type == OBJ_SHIP) || (objp->type == OBJ_START))
1975 return Ship_info[Ships[objp->instance].ship_info_index].flags;
1981 int obj_get_SIF(int obj)
1983 if ((Objects[obj].type == OBJ_SHIP) || (Objects[obj].type == OBJ_START))
1984 return Ship_info[Ships[Objects[obj].instance].ship_info_index].flags;
1990 // Return the team for the object passed as a parameter
1992 // input: objp => pointer to object that you want team for
1994 // exit: success => enumerated team ( TEAM_HOSTILE, TEAM_FRIENDLY, TEAM_NEUTRAL, etc )
1995 // failure => -1 (for objects that don't have teams)
1996 int obj_team(object *objp)
1998 Assert( objp != NULL );
2001 switch ( objp->type ) {
2003 Assert( objp->instance >= 0 && objp->instance < MAX_SHIPS );
2004 team = Ships[objp->instance].team;
2008 team = debris_get_team(objp);
2013 Assert( objp->instance >= 0 && objp->instance < MAX_CMEASURES);
2014 team = Cmeasures[objp->instance].team;
2018 Assert( objp->instance >= 0 && objp->instance < MAX_WEAPONS );
2019 team = Weapons[objp->instance].team;
2023 team = Player_ship->team;
2033 nprintf(("Warning","Warning => Asking for a team for object type %d\n", Object_type_names[objp->type]));
2038 team = TEAM_TRAITOR;
2042 Int3(); // can't happen
2050 // -------------------------------------------------------
2053 // Add an element to the CheckObjects[] array, and update the
2054 // object pairs. This is called from obj_create(), and the restore
2057 void obj_add_pairs(int objnum)
2061 Assert(objnum != -1);
2062 objp = &Objects[objnum];
2064 // don't do anything if its already in the object pair list
2065 if(!(objp->flags & OF_NOT_IN_COLL)){
2070 CheckObjects[objnum].type = objp->type;
2071 CheckObjects[objnum].signature = objp->signature;
2072 CheckObjects[objnum].flags = objp->flags & ~(OF_NOT_IN_COLL);
2073 CheckObjects[objnum].parent_sig = objp->parent_sig;
2074 CheckObjects[objnum].parent_type = objp->parent_type;
2077 // Find all the objects that can collide with this and add
2078 // it to the collision pair list.
2080 for ( A = GET_FIRST(&obj_used_list); A !=END_OF_LIST(&obj_used_list); A = GET_NEXT(A) ) {
2081 obj_add_pair( objp, A );
2084 objp->flags &= ~OF_NOT_IN_COLL;
2087 // Removes any occurances of object 'a' from
2089 extern int Num_pairs;
2090 extern obj_pair pair_used_list;
2091 extern obj_pair pair_free_list;
2092 void obj_remove_pairs( object * a )
2094 obj_pair *parent, *tmp;
2096 a->flags |= OF_NOT_IN_COLL;
2098 CheckObjects[OBJ_INDEX(a)].flags |= OF_NOT_IN_COLL;
2101 if ( a->num_pairs < 1 ) {
2102 //mprintf(( "OBJPAIR: No need to remove pairs 1!\n" ));
2106 Num_pairs-=a->num_pairs;
2108 parent = &pair_used_list;
2111 while( tmp != NULL ) {
2112 if ( (tmp->a==a) || (tmp->b==a) ) {
2113 // Hmmm... a potenial compiler optimization problem here... either tmp->a or tmp->b
2114 // is equal to 'a' and we modify 'num_pairs' in one of these and then use the value
2115 // stored in 'a' later one... will the optimizer find that? Hmmm...
2116 tmp->a->num_pairs--;
2117 Assert( tmp->a->num_pairs > -1 );
2118 tmp->b->num_pairs--;
2119 Assert( tmp->b->num_pairs > -1 );
2120 parent->next = tmp->next;
2121 tmp->a = tmp->b = NULL;
2122 tmp->next = pair_free_list.next;
2123 pair_free_list.next = tmp;
2126 if ( a->num_pairs==0 ) {
2127 //mprintf(( "OBJPAIR: No need to remove pairs 2!\n" ));
2138 // reset all collisions
2139 void obj_reset_all_collisions()
2141 // clear checkobjects
2143 memset(CheckObjects, 0, sizeof(checkobject) * MAX_OBJECTS);
2146 // clear object pairs
2149 // now add every object back into the object collision pairs
2151 moveup = GET_FIRST(&obj_used_list);
2152 while(moveup != END_OF_LIST(&obj_used_list)){
2153 // he's not in the collision list
2154 moveup->flags |= OF_NOT_IN_COLL;
2156 // recalc pairs for this guy
2157 obj_add_pairs(OBJ_INDEX(moveup));
2160 moveup = GET_NEXT(moveup);