1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
|
/*
* Copyright (C) Volition, Inc. 1999. All rights reserved.
*
* All source code herein is the property of Volition, Inc. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
#ifndef _OBJECT_H
#define _OBJECT_H
#include "globalincs/globals.h"
#include "globalincs/pstypes.h"
#include "math/vecmat.h"
#include "object/object.h"
#include "object/object_flags.h"
#include "physics/physics.h"
#include "utils/event.h"
#include "network/multi_interpolate.h"
#include <functional>
/*
* CONSTANTS
*/
#define DEFAULT_SHIELD_SECTIONS 4 // Number of sections in standard shields.
#ifndef NDEBUG
#define OBJECT_CHECK
#endif
//Object types
#define OBJ_NONE 0 //unused object
#define OBJ_SHIP 1 //a ship
#define OBJ_WEAPON 2 //a laser, missile, etc
#define OBJ_FIREBALL 3 //an explosion
#define OBJ_START 4 //a starting point marker (player start, etc)
#define OBJ_WAYPOINT 5 //a waypoint object, maybe only ever used by Fred
#define OBJ_DEBRIS 6 //a flying piece of ship debris
//#define OBJ_CMEASURE 7 //a countermeasure, such as chaff
#define OBJ_GHOST 8 //so far, just a placeholder for when a player dies.
#define OBJ_POINT 9 //generic object type to display a point in Fred.
#define OBJ_SHOCKWAVE 10 // a shockwave
#define OBJ_WING 11 // not really a type used anywhere, but I need it for Fred.
#define OBJ_OBSERVER 12 // used for multiplayer observers (possibly single player later)
#define OBJ_ASTEROID 13 // An asteroid, you know, a big rock, like debris, sort of.
#define OBJ_JUMP_NODE 14 // A jump node object, used only in Fred.
#define OBJ_BEAM 15 // beam weapons. we have to roll them into the object system to get the benefits of the collision pairs
//Make sure to change Object_type_names in Object.c when adding another type!
#define MAX_OBJECT_TYPES 16
#define UNUSED_OBJNUM (-MAX_OBJECTS*2) // Newer systems use this instead of -1 for invalid object.
extern const char *Object_type_names[MAX_OBJECT_TYPES];
// each object type should have these functions: (I will use weapon as example)
//
// int weapon_create( weapon specific parameters )
// {
// ...
// objnum = obj_create();
// ... Do some check to correctly handle obj_create returning which
// means that that object couldn't be created
// ... Initialize the weapon-specific info in Objects[objnum]
// return objnum;
// }
//
// void weapon_delete( object * obj )
// {
// {Put a call to this in OBJECT.C, function obj_delete_all_that_should_be_dead }
// WARNING: To kill an object, set it's OF_SHOULD_BE_DEAD flag. Then,
// this function will get called when it's time to clean up the data.
// Assert( obj->flags[Object::Object_Flags::Should_be_dead] );
// ...
// ... Free up all weapon-specfic data
// obj_delete(objnum);
// }
//
// void weapon_move( object * obj )
// {
// {Put a call to this in ??? }
// ... Do whatever needs to be done each frame. Usually this amounts
// to setting the thrust, seeing if we've died, etc.
// }
//
// int weapon_check_collision( object * obj, object * other_obj, vec3d * hitpos )
// {
// this should check if a vector from
// other_obj->last_pos to other_obj->pos with a radius of other_obj->radius
// collides with object obj. If it does, then fill in hitpos with the point
// of impact and return non-zero, otherwise return 0 if no impact. Note that
// this shouldn't take any action... that happens in weapon_hit.
// }
//
// void weapon_hit( object * obj, object * other_obj, vec3d * hitpos )
// {
// {Put a call to this in COLLIDE.C}
// ... Do what needs to be done when this object gets hit
// ... Reducing shields, etc
// }
typedef struct obj_flag_name {
Object::Object_Flags flag;
char flag_name[TOKEN_LENGTH];
} obj_flag_name;
typedef struct obj_flag_description {
Object::Object_Flags flag;
SCP_string flag_desc;
} obj_flag_description;
extern obj_flag_name Object_flag_names[];
extern obj_flag_description Object_flag_descriptions[];
extern const int Num_object_flag_names;
struct dock_instance;
class model_draw_list;
class object
{
public:
class object *next, *prev; // for linked lists of objects
int signature; // Every object ever has a unique signature...
char type; // what type of object this is... ship, weapon, debris, asteroid, fireball, see OBJ_* defines above
int parent; // This object's parent.
int parent_sig; // This object's parent's signature
int instance; // index into the corresponding type array, i.e. if type == OBJ_SHIP then instance indexes the Ships array
flagset<Object::Object_Flags> flags; // misc flags. Call obj_set_flags to change this.
vec3d pos; // absolute x,y,z coordinate of center of object
matrix orient; // orientation of object in world
float radius; // 3d size of object - for collision detection
vec3d last_pos; // where object was last frame
matrix last_orient; // how the object was oriented last frame
physics_info phys_info; // a physics object
int n_quadrants; // how many shield quadrants the ship has
SCP_vector<float> shield_quadrant; // Shield is broken into components, quadrants by default.
float hull_strength; // Remaining hull strength.
float sim_hull_strength; // Simulated hull strength - used with training weapons.
SCP_vector<int> objsnd_num; // Index of persistant sound struct.
ushort net_signature;
int num_pairs; // How many object pairs this is associated with. When 0 then there are no more.
dock_instance *dock_list; // Goober5000 - objects this object is docked to
dock_instance *dead_dock_list; // Goober5000 - objects this object was docked to when destroyed; replaces dock_objnum_when_dead
int collision_group_id; // This is a bitfield. Collision checks will be skipped if A->collision_group_id & B->collision_group_id returns nonzero
util::event<void, object*> pre_move_event;
util::event<void, object*> post_move_event;
interpolation_manager interp_info;
object();
~object();
void clear();
private:
// An object should never be copied; there are allocated pointers, and linked list shenanigans.
object(const object& other); // no implementation
object& operator= (const object & other); // no implementation
};
struct lua_State;
namespace scripting {
class ade_table_entry;
}
namespace luacpp {
class LuaValue;
}
extern int Num_objects;
extern object Objects[];
struct object_h {
object *objp;
int sig;
bool IsValid() const {return (objp != nullptr && objp->signature == sig && sig > 0); }
object_h(object *in) {objp = in; sig = (in == nullptr) ? -1 : in->signature; }
object_h() { objp = nullptr; sig = -1; }
object_h(int objnum)
{
if (objnum >= 0 && objnum < MAX_OBJECTS)
{
objp = &Objects[objnum];
sig = objp->signature;
}
else
{
objp = nullptr;
sig = -1;
}
}
static void serialize(lua_State* L, const scripting::ade_table_entry& tableEntry, const luacpp::LuaValue& value, ubyte* data, int& packet_size);
static void deserialize(lua_State* L, const scripting::ade_table_entry& tableEntry, char* data_ptr, ubyte* data, int& offset);
};
// object backup struct used by Fred.
typedef struct object_orient_pos {
vec3d pos;
matrix orient;
} object_orient_pos;
#ifdef OBJECT_CHECK
class checkobject
{
public:
int type;
int signature;
flagset<Object::Object_Flags> flags;
int parent_sig;
checkobject();
};
#endif
/*
* VARIABLES
*/
extern int Object_inited;
extern int Show_waypoints;
extern int Object_next_signature; // The next signature for the next newly created object. Zero is bogus
extern int Highest_object_index; //highest objnum
extern int Highest_ever_object_index;
extern object obj_free_list;
extern object obj_used_list;
extern object obj_create_list;
extern int render_total;
extern int render_order[MAX_OBJECTS];
extern object *Viewer_obj; // Which object is the viewer. Can be NULL.
extern object *Player_obj; // Which object is the player. Has to be valid.
// Use this instead of "objp - Objects" to get an object number
// given it's pointer. This way, we can replace it with a macro
// to check that the pointer is valid for debugging.
// This code will break in 64 bit builds when we have more than 2^31 objects but that will probably never happen
#define OBJ_INDEX(objp) static_cast<int>(objp-Objects)
/*
* FUNCTIONS
*/
//do whatever setup needs to be done
void obj_init();
void obj_shutdown();
//initialize a new object. adds to the list for the given segment.
//returns the object number. The object will be a non-rendering, non-physics
//object. Returns 0 if failed, otherwise object index.
//You can pass 0 for parent if you don't care about that.
//You can pass null for orient and/or pos if you don't care.
int obj_create(ubyte type, int parent_obj, int instance, const matrix *orient, const vec3d *pos, float radius, const flagset<Object::Object_Flags> &flags, bool essential = true);
void obj_render(object* obj);
void obj_queue_render(object* obj, model_draw_list* scene);
//Sorts and renders all the ojbects
void obj_render_all(const std::function<void(object*)>& render_function, bool* render_viewer_last );
//move all objects for the current frame
void obj_move_all(float frametime); // moves all objects
// function to delete an object -- should probably only be called directly from editor code
void obj_delete(int objnum);
void obj_delete_all();
void obj_delete_all_that_should_be_dead();
// should only be used by the editor!
void obj_merge_created_list(void);
// recalculate object pairs for an object
#define OBJ_RECALC_PAIRS(obj_to_reset) do { obj_set_flags(obj_to_reset, obj_to_reset->flags - Object::Object_Flags::Collides); obj_set_flags(obj_to_reset, obj_to_reset->flags + Object::Object_Flags::Collides); } while(false);
// Returns true if objects A and B are expected to collide in next duration seconds.
// For purposes of this check, the first object moves from current location to predicted
// location. The second object is assumed to be where it will be at time duration, NOT
// where it currently is.
// radius_scale: 0.0f means use polygon models, else scale sphere size by radius_scale
// radius_scale == 1.0f means Descent style collisions.
int objects_will_collide(object *A, object *B, float duration, float radius_scale);
// Used for pausing. Seems hacked. Was in PHYSICS, but that broke the TestCode program,
// so I moved it into the object lib. -John
void obj_init_all_ships_physics();
// Goober5000
float get_hull_pct(object *objp);
float get_sim_hull_pct(object *objp);
float get_shield_pct(object *objp);
// returns the average 3-space position of all ships. useful to find "center" of battle (sort of)
void obj_get_average_ship_pos(vec3d *pos);
// function to deal with firing player things like lasers, missiles, etc.
// separated out because of multiplayer issues.
void obj_player_fire_stuff( object *objp, control_info ci );
// Call this if you want to change an object flag so that the
// object code knows what's going on. For instance if you turn
// off OF_COLLIDES, the object code needs to know this in order to
// actually turn the object collision detection off. By calling
// this you shouldn't get Int3's in the checkobject code. If you
// do, then put code in here to correctly handle the case.
void obj_set_flags(object *obj, const flagset<Object::Object_Flags>& new_flags);
// get the team for any object
int obj_team(object *objp);
void obj_move_all_pre(object *objp, float frametime);
void obj_move_all_post(object *objp, float frametime);
void obj_move_call_physics(object *objp, float frametime);
// multiplayer object update stuff begins -------------------------------------------
// move an observer object in multiplayer
void obj_observer_move(float frame_time);
/**
* @brief Checks if the given object is docked with anyone.
*
* @returns Nonzero if docked, or
* @returns 0 if not docked
*
* @author Goober5000
*/
int object_is_docked(object *objp);
/**
* @brief Checks if the given object is dead-docked with anyone.
*
* @returns Nonzero if docked, or
* @returns 0 if not docked
*
* @details An object is "dead-docked" when it is dying and still has objects docked to it. The dead_dock list is
* populated when the object dies, and is used later on to jettison and maybe damage the docked objects.
*
* @author Goober5000
*/
int object_is_dead_docked(object *objp);
/**
* @brief Moves a docked object to keep up with the parent object as it moves
*
* @param[in,out] objp The docked object
* @param[in] parent_objp The object that it's docked to
*
* @author Goober5000
*/
void obj_move_one_docked_object(object *objp, object *parent_objp);
//WMC
void object_set_gliding(object *objp, bool enable=true, bool force = false);
bool object_get_gliding(object *objp);
bool object_glide_forced(object* objp);
int obj_get_by_signature(int sig);
int object_get_model(const object *objp);
int object_get_model_instance(const object *objp);
void obj_render_queue_all();
/**
* @brief Compares two object pointers and determines if they refer to the same object
*
* @note Two @c nullptr parameters are considered equal
*
* @param left The first object pointer, may be @c nullptr
* @param right The second object pointer, may be @c nullptr
* @return @c true if the two pointers refer to the same object
*/
bool obj_compare(object *left, object *right);
#endif
|