2006-03-20 17:12:09 +00:00
/*
2014-06-01 17:55:23 +00:00
* Portions of this file are copyright Rebirth contributors and licensed as
* described in COPYING . txt .
* Portions of this file are copyright Parallax Software and licensed
* according to the Parallax license below .
* See COPYING . txt for license details .
2006-03-20 17:12:09 +00:00
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
SOFTWARE CORPORATION ( " PARALLAX " ) . PARALLAX , IN DISTRIBUTING THE CODE TO
END - USERS , AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN , GRANTS A
ROYALTY - FREE , PERPETUAL LICENSE TO SUCH END - USERS FOR USE BY SUCH END - USERS
IN USING , DISPLAYING , AND CREATING DERIVATIVE WORKS THEREOF , SO LONG AS
SUCH USE , DISPLAY OR CREATION IS FOR NON - COMMERCIAL , ROYALTY OR REVENUE
FREE PURPOSES . IN NO EVENT SHALL THE END - USER USE THE COMPUTER CODE
CONTAINED HEREIN FOR REVENUE - BEARING PURPOSES . THE END - USER UNDERSTANDS
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE .
COPYRIGHT 1993 - 1999 PARALLAX SOFTWARE CORPORATION . ALL RIGHTS RESERVED .
*/
/*
*
* object system definitions
*
*/
2014-11-23 04:36:58 +00:00
# pragma once
2006-03-20 17:12:09 +00:00
2017-06-25 20:46:03 +00:00
# include <type_traits>
2016-08-06 19:55:24 +00:00
# include "dsx-ns.h"
2016-01-09 16:38:15 +00:00
# ifdef dsx
2015-04-19 04:18:52 +00:00
2006-03-20 17:12:09 +00:00
# include "pstypes.h"
# include "vecmat.h"
# include "aistruct.h"
2013-03-24 20:32:01 +00:00
# include "polyobj.h"
2006-03-20 17:12:09 +00:00
2014-07-20 01:09:55 +00:00
# include <cassert>
2013-12-26 22:21:16 +00:00
# include <cstdint>
2013-12-12 21:48:34 +00:00
# include "dxxsconf.h"
2013-12-24 04:53:59 +00:00
# include "valptridx.h"
2013-12-29 04:28:07 +00:00
# include "objnum.h"
2016-12-24 18:12:17 +00:00
# include "fwd-segment.h"
2013-12-25 23:47:30 +00:00
# include <vector>
2013-12-26 03:10:16 +00:00
# include <stdexcept>
2015-10-10 03:44:14 +00:00
# include "fwd-object.h"
2021-02-05 12:54:08 +00:00
# include "fwd-weapon.h"
# include "fwd-player.h"
2015-04-19 04:18:53 +00:00
# include "powerup.h"
2017-02-19 19:33:36 +00:00
# include "compiler-poison.h"
2020-05-17 23:35:25 +00:00
# include "physics_info.h"
2015-11-07 21:55:59 +00:00
# include "player-flags.h"
2019-03-03 00:31:08 +00:00
# if defined(DXX_BUILD_DESCENT_II)
# include "escort.h"
# endif
2020-05-02 21:18:42 +00:00
# include <array>
2020-04-26 17:26:23 +00:00
# include <utility>
2006-03-20 17:12:09 +00:00
2016-04-06 03:34:13 +00:00
namespace dcx {
2015-12-05 22:57:25 +00:00
2006-03-20 17:12:09 +00:00
// Object types
2016-11-20 23:12:00 +00:00
enum object_type_t : uint8_t
2012-09-01 22:24:42 +00:00
{
OBJ_NONE = 255 , // unused object
OBJ_WALL = 0 , // A wall... not really an object, but used for collisions
OBJ_FIREBALL = 1 , // a fireball, part of an explosion
OBJ_ROBOT = 2 , // an evil enemy
OBJ_HOSTAGE = 3 , // a hostage you need to rescue
OBJ_PLAYER = 4 , // the player on the console
OBJ_WEAPON = 5 , // a laser, missile, etc
OBJ_CAMERA = 6 , // a camera to slew around with
OBJ_POWERUP = 7 , // a powerup you can pick up
OBJ_DEBRIS = 8 , // a piece of robot
OBJ_CNTRLCEN = 9 , // the control center
OBJ_CLUTTER = 11 , // misc objects
OBJ_GHOST = 12 , // what the player turns into when dead
OBJ_LIGHT = 13 , // a light source, & not much else
OBJ_COOP = 14 , // a cooperative player object.
OBJ_MARKER = 15 , // a map marker
} ;
2006-03-20 17:12:09 +00:00
2020-05-02 21:18:43 +00:00
enum render_type_t : uint8_t
{
RT_NONE = 0 , // does not render
RT_POLYOBJ = 1 , // a polygon model
RT_FIREBALL = 2 , // a fireball
RT_LASER = 3 , // a laser
RT_HOSTAGE = 4 , // a hostage
RT_POWERUP = 5 , // a powerup
RT_MORPH = 6 , // a robot being morphed
RT_WEAPON_VCLIP = 7 , // a weapon that renders as a vclip
} ;
static inline bool valid_render_type ( const uint8_t r )
{
switch ( r )
{
case RT_NONE :
case RT_POLYOBJ :
case RT_FIREBALL :
case RT_LASER :
case RT_HOSTAGE :
case RT_POWERUP :
case RT_MORPH :
case RT_WEAPON_VCLIP :
return true ;
default :
return false ;
}
}
2016-04-06 03:34:13 +00:00
}
namespace dsx {
2006-03-20 17:12:09 +00:00
/*
* STRUCTURES
*/
2013-03-23 19:09:44 +00:00
struct reactor_static {
/* Location of the gun on the reactor object */
2020-05-02 21:18:42 +00:00
std : : array < vms_vector , MAX_CONTROLCEN_GUNS > gun_pos ,
2013-03-23 19:09:44 +00:00
/* Orientation of the gun on the reactor object */
2015-04-02 02:36:52 +00:00
gun_dir ;
2013-03-23 19:09:44 +00:00
} ;
2015-11-07 21:55:58 +00:00
struct player_info
{
fix energy ; // Amount of energy remaining.
2015-11-14 18:17:22 +00:00
fix homing_object_dist ; // Distance of nearest homing object.
2016-12-10 17:51:09 +00:00
fix Fusion_charge ;
2016-08-28 22:41:47 +00:00
# if defined(DXX_BUILD_DESCENT_II)
fix Omega_charge ;
2016-11-12 18:10:08 +00:00
fix Omega_recharge_delay ;
2016-08-28 22:41:47 +00:00
# endif
2015-11-07 21:55:59 +00:00
player_flags powerup_flags ;
2015-11-07 21:55:59 +00:00
objnum_t killer_objnum ; // Who killed me.... (-1 if no one)
2015-11-07 21:55:59 +00:00
uint16_t vulcan_ammo ;
2015-11-07 21:55:59 +00:00
# if defined(DXX_BUILD_DESCENT_I)
using primary_weapon_flag_type = uint8_t ;
# elif defined(DXX_BUILD_DESCENT_II)
using primary_weapon_flag_type = uint16_t ;
# endif
primary_weapon_flag_type primary_weapon_flags ;
2016-12-10 17:51:09 +00:00
bool Player_eggs_dropped ;
2016-02-27 19:02:21 +00:00
bool FakingInvul ;
2016-07-24 04:04:25 +00:00
bool lavafall_hiss_playing ;
2016-07-06 01:54:25 +00:00
uint8_t missile_gun ;
2016-08-28 22:41:49 +00:00
player_selected_weapon < primary_weapon_index_t > Primary_weapon ;
2016-10-02 00:34:43 +00:00
player_selected_weapon < secondary_weapon_index_t > Secondary_weapon ;
2020-08-24 01:31:28 +00:00
enum laser_level laser_level ;
2020-05-02 21:18:42 +00:00
std : : array < uint8_t , MAX_SECONDARY_WEAPONS > secondary_ammo ; // How much ammo of each type.
2019-05-04 18:27:36 +00:00
uint8_t Spreadfire_toggle ;
2016-08-28 22:41:47 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2017-02-19 19:33:44 +00:00
uint8_t Primary_last_was_super ;
2017-02-19 19:33:45 +00:00
uint8_t Secondary_last_was_super ;
2019-05-04 18:27:36 +00:00
uint8_t Helix_orientation ;
2016-08-28 22:41:47 +00:00
# endif
2016-11-12 18:10:07 +00:00
int16_t net_killed_total ; // Number of times killed total
2016-11-12 18:10:07 +00:00
int16_t net_kills_total ; // Number of net kills total
2016-11-12 18:10:07 +00:00
int16_t KillGoalCount ; // Num of players killed this level
2016-10-15 00:53:19 +00:00
union {
struct {
int score ; // Current score.
2016-10-15 00:53:19 +00:00
int last_score ; // Score at beginning of current level.
2016-10-15 00:53:19 +00:00
uint16_t hostages_rescued_total ; // Total number of hostages rescued.
2016-10-15 00:53:19 +00:00
uint8_t hostages_on_board ;
2016-10-15 00:53:19 +00:00
} mission ;
2017-03-18 18:07:36 +00:00
struct {
uint8_t orbs ;
} hoard ;
} ;
enum
{
max_hoard_orbs = 12 ,
2016-10-15 00:53:19 +00:00
} ;
2015-11-14 18:17:21 +00:00
fix64 cloak_time ; // Time cloaked
2015-11-14 18:17:21 +00:00
fix64 invulnerable_time ; // Time invulnerable
2016-07-06 01:54:25 +00:00
fix64 Next_flare_fire_time ;
2016-07-06 01:54:26 +00:00
fix64 Next_laser_fire_time ;
2016-07-06 01:54:26 +00:00
fix64 Next_missile_fire_time ;
2016-07-25 03:48:08 +00:00
fix64 Last_bumped_local_player ;
2016-12-10 17:51:09 +00:00
fix64 Auto_fire_fusion_cannon_time ;
2015-11-07 21:55:58 +00:00
} ;
2015-12-05 22:57:25 +00:00
}
2015-12-13 18:00:49 +00:00
namespace dcx {
2015-12-05 22:57:25 +00:00
2007-12-29 14:18:49 +00:00
// A compressed form for sending crucial data
2019-05-11 20:18:29 +00:00
struct shortpos : prohibit_void_ptr < shortpos >
2013-12-22 22:03:07 +00:00
{
2020-05-02 21:18:42 +00:00
std : : array < int8_t , 9 > bytemat ;
2019-05-11 20:18:29 +00:00
int16_t xo , yo , zo ;
segnum_t segment ;
int16_t velx , vely , velz ;
} ;
2006-03-20 17:12:09 +00:00
2012-05-21 15:06:50 +00:00
// Another compressed form for object position, velocity, orientation and rotvel using quaternion
2018-03-31 21:53:01 +00:00
struct quaternionpos : prohibit_void_ptr < quaternionpos >
2013-12-22 22:03:07 +00:00
{
2018-03-31 21:53:01 +00:00
using packed_size = std : : integral_constant < std : : size_t , sizeof ( vms_quaternion ) + sizeof ( segnum_t ) + ( sizeof ( vms_vector ) * 3 ) > ;
2012-05-21 15:06:50 +00:00
vms_quaternion orient ;
vms_vector pos ;
2018-03-31 21:53:01 +00:00
segnum_t segment ;
2012-05-21 15:06:50 +00:00
vms_vector vel ;
vms_vector rotvel ;
2018-03-31 21:53:01 +00:00
} ;
2012-05-21 15:06:50 +00:00
2006-03-20 17:12:09 +00:00
// stuctures for different kinds of simulation
2015-04-19 04:18:52 +00:00
struct laser_parent
{
2018-12-30 00:43:58 +00:00
int16_t parent_type = { } ; // The type of the parent of this object
objnum_t parent_num = { } ; // The object's parent's number
2019-07-07 22:00:02 +00:00
object_signature_t parent_signature = object_signature_t { 0 } ; // The object's parent's signature...
2015-04-19 04:18:52 +00:00
} ;
struct laser_info : prohibit_void_ptr < laser_info > , laser_parent
2013-12-22 22:03:07 +00:00
{
2018-12-30 00:43:58 +00:00
fix64 creation_time = 0 ; // Absolute time of creation.
2017-01-15 00:03:13 +00:00
/* hitobj_pos specifies the next position to which a value should be
* written . That position may have a defined value if the array has
* wrapped , but should be treated as write - only in the general case .
*
* hitobj_count tells how many elements in hitobj_values [ ] are
* valid . Its valid values are [ 0 , hitobj_values . size ( ) ] . When
* hitobj_count = = hitobj_values . size ( ) , hitobj_pos wraps around and
* begins erasing the oldest elements first .
*/
2018-12-30 00:43:58 +00:00
uint8_t hitobj_pos = 0 , hitobj_count = 0 ;
std : : array < objnum_t , 83 > hitobj_values = { } ;
objnum_t track_goal = 0 ; // Object this object is tracking.
fix multiplier = 0 ; // Power if this is a fusion bolt (or other super weapon to be added).
2019-02-02 18:36:39 +00:00
uint_fast8_t test_set_hitobj ( const vcobjidx_t o ) ;
uint_fast8_t test_hitobj ( const vcobjidx_t o ) const ;
2019-12-16 01:56:59 +00:00
icobjidx_t get_last_hitobj ( ) const ;
2017-01-15 00:03:13 +00:00
void clear_hitobj ( )
{
2017-01-15 00:03:13 +00:00
hitobj_pos = hitobj_count = 0 ;
2017-01-15 00:03:13 +00:00
}
2017-06-10 03:31:02 +00:00
void reset_hitobj ( const icobjidx_t o )
2017-01-15 00:03:13 +00:00
{
if ( o = = object_none )
2017-01-15 00:03:13 +00:00
{
/* Adding object_none to the array is harmless, since
* get_last_hitobj can return object_none for empty arrays .
* However , by filtering it here ( which is called only when
* loading data into new objects ) , test_hitobj ( which is
* called every time the object strikes a potential target )
* will not need to read a slot that is guaranteed not to
* match .
*/
clear_hitobj ( ) ;
2017-01-15 00:03:13 +00:00
return ;
2017-01-15 00:03:13 +00:00
}
/* Assume caller already poisoned the unused array elements */
hitobj_pos = hitobj_count = 1 ;
hitobj_values [ 0 ] = o ;
2017-01-15 00:03:13 +00:00
}
2014-01-11 21:51:29 +00:00
} ;
2006-03-20 17:12:09 +00:00
2020-12-19 16:13:26 +00:00
}
namespace dcx {
2010-12-22 00:17:59 +00:00
// Same as above but structure Savegames/Multiplayer objects expect
2013-12-22 22:03:07 +00:00
struct laser_info_rw
{
2010-12-22 00:17:59 +00:00
short parent_type ; // The type of the parent of this object
short parent_num ; // The object's parent's number
int parent_signature ; // The object's parent's signature...
fix creation_time ; // Absolute time of creation.
2010-12-22 09:41:25 +00:00
short last_hitobj ; // For persistent weapons (survive object collision), object it most recently hit.
2010-12-22 00:17:59 +00:00
short track_goal ; // Object this object is tracking.
fix multiplier ; // Power if this is a fusion bolt (or other super weapon to be added).
2013-12-22 22:03:07 +00:00
} __pack__ ;
2010-12-22 00:17:59 +00:00
2014-11-23 04:36:58 +00:00
struct explosion_info : prohibit_void_ptr < explosion_info >
2013-12-22 23:11:35 +00:00
{
fix spawn_time ; // when lifeleft is < this, spawn another
fix delete_time ; // when to delete object
2013-12-29 04:28:07 +00:00
objnum_t delete_objnum ; // and what object to delete
objnum_t attach_parent ; // explosion is attached to this object
objnum_t prev_attach ; // previous explosion in attach list
objnum_t next_attach ; // next explosion in attach list
2013-12-22 23:11:35 +00:00
} ;
struct explosion_info_rw
2013-12-22 22:03:07 +00:00
{
2006-03-20 17:12:09 +00:00
fix spawn_time ; // when lifeleft is < this, spawn another
fix delete_time ; // when to delete object
short delete_objnum ; // and what object to delete
short attach_parent ; // explosion is attached to this object
short prev_attach ; // previous explosion in attach list
short next_attach ; // next explosion in attach list
2013-12-22 22:03:07 +00:00
} __pack__ ;
2006-03-20 17:12:09 +00:00
2014-11-23 04:36:58 +00:00
struct light_info : prohibit_void_ptr < light_info >
2013-12-22 23:11:35 +00:00
{
fix intensity ; // how bright the light is
} ;
struct light_info_rw
2013-12-22 22:03:07 +00:00
{
2006-03-20 17:12:09 +00:00
fix intensity ; // how bright the light is
2013-12-22 22:03:07 +00:00
} __pack__ ;
2006-03-20 17:12:09 +00:00
2014-11-23 04:36:58 +00:00
struct powerup_info : prohibit_void_ptr < powerup_info >
2013-12-22 22:03:07 +00:00
{
2006-03-20 17:12:09 +00:00
int count ; // how many/much we pick up (vulcan cannon only?)
int flags ; // spat by player?
2013-12-12 23:12:55 +00:00
fix64 creation_time ; // Absolute time of creation.
2014-06-21 23:55:24 +00:00
} ;
2006-03-20 17:12:09 +00:00
2015-12-05 22:57:25 +00:00
}
2015-12-13 18:00:49 +00:00
namespace dsx {
2015-12-05 22:57:25 +00:00
2013-12-22 22:03:07 +00:00
struct powerup_info_rw
{
2010-12-22 00:17:59 +00:00
int count ; // how many/much we pick up (vulcan cannon only?)
2013-12-22 22:03:07 +00:00
# if defined(DXX_BUILD_DESCENT_II)
// Same as above but structure Savegames/Multiplayer objects expect
2010-12-22 00:17:59 +00:00
fix creation_time ; // Absolute time of creation.
int flags ; // spat by player?
2013-03-03 01:03:33 +00:00
# endif
2013-12-22 22:03:07 +00:00
} __pack__ ;
2010-12-22 00:17:59 +00:00
2015-12-05 22:57:25 +00:00
}
2015-12-13 18:00:49 +00:00
namespace dcx {
2015-12-05 22:57:25 +00:00
2014-11-23 04:36:58 +00:00
struct vclip_info : prohibit_void_ptr < vclip_info >
2013-12-22 23:11:35 +00:00
{
int vclip_num ;
fix frametime ;
2016-07-16 16:52:04 +00:00
uint8_t framenum ;
2013-12-22 23:11:35 +00:00
} ;
struct vclip_info_rw
2013-12-22 22:03:07 +00:00
{
2006-03-20 17:12:09 +00:00
int vclip_num ;
fix frametime ;
sbyte framenum ;
2013-12-22 22:03:07 +00:00
} __pack__ ;
2006-03-20 17:12:09 +00:00
// structures for different kinds of rendering
2014-11-23 04:36:58 +00:00
struct polyobj_info : prohibit_void_ptr < polyobj_info >
2013-12-22 23:11:35 +00:00
{
2020-05-02 21:18:42 +00:00
int model_num = 0 ; // which polygon model
2020-05-02 21:18:42 +00:00
std : : array < vms_angvec , MAX_SUBMODELS > anim_angles { } ; // angles for each subobject
2020-05-02 21:18:42 +00:00
int subobj_flags = 0 ; // specify which subobjs to draw
int tmap_override = 0 ; // if this is not -1, map all face to this
int alt_textures = 0 ; // if not -1, use these textures instead
2013-12-22 23:11:35 +00:00
} ;
struct polyobj_info_rw
2013-12-22 22:03:07 +00:00
{
2006-03-20 17:12:09 +00:00
int model_num ; // which polygon model
vms_angvec anim_angles [ MAX_SUBMODELS ] ; // angles for each subobject
int subobj_flags ; // specify which subobjs to draw
int tmap_override ; // if this is not -1, map all face to this
int alt_textures ; // if not -1, use these textures instead
2013-12-22 22:03:07 +00:00
} __pack__ ;
2006-03-20 17:12:09 +00:00
2015-12-22 04:18:50 +00:00
struct object_base
{
2020-08-06 03:47:56 +00:00
enum class control_type : uint8_t ;
2020-08-10 03:45:13 +00:00
enum class movement_type : uint8_t ;
2015-03-22 18:49:21 +00:00
object_signature_t signature ;
2016-11-20 23:12:00 +00:00
object_type_t type ; // what type of object this is... robot, weapon, hostage, powerup, fireball
2006-03-20 17:12:09 +00:00
ubyte id ; // which form of object...which powerup, robot, etc.
2013-12-29 04:28:07 +00:00
objnum_t next , prev ; // id of next and previous connected object in Objects, -1 = no connection
2020-08-10 03:45:13 +00:00
enum control_type control_source ; // how this object is controlled
2020-08-10 03:45:13 +00:00
enum movement_type movement_source ; // how this object moves
2020-05-02 21:18:43 +00:00
render_type_t render_type ; // how this object renders
2006-03-20 17:12:09 +00:00
ubyte flags ; // misc flags
2013-12-29 04:28:07 +00:00
segnum_t segnum ; // segment number containing object
objnum_t attached_obj ; // number of attached fireball object
2006-03-20 17:12:09 +00:00
vms_vector pos ; // absolute x,y,z coordinate of center of object
vms_matrix orient ; // orientation of object in world
fix size ; // 3d size of object - for collision detection
fix shields ; // Starts at maximum, when <0, object dies..
sbyte contains_type ; // Type of object this object contains (eg, spider contains powerup)
sbyte contains_id ; // ID of object this object contains (eg, id = blue type = key)
sbyte contains_count ; // number of objects of type:id this object contains
sbyte matcen_creator ; // Materialization center that created this object, high bit set if matcen-created
fix lifeleft ; // how long until goes away, or 7fff if immortal
// -- Removed, MK, 10/16/95, using lifeleft instead: int lightlevel;
// movement info, determined by MOVEMENT_TYPE
2015-09-22 02:28:38 +00:00
union movement_info {
2006-03-20 17:12:09 +00:00
physics_info phys_info ; // a physics object
vms_vector spin_rate ; // for spinning objects
2015-09-22 02:28:38 +00:00
constexpr movement_info ( ) :
phys_info { }
{
static_assert ( sizeof ( phys_info ) = = sizeof ( * this ) , " insufficient initialization " ) ;
}
2013-12-22 23:11:35 +00:00
} mtype ;
2006-03-20 17:12:09 +00:00
2013-12-26 02:53:14 +00:00
// render info, determined by RENDER_TYPE
2015-09-22 02:28:38 +00:00
union render_info {
2013-12-26 02:53:14 +00:00
struct polyobj_info pobj_info ; // polygon model
struct vclip_info vclip_info ; // vclip
2015-09-22 02:28:38 +00:00
constexpr render_info ( ) :
pobj_info { }
{
static_assert ( sizeof ( pobj_info ) = = sizeof ( * this ) , " insufficient initialization " ) ;
}
2013-12-26 02:53:14 +00:00
} rtype ;
2015-12-22 04:18:50 +00:00
} ;
2013-12-26 02:53:14 +00:00
2020-08-06 03:47:56 +00:00
// Control types - what tells this object what do do
enum class object_base : : control_type : uint8_t
{
None = 0 , // doesn't move (or change movement)
ai = 1 , // driven by AI
explosion = 2 , // explosion sequencer
flying = 4 , // the player is flying
slew = 5 , // slewing
flythrough = 6 , // the flythrough system
weapon = 9 , // laser, etc.
repaircen = 10 , // under the control of the repair center
morph = 11 , // this object is being morphed
debris = 12 , // this is a piece of debris
powerup = 13 , // animating powerup blob
light = 14 , // doesn't actually do anything
remote = 15 , // controlled by another net player
cntrlcen = 16 , // the control center/main reactor
} ;
2020-08-10 03:45:13 +00:00
enum class object_base : : movement_type : uint8_t
{
None = 0 , // doesn't move
physics = 1 , // moves by physics
spinning = 3 , // this object doesn't move, just sits and spins
} ;
2015-12-22 04:18:50 +00:00
}
namespace dsx {
2019-02-02 18:36:39 +00:00
# if defined(DXX_BUILD_DESCENT_II)
struct laser_info : public : : dcx : : laser_info
{
fix64 last_afterburner_time = 0 ; // Time at which this object last created afterburner blobs.
} ;
# endif
2015-12-22 04:18:50 +00:00
struct object : public : : dcx : : object_base
{
2006-03-20 17:12:09 +00:00
// control info, determined by CONTROL_TYPE
2015-06-06 18:03:45 +00:00
union control_info {
constexpr control_info ( ) :
2015-09-22 02:28:38 +00:00
ai_info { }
2015-06-06 18:03:45 +00:00
{
2015-09-22 02:28:38 +00:00
static_assert ( sizeof ( ai_info ) = = sizeof ( * this ) , " insufficient initialization " ) ;
2015-06-06 18:03:45 +00:00
}
2012-11-02 17:13:04 +00:00
struct laser_info laser_info ;
struct explosion_info expl_info ; // NOTE: debris uses this also
struct light_info light_info ; // why put this here? Didn't know what else to do with it.
struct powerup_info powerup_info ;
2013-03-24 20:32:01 +00:00
struct ai_static ai_info ;
2013-03-23 19:09:44 +00:00
struct reactor_static reactor_info ;
2015-11-07 21:55:58 +00:00
struct player_info player_info ;
2013-12-22 23:11:35 +00:00
} ctype ;
2013-03-24 20:32:01 +00:00
} ;
2006-03-20 17:12:09 +00:00
2015-12-05 22:57:25 +00:00
}
2015-12-13 18:00:49 +00:00
namespace dcx {
2015-12-05 22:57:25 +00:00
2010-12-22 00:17:59 +00:00
// Same as above but structure Savegames/Multiplayer objects expect
2013-12-22 22:03:07 +00:00
struct object_rw
{
2010-12-22 00:17:59 +00:00
int signature ; // Every object ever has a unique signature...
ubyte type ; // what type of object this is... robot, weapon, hostage, powerup, fireball
ubyte id ; // which form of object...which powerup, robot, etc.
short next , prev ; // id of next and previous connected object in Objects, -1 = no connection
2020-08-10 03:45:13 +00:00
ubyte control_source ; // how this object is controlled
2020-08-10 03:45:13 +00:00
ubyte movement_source ; // how this object moves
2010-12-22 00:17:59 +00:00
ubyte render_type ; // how this object renders
ubyte flags ; // misc flags
short segnum ; // segment number containing object
short attached_obj ; // number of attached fireball object
vms_vector pos ; // absolute x,y,z coordinate of center of object
vms_matrix orient ; // orientation of object in world
fix size ; // 3d size of object - for collision detection
fix shields ; // Starts at maximum, when <0, object dies..
vms_vector last_pos ; // where object was last frame
sbyte contains_type ; // Type of object this object contains (eg, spider contains powerup)
sbyte contains_id ; // ID of object this object contains (eg, id = blue type = key)
sbyte contains_count ; // number of objects of type:id this object contains
sbyte matcen_creator ; // Materialization center that created this object, high bit set if matcen-created
fix lifeleft ; // how long until goes away, or 7fff if immortal
// -- Removed, MK, 10/16/95, using lifeleft instead: int lightlevel;
// movement info, determined by MOVEMENT_TYPE
union {
2013-12-22 23:11:35 +00:00
physics_info_rw phys_info ; // a physics object
2010-12-22 00:17:59 +00:00
vms_vector spin_rate ; // for spinning objects
} __pack__ mtype ;
// control info, determined by CONTROL_TYPE
union {
laser_info_rw laser_info ;
2013-12-22 23:11:35 +00:00
explosion_info_rw expl_info ; // NOTE: debris uses this also
2010-12-22 00:17:59 +00:00
ai_static_rw ai_info ;
2013-12-22 23:11:35 +00:00
light_info_rw light_info ; // why put this here? Didn't know what else to do with it.
2010-12-22 00:17:59 +00:00
powerup_info_rw powerup_info ;
} __pack__ ctype ;
// render info, determined by RENDER_TYPE
union {
2013-12-22 23:11:35 +00:00
polyobj_info_rw pobj_info ; // polygon model
vclip_info_rw vclip_info ; // vclip
2012-04-17 09:15:09 +00:00
} __pack__ rtype ;
2013-12-22 22:03:07 +00:00
} __pack__ ;
2010-12-22 00:17:59 +00:00
2013-12-22 22:03:07 +00:00
struct obj_position
{
2006-03-20 17:12:09 +00:00
vms_vector pos ; // absolute x,y,z coordinate of center of object
vms_matrix orient ; // orientation of object in world
2013-12-29 04:28:07 +00:00
segnum_t segnum ; // segment number containing object
2013-12-22 22:03:07 +00:00
} ;
2006-03-20 17:12:09 +00:00
2020-12-19 16:13:26 +00:00
}
2016-11-20 23:12:00 +00:00
# define set_object_type(O,T) \
( DXX_BEGIN_COMPOUND_STATEMENT { \
object_base & dxx_object_type_ref = ( O ) ; \
const uint8_t & dxx_object_type_value = ( T ) ; \
assert ( \
dxx_object_type_value = = OBJ_NONE | | \
dxx_object_type_value = = OBJ_FIREBALL | | \
dxx_object_type_value = = OBJ_ROBOT | | \
dxx_object_type_value = = OBJ_HOSTAGE | | \
dxx_object_type_value = = OBJ_PLAYER | | \
dxx_object_type_value = = OBJ_WEAPON | | \
dxx_object_type_value = = OBJ_CAMERA | | \
dxx_object_type_value = = OBJ_POWERUP | | \
dxx_object_type_value = = OBJ_DEBRIS | | \
dxx_object_type_value = = OBJ_CNTRLCEN | | \
dxx_object_type_value = = OBJ_CLUTTER | | \
dxx_object_type_value = = OBJ_GHOST | | \
dxx_object_type_value = = OBJ_LIGHT | | \
dxx_object_type_value = = OBJ_COOP | | \
dxx_object_type_value = = OBJ_MARKER \
) ; \
dxx_object_type_ref . type = static_cast < object_type_t > ( dxx_object_type_value ) ; \
} DXX_END_COMPOUND_STATEMENT )
2020-12-19 16:13:26 +00:00
namespace dsx {
2018-09-09 01:00:39 +00:00
template < typename T , std : : size_t . . . N >
2020-05-02 21:18:42 +00:00
constexpr std : : array < T , sizeof . . . ( N ) > init_object_number_array ( std : : index_sequence < N . . . > )
2018-09-09 01:00:39 +00:00
{
return { { ( ( void ) N , object_none ) . . . } } ;
}
template < typename T , std : : size_t N >
2020-05-02 21:18:42 +00:00
struct object_number_array : std : : array < T , N >
2018-09-09 01:00:39 +00:00
{
constexpr object_number_array ( ) :
2020-05-02 21:18:42 +00:00
std : : array < T , N > ( init_object_number_array < T > ( std : : make_index_sequence < N > ( ) ) )
2018-09-09 01:00:39 +00:00
{
}
} ;
2020-12-19 16:13:26 +00:00
}
namespace dcx {
2019-07-07 22:00:02 +00:00
unsigned laser_parent_is_matching_signature ( const laser_parent & l , const object_base & o ) ;
2019-08-15 01:34:22 +00:00
struct d_level_unique_control_center_state
{
uint8_t Control_center_destroyed ;
2019-08-15 01:34:22 +00:00
uint8_t Control_center_been_hit ;
2019-08-15 01:34:22 +00:00
uint8_t Control_center_present ;
2019-08-15 01:34:22 +00:00
player_visibility_state Control_center_player_been_seen ;
2019-08-15 01:34:22 +00:00
objnum_t Dead_controlcen_object_num ;
2019-08-15 01:34:22 +00:00
int Countdown_seconds_left ;
2019-08-15 01:34:22 +00:00
fix Countdown_timer ;
2019-08-15 01:34:22 +00:00
fix Frametime_until_next_fire ;
2019-08-15 01:34:22 +00:00
/* If the player is not dead, this stays 0. If the player is dead,
* this accumulates FrameTime , up until it saturates . When it
* saturates , the reactor stops firing .
*
* FIXME : The original game defined this in terms of " the player " ,
* but reactors are present in multiplayer games .
*/
fix Frametime_since_player_died ;
2019-08-15 01:34:22 +00:00
int Total_countdown_time ; //in whole seconds
2019-08-15 01:34:22 +00:00
} ;
2019-07-13 22:28:57 +00:00
struct d_level_unique_boss_state
{
fix64 Last_gate_time ;
2019-08-06 02:59:40 +00:00
fix64 Boss_cloak_start_time ;
2019-08-06 02:59:40 +00:00
fix64 Last_teleport_time ;
2019-08-06 02:59:40 +00:00
fix64 Boss_dying_start_time ;
2019-08-06 02:59:40 +00:00
int8_t Boss_hit_this_frame ;
2019-08-06 02:59:40 +00:00
int8_t Boss_dying ;
2019-08-06 02:59:40 +00:00
int8_t Boss_dying_sound_playing ;
2019-07-13 22:28:57 +00:00
} ;
2015-12-05 22:57:25 +00:00
}
2016-01-09 16:38:14 +00:00
# define Highest_object_index (Objects.get_count() - 1)
2013-12-12 21:48:34 +00:00
2015-12-13 18:00:49 +00:00
namespace dsx {
2015-12-05 22:57:25 +00:00
2020-08-06 03:47:56 +00:00
// initialize a new object. adds to the list for the given segment
// returns the object number
2020-08-10 03:45:13 +00:00
imobjptridx_t obj_create ( object_type_t type , unsigned id , vmsegptridx_t segnum , const vms_vector & pos , const vms_matrix * orient , fix size , enum object : : control_type ctype , enum object : : movement_type mtype , render_type_t rtype ) ;
2020-08-06 03:47:56 +00:00
2018-10-08 03:58:48 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2020-07-22 03:11:18 +00:00
/* game_marker_index values are assigned as the object.id field for
* marker objects , and are used as an index into most marker - related
* arrays . These values are scoped to a single level . Each player
* marker has a unique value for game_marker_index , computed based on
* the player ' s ID and the player_marker_index active for that player
* when the marker was created .
*/
enum class game_marker_index : uint8_t
{
GuidebotDeathSite = 10 ,
None = UINT8_MAX
} ;
/* player_marker_index are per-player marker indexes. Each player has
* their own private number space . Valid values range from [ 0 ,
* maxdrop ) , where maxdrop depends on the game type ( single player ,
* competitive multiplayer , or cooperative multiplayer ) .
*/
enum class player_marker_index : uint8_t
{
_0 ,
None = UINT8_MAX
} ;
static inline game_marker_index & operator + + ( game_marker_index & i )
{
auto u = static_cast < unsigned > ( i ) ;
+ + u ;
i = static_cast < game_marker_index > ( u ) ;
return i ;
}
static inline player_marker_index & operator + + ( player_marker_index & i )
{
auto u = static_cast < unsigned > ( i ) ;
+ + u ;
i = static_cast < player_marker_index > ( u ) ;
return i ;
}
2019-03-03 00:31:08 +00:00
struct d_unique_buddy_state
{
2019-05-26 00:44:37 +00:00
enum class Escort_goal_reachability : uint8_t
{
unreachable ,
reachable ,
} ;
2019-03-03 00:31:08 +00:00
icobjidx_t Buddy_objnum = object_none ;
2019-05-26 00:44:37 +00:00
icobjidx_t Escort_goal_objidx = object_none ;
Escort_goal_reachability Escort_goal_reachable = Escort_goal_reachability : : unreachable ;
2019-03-03 00:31:08 +00:00
uint8_t Buddy_allowed_to_talk ;
2019-03-03 00:31:08 +00:00
uint8_t Buddy_messages_suppressed ;
2019-03-03 00:31:08 +00:00
uint8_t Buddy_gave_hint_count ;
2020-07-22 03:11:18 +00:00
game_marker_index Looking_for_marker ;
2019-03-03 00:31:08 +00:00
int Last_buddy_key ;
2019-03-03 00:31:08 +00:00
int Last_buddy_polish_path_tick ;
2019-03-03 00:31:08 +00:00
escort_goal_t Escort_goal_object ;
2019-03-03 00:31:09 +00:00
escort_goal_t Escort_special_goal ;
2019-03-03 00:31:08 +00:00
fix64 Buddy_sorry_time ;
2019-03-03 00:31:08 +00:00
fix64 Buddy_last_seen_player ;
2019-03-03 00:31:09 +00:00
fix64 Buddy_last_missile_time ;
2019-03-03 00:31:09 +00:00
fix64 Last_time_buddy_gave_hint ;
2019-03-03 00:31:09 +00:00
fix64 Last_come_back_message_time ;
2019-03-03 00:31:09 +00:00
fix64 Escort_last_path_created ;
2019-03-03 00:31:09 +00:00
fix64 Buddy_last_player_path_created ;
2019-03-03 00:31:09 +00:00
fix64 Last_buddy_message_time ;
2019-03-03 00:31:08 +00:00
} ;
2019-08-15 01:34:22 +00:00
struct d_level_unique_control_center_state :
: : dcx : : d_level_unique_control_center_state
{
fix64 Last_time_cc_vis_check ;
} ;
2018-10-08 03:58:48 +00:00
class d_guided_missile_indices : object_number_array < imobjidx_t , MAX_PLAYERS >
{
template < typename R , typename F >
R get_player_active_guided_missile_tmpl ( F & fvcobj , unsigned pnum ) const ;
static bool debug_check_current_object ( const object_base & ) ;
public :
imobjidx_t get_player_active_guided_missile ( unsigned pnum ) const ;
imobjptr_t get_player_active_guided_missile ( fvmobjptr & vmobjptr , unsigned pnum ) const ;
imobjptridx_t get_player_active_guided_missile ( fvmobjptridx & vmobjptridx , unsigned pnum ) const ;
void set_player_active_guided_missile ( vmobjidx_t , unsigned pnum ) ;
void clear_player_active_guided_missile ( unsigned pnum ) ;
} ;
2019-06-27 03:26:20 +00:00
2019-08-06 02:59:40 +00:00
struct d_level_unique_boss_state : : : dcx : : d_level_unique_boss_state
{
fix64 Boss_hit_time ;
} ;
2019-06-27 03:26:20 +00:00
const player & get_player_controlling_guidebot ( const d_unique_buddy_state & /* reserved for future use */ , const valptridx < player > : : array_managed_type & Players ) ;
2018-10-08 03:58:48 +00:00
# endif
2019-07-07 22:00:02 +00:00
unsigned laser_parent_is_player ( fvcobjptr & , const laser_parent & , const object_base & ) ;
unsigned laser_parent_is_object ( fvcobjptr & , const laser_parent & , const object_base & ) ;
unsigned laser_parent_is_object ( const laser_parent & , vcobjptridx_t ) ;
unsigned laser_parent_object_exists ( fvcobjptr & , const laser_parent & ) ;
2016-04-06 03:34:13 +00:00
static inline powerup_type_t get_powerup_id ( const object_base & o )
2014-10-05 19:47:30 +00:00
{
2016-04-06 03:34:13 +00:00
return static_cast < powerup_type_t > ( o . id ) ;
2014-10-05 19:47:30 +00:00
}
2016-04-06 03:34:13 +00:00
static inline weapon_id_type get_weapon_id ( const object_base & o )
2014-10-05 19:47:30 +00:00
{
2016-04-06 03:34:13 +00:00
return static_cast < weapon_id_type > ( o . id ) ;
2014-10-05 19:47:30 +00:00
}
2016-04-06 03:34:13 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2020-07-22 03:11:18 +00:00
static inline game_marker_index get_marker_id ( const object_base & o )
2014-10-05 19:47:30 +00:00
{
2020-07-22 03:11:18 +00:00
return game_marker_index { o . id } ;
2014-10-05 19:47:30 +00:00
}
2016-04-06 03:34:13 +00:00
# endif
2018-10-08 03:58:48 +00:00
void set_powerup_id ( const d_powerup_info_array & Powerup_info , const d_vclip_array & Vclip , object_base & o , powerup_type_t id ) ;
2014-10-05 19:47:30 +00:00
2016-04-06 03:34:13 +00:00
static inline void set_weapon_id ( object_base & o , weapon_id_type id )
2014-10-05 19:47:30 +00:00
{
2016-04-06 03:34:13 +00:00
o . id = static_cast < uint8_t > ( id ) ;
}
2014-10-05 19:47:30 +00:00
}
2016-04-06 03:34:13 +00:00
namespace dcx {
2021-06-28 03:37:50 +00:00
static inline unsigned get_player_id ( const object_base & o )
2014-10-05 19:47:30 +00:00
{
2015-09-15 02:48:04 +00:00
return o . id ;
2014-10-05 19:47:30 +00:00
}
2016-04-06 03:34:13 +00:00
static inline uint8_t get_reactor_id ( const object_base & o )
2015-11-27 03:56:13 +00:00
{
return o . id ;
}
2016-04-06 03:34:13 +00:00
static inline uint8_t get_fireball_id ( const object_base & o )
2014-10-05 19:47:30 +00:00
{
2016-04-06 03:34:13 +00:00
return o . id ;
2014-10-05 19:47:30 +00:00
}
2016-04-06 03:34:13 +00:00
static inline uint8_t get_robot_id ( const object_base & o )
2014-10-05 19:47:30 +00:00
{
2016-04-06 03:34:13 +00:00
return o . id ;
2014-10-05 19:47:30 +00:00
}
2016-04-06 03:34:13 +00:00
static inline void set_player_id ( object_base & o , const uint8_t id )
2015-11-27 03:56:13 +00:00
{
o . id = id ;
}
2016-04-06 03:34:13 +00:00
static inline void set_reactor_id ( object_base & o , const uint8_t id )
2014-10-05 19:47:30 +00:00
{
2015-09-15 02:48:04 +00:00
o . id = id ;
2014-10-05 19:47:30 +00:00
}
2016-04-06 03:34:13 +00:00
static inline void set_robot_id ( object_base & o , const uint8_t id )
2014-10-05 19:47:30 +00:00
{
2016-04-06 03:34:13 +00:00
o . id = id ;
2014-10-05 19:47:30 +00:00
}
2015-11-26 02:56:56 +00:00
2016-04-06 03:34:13 +00:00
void check_warn_object_type ( const object_base & , object_type_t , const char * file , unsigned line ) ;
2015-11-26 02:56:56 +00:00
# define get_player_id(O) (check_warn_object_type(O, OBJ_PLAYER, __FILE__, __LINE__), get_player_id(O))
# define get_powerup_id(O) (check_warn_object_type(O, OBJ_POWERUP, __FILE__, __LINE__), get_powerup_id(O))
# define get_reactor_id(O) (check_warn_object_type(O, OBJ_CNTRLCEN, __FILE__, __LINE__), get_reactor_id(O))
2016-03-20 20:38:54 +00:00
# define get_ghost_id(O) (check_warn_object_type(O, OBJ_GHOST, __FILE__, __LINE__), (get_player_id)(O))
2015-11-27 03:56:13 +00:00
# define get_fireball_id(O) (check_warn_object_type(O, OBJ_FIREBALL, __FILE__, __LINE__), get_fireball_id(O))
2015-11-26 02:56:56 +00:00
# define get_robot_id(O) (check_warn_object_type(O, OBJ_ROBOT, __FILE__, __LINE__), get_robot_id(O))
# define get_weapon_id(O) (check_warn_object_type(O, OBJ_WEAPON, __FILE__, __LINE__), get_weapon_id(O))
2016-04-06 03:34:13 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2015-11-27 03:56:13 +00:00
# define get_marker_id(O) (check_warn_object_type(O, OBJ_MARKER, __FILE__, __LINE__), get_marker_id(O))
2016-04-06 03:34:13 +00:00
# endif
2015-11-26 02:56:56 +00:00
# define set_player_id(O,I) (check_warn_object_type(O, OBJ_PLAYER, __FILE__, __LINE__), set_player_id(O, I))
2015-11-27 03:56:13 +00:00
# define set_reactor_id(O,I) (check_warn_object_type(O, OBJ_CNTRLCEN, __FILE__, __LINE__), set_reactor_id(O, I))
2015-11-26 02:56:56 +00:00
# define set_robot_id(O,I) (check_warn_object_type(O, OBJ_ROBOT, __FILE__, __LINE__), set_robot_id(O, I))
# define set_weapon_id(O,I) (check_warn_object_type(O, OBJ_WEAPON, __FILE__, __LINE__), set_weapon_id(O, I))
2016-03-05 17:26:24 +00:00
# ifdef DXX_CONSTANT_TRUE
2015-11-27 03:56:12 +00:00
# define check_warn_object_type(O,T,F,L) \
2016-03-05 17:26:24 +00:00
( DXX_BEGIN_COMPOUND_STATEMENT { \
2016-04-06 03:34:13 +00:00
const object_base & dxx_check_warn_o = ( O ) ; \
2016-05-21 17:24:51 +00:00
const auto dxx_check_warn_actual_type = dxx_check_warn_o . type ; \
const auto dxx_check_warn_expected_type = ( T ) ; \
2015-11-27 03:56:12 +00:00
/* If the type is always right, omit the runtime check. */ \
2016-05-21 17:24:51 +00:00
DXX_CONSTANT_TRUE ( dxx_check_warn_actual_type = = dxx_check_warn_expected_type ) | | ( \
2016-03-05 17:26:24 +00:00
/* If the type is always wrong, force a compile-time error. */ \
2016-05-21 17:24:51 +00:00
DXX_CONSTANT_TRUE ( dxx_check_warn_actual_type ! = dxx_check_warn_expected_type ) \
2016-03-05 17:26:24 +00:00
? DXX_ALWAYS_ERROR_FUNCTION ( dxx_error_object_type_mismatch , " object type mismatch " ) \
2016-05-21 17:24:51 +00:00
: ( \
check_warn_object_type ( dxx_check_warn_o , dxx_check_warn_expected_type , F , L ) \
2016-03-05 17:26:24 +00:00
) \
, 0 ) ; \
} DXX_END_COMPOUND_STATEMENT )
2015-11-26 02:56:56 +00:00
# endif
2015-12-05 22:57:25 +00:00
}
2013-03-24 20:32:01 +00:00
2006-03-20 17:12:09 +00:00
# endif