1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
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 the
6  * source.
7  *
8 */
9 
10 
11 
12 #ifndef _OBJECT_H
13 #define _OBJECT_H
14 
15 #include "globalincs/pstypes.h"
16 #include "globalincs/globals.h"
17 #include "math/vecmat.h"
18 #include "physics/physics.h"
19 
20 /*
21  *		CONSTANTS
22  */
23 
24 #define DEFAULT_SHIELD_SECTIONS	4	//	Number of sections in standard shields.
25 
26 #ifndef NDEBUG
27 #define OBJECT_CHECK
28 #endif
29 
30 //Object types
31 #define OBJ_NONE				0		//unused object
32 #define OBJ_SHIP				1		//a ship
33 #define OBJ_WEAPON			2		//a laser, missile, etc
34 #define OBJ_FIREBALL			3		//an explosion
35 #define OBJ_START				4		//a starting point marker (player start, etc)
36 #define OBJ_WAYPOINT			5		//a waypoint object, maybe only ever used by Fred
37 #define OBJ_DEBRIS			6		//a flying piece of ship debris
38 //#define OBJ_CMEASURE			7		//a countermeasure, such as chaff
39 #define OBJ_GHOST				8		//so far, just a placeholder for when a player dies.
40 #define OBJ_POINT				9		//generic object type to display a point in Fred.
41 #define OBJ_SHOCKWAVE		10		// a shockwave
42 #define OBJ_WING				11		// not really a type used anywhere, but I need it for Fred.
43 #define OBJ_OBSERVER       12    // used for multiplayer observers (possibly single player later)
44 #define OBJ_ASTEROID			13		//	An asteroid, you know, a big rock, like debris, sort of.
45 #define OBJ_JUMP_NODE		14		// A jump node object, used only in Fred.
46 #define OBJ_BEAM				15		// beam weapons. we have to roll them into the object system to get the benefits of the collision pairs
47 
48 //Make sure to change Object_type_names in Object.c when adding another type!
49 #define MAX_OBJECT_TYPES	16
50 
51 #define UNUSED_OBJNUM		(-MAX_OBJECTS*2)	//	Newer systems use this instead of -1 for invalid object.
52 
53 extern char	*Object_type_names[MAX_OBJECT_TYPES];
54 
55 // each object type should have these functions:  (I will use weapon as example)
56 //
57 // int weapon_create( weapon specific parameters )
58 // {
59 //    ...
60 //		objnum = obj_create();
61 //		... Do some check to correctly handle obj_create returning  which
62 //        means that that object couldn't be created
63 //    ... Initialize the weapon-specific info in Objects[objnum]
64 //    return objnum;
65 // }
66 //
67 // void weapon_delete( object * obj )
68 // {
69 //    {Put a call to this in OBJECT.C, function obj_delete_all_that_should_be_dead }
70 //    WARNING: To kill an object, set it's OF_SHOULD_BE_DEAD flag.  Then,
71 //    this function will get called when it's time to clean up the data.
72 //    Assert( obj->flags & OF_SHOULD_BE_DEAD );
73 //    ...
74 //    ... Free up all weapon-specfic data
75 //    obj_delete(objnum);
76 // }
77 //
78 // void weapon_move( object * obj )
79 // {
80 //    {Put a call to this in ??? }
81 //    ... Do whatever needs to be done each frame.  Usually this amounts
82 //        to setting the thrust, seeing if we've died, etc.
83 // }
84 //
85 // int weapon_check_collision( object * obj, object * other_obj, vec3d * hitpos )
86 // {
87 //    this should check if a vector from
88 //		other_obj->last_pos to other_obj->pos with a radius of other_obj->radius
89 //    collides with object obj.   If it does, then fill in hitpos with the point
90 //    of impact and return non-zero, otherwise return 0 if no impact.   Note that
91 //    this shouldn't take any action... that happens in weapon_hit.
92 // }
93 
94 //
95 // void weapon_hit( object * obj, object * other_obj, vec3d * hitpos )
96 // {
97 //    {Put a call to this in COLLIDE.C}
98 //    ... Do what needs to be done when this object gets hit
99 //    ... Reducing shields, etc
100 // }
101 
102 //Misc object flags
103 #define OF_RENDERS					(1<<0)	// It renders as something ( objtype_render gets called)
104 #define OF_COLLIDES					(1<<1)	// It collides with stuff (objtype_check_impact & objtype_hit gets called)
105 #define OF_PHYSICS					(1<<2)	// It moves with standard physics.
106 #define OF_SHOULD_BE_DEAD			(1<<3)	// this object should be dead, so next time we can, we should delete this object.
107 #define OF_INVULNERABLE				(1<<4)	// invulnerable
108 #define OF_PROTECTED				(1<<5)	// Don't kill this object, probably mission-critical.
109 #define OF_PLAYER_SHIP				(1<<6)	// this object under control of some player -- don't do ai stuff on it!!!
110 #define OF_NO_SHIELDS				(1<<7)	// object has no shield generator system (i.e. no shields)
111 #define OF_JUST_UPDATED				(1<<8)	// for multiplayer -- indicates that we received object update this frame
112 #define OF_COULD_BE_PLAYER			(1<<9)	// for multiplayer -- indicates that it is selectable ingame joiners as their ship
113 #define OF_WAS_RENDERED				(1<<10)	// Set if this object was rendered this frame.  Only gets set if OF_RENDERS set.  Gets cleared or set in obj_render_all().
114 #define OF_NOT_IN_COLL				(1<<11)	// object has not been added to collision list
115 #define OF_BEAM_PROTECTED			(1<<12)	// don't fire beam weapons at this type of object, probably mission critical.
116 #define OF_SPECIAL_WARPIN			(1<<13)	// Object has special warp-in enabled.
117 #define OF_DOCKED_ALREADY_HANDLED	(1<<14)	// Goober5000 - a docked object that we already moved
118 #define OF_TARGETABLE_AS_BOMB		(1<<15)
119 #define	OF_FLAK_PROTECTED			(1<<16)	// Goober5000 - protected from flak turrets
120 #define	OF_LASER_PROTECTED			(1<<17)	// Goober5000 - protected from laser turrets
121 #define	OF_MISSILE_PROTECTED		(1<<18)	// Goober5000 - protected from missile turrets
122 #define OF_IMMOBILE					(1<<19)	// Goober5000 - doesn't move, no matter what
123 
124 // Flags used by Fred
125 #define OF_MARKED			(1<<29)	// Object is marked (Fred).  Can be reused in FreeSpace for anything that won't be used by Fred.
126 #define OF_TEMP_MARKED		(1<<30)	// Temporarily marked (Fred).
127 #define OF_HIDDEN			(1<<31)	// Object is hidden (not shown) and can't be manipulated
128 
129 typedef struct obj_flag_name {
130 	int flag;
131 	char flag_name[TOKEN_LENGTH];
132 	int flag_list;
133 } obj_flag_name;
134 
135 #define MAX_OBJECT_FLAG_NAMES			9
136 extern obj_flag_name Object_flag_names[];
137 
138 struct dock_instance;
139 
140 class object
141 {
142 public:
143 	class object	*next, *prev;	// for linked lists of objects
144 	int				signature;		// Every object ever has a unique signature...
145 	char			type;				// what type of object this is... robot, weapon, hostage, powerup, fireball
146 	int				parent;			// This object's parent.
147 	int				parent_sig;		// This object's parent's signature
148 	char			parent_type;	// This object's parent's type
149 	int				instance;		// which instance.  ie.. if type is Robot, then this indexes into the Robots array
150 	uint			flags;			// misc flags.  Call obj_set_flags to change this.
151 	vec3d			pos;				// absolute x,y,z coordinate of center of object
152 	matrix			orient;			// orientation of object in world
153 	float			radius;			// 3d size of object - for collision detection
154 	vec3d			last_pos;		// where object was last frame
155 	matrix			last_orient;	// how the object was oriented last frame
156 	physics_info	phys_info;		// a physics object
157 	int				n_quadrants;	// how many shield quadrants the ship has
158 	SCP_vector<float>	shield_quadrant;	//	Shield is broken into components, quadrants by default.
159 	float			hull_strength;	//	Remaining hull strength.
160 	float			sim_hull_strength;	// Simulated hull strength - used with training weapons.
161 	SCP_vector<int> objsnd_num;		// Index of persistant sound struct.
162 	ushort			net_signature;
163 	int				num_pairs;		// How many object pairs this is associated with.  When 0 then there are no more.
164 
165 	dock_instance	*dock_list;			// Goober5000 - objects this object is docked to
166 	dock_instance	*dead_dock_list;	// Goober5000 - objects this object was docked to when destroyed; replaces dock_objnum_when_dead
167 
168 	int				collision_group_id; // This is a bitfield. Collision checks will be skipped if A->collision_group_id & B->collision_group_id returns nonzero
169 
170 	object();
171 	~object();
172 	void clear();
173 };
174 
175 struct object_h {
176 	object *objp;
177 	int sig;
178 
IsValidobject_h179 	bool IsValid(){return (this != NULL && objp != NULL && objp->signature == sig);}
object_hobject_h180 	object_h(object *in){objp=in; if(objp!=NULL){sig=in->signature;}}
object_hobject_h181 	object_h(){objp=NULL;sig=-1;}
182 };
183 
184 // object backup struct used by Fred.
185 typedef struct object_orient_pos {
186 	vec3d pos;
187 	matrix orient;
188 } object_orient_pos;
189 
190 #ifdef OBJECT_CHECK
191 typedef struct checkobject
192 {
193 	int	type;
194 	int	signature;
195 	uint	flags;
196 	int	parent_sig;
197 	int	parent_type;
198 } checkobject;
199 #endif
200 
201 /*
202  *		VARIABLES
203  */
204 
205 extern int Object_inited;
206 extern int Show_waypoints;
207 
208 // The next signature for the next newly created object. Zero is bogus
209 extern int Object_next_signature;
210 extern int Num_objects;
211 
212 extern object Objects[];
213 extern int Highest_object_index;		//highest objnum
214 extern int Highest_ever_object_index;
215 extern object obj_free_list;
216 extern object obj_used_list;
217 extern object obj_create_list;
218 
219 extern int render_total;
220 extern int render_order[MAX_OBJECTS];
221 
222 extern object *Viewer_obj;	// Which object is the viewer. Can be NULL.
223 extern object *Player_obj;	// Which object is the player. Has to be valid.
224 
225 // Use this instead of "objp - Objects" to get an object number
226 // given it's pointer.  This way, we can replace it with a macro
227 // to check that the pointer is valid for debugging.
228 #define OBJ_INDEX(objp) (objp-Objects)
229 
230 /*
231  *		FUNCTIONS
232  */
233 
234 //do whatever setup needs to be done
235 void obj_init();
236 
237 //initialize a new object.  adds to the list for the given segment.
238 //returns the object number.  The object will be a non-rendering, non-physics
239 //object.  Returns 0 if failed, otherwise object index.
240 //You can pass 0 for parent if you don't care about that.
241 //You can pass null for orient and/or pos if you don't care.
242 int obj_create(ubyte type,int parent_obj, int instance, matrix * orient, vec3d * pos, float radius, uint flags );
243 
244 //Render an object.  Calls one of several routines based on type
245 void obj_render(object *obj);
246 
247 //Sorts and renders all the ojbects
248 void obj_render_all(void (*render_function)(object *objp), bool* render_viewer_last );
249 
250 //move all objects for the current frame
251 void obj_move_all(float frametime);		// moves all objects
252 
253 //move an object for the current frame
254 void obj_move_one(object * obj, float frametime);
255 
256 // function to delete an object -- should probably only be called directly from editor code
257 void obj_delete(int objnum);
258 
259 // should only be used by the editor!
260 void obj_merge_created_list(void);
261 
262 // recalculate object pairs for an object
263 #define OBJ_RECALC_PAIRS(obj_to_reset)		do {	obj_set_flags(obj_to_reset, obj_to_reset->flags & ~(OF_COLLIDES)); obj_set_flags(obj_to_reset, obj_to_reset->flags | OF_COLLIDES); } while(0);
264 
265 // Removes any occurances of object 'a' from the pairs list.
266 void obj_remove_pairs( object * a );
267 
268 // add an object to the pairs list
269 void obj_add_pairs(int objnum);
270 
271 //	Returns true if objects A and B are expected to collide in next duration seconds.
272 //	For purposes of this check, the first object moves from current location to predicted
273 //	location.  The second object is assumed to be where it will be at time duration, NOT
274 //	where it currently is.
275 //	radius_scale: 0.0f means use polygon models, else scale sphere size by radius_scale
276 //	radius_scale == 1.0f means Descent style collisions.
277 int objects_will_collide(object *A, object *B, float duration, float radius_scale);
278 
279 // Used for pausing.  Seems hacked.  Was in PHYSICS, but that broke the TestCode program,
280 // so I moved it into the object lib.  -John
281 void obj_init_all_ships_physics();
282 
283 // Goober5000
284 float get_hull_pct(object *objp);
285 float get_sim_hull_pct(object *objp);
286 float get_shield_pct(object *objp);
287 float get_max_shield_quad(object *objp);
288 
289 // returns the average 3-space position of all ships.  useful to find "center" of battle (sort of)
290 void obj_get_average_ship_pos(vec3d *pos);
291 
292 // function to deal with firing player things like lasers, missiles, etc.
293 // separated out because of multiplayer issues.
294 void obj_player_fire_stuff( object *objp, control_info ci );
295 
296 // Call this if you want to change an object flag so that the
297 // object code knows what's going on.  For instance if you turn
298 // off OF_COLLIDES, the object code needs to know this in order to
299 // actually turn the object collision detection off.  By calling
300 // this you shouldn't get Int3's in the checkobject code.  If you
301 // do, then put code in here to correctly handle the case.
302 void obj_set_flags(object *obj, uint new_flags);
303 
304 // get the Ship_info flags for a given ship (if you have the object)
305 int obj_get_SIF(object *objp);
306 int obj_get_SIF(int obj);
307 
308 // get the team for any object
309 int obj_team(object *objp);
310 
311 void obj_move_all_pre(object *objp, float frametime);
312 void obj_move_all_post(object *objp, float frametime);
313 
314 void obj_move_call_physics(object *objp, float frametime);
315 
316 // multiplayer object update stuff begins -------------------------------------------
317 
318 // do client-side pre-interpolation object movement
319 void obj_client_pre_interpolate();
320 
321 // do client-side post-interpolation object movement
322 void obj_client_post_interpolate();
323 
324 // move an observer object in multiplayer
325 void obj_observer_move(float frame_time);
326 
327 // Goober5000
328 int object_is_docked(object *objp);
329 int object_is_dead_docked(object *objp);
330 void obj_move_one_docked_object(object *objp, object *parent_objp);
331 
332 //WMC
333 void object_set_gliding(object *objp, bool enable=true, bool force = false);
334 bool object_get_gliding(object *objp);
335 bool object_glide_forced(object* objp);
336 int obj_get_by_signature(int sig);
337 int object_get_model(object *objp);
338 
339 #endif
340