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 .
*/
/*
*
* Header for robot . c
*
*/
2015-12-03 03:26:49 +00:00
# pragma once
2006-03-20 17:12:09 +00:00
# include "vecmat.h"
# include "game.h"
2013-10-09 03:12:09 +00:00
# ifdef __cplusplus
2014-12-18 04:12:38 +00:00
# include "pack.h"
2017-01-22 09:55:42 +00:00
# include "ai.h"
2015-04-26 20:15:51 +00:00
# include "aistruct.h"
2015-04-02 02:36:57 +00:00
# include "polyobj.h"
2015-12-03 03:26:49 +00:00
# include "weapon_id.h"
2017-01-22 09:55:42 +00:00
# include "object.h"
2020-06-10 02:25:32 +00:00
# include "fwd-partial_range.h"
2013-10-09 03:12:09 +00:00
2006-03-20 17:12:09 +00:00
# define MAX_GUNS 8 //should be multiple of 4 for ubyte array
//Animation states
# define AS_REST 0
# define AS_ALERT 1
# define AS_FIRE 2
# define AS_RECOIL 3
# define AS_FLINCH 4
# define N_ANIM_STATES 5
# define RI_CLOAKED_ALWAYS 1
2016-06-25 23:21:36 +00:00
namespace dcx {
2010-02-07 07:28:49 +00:00
2006-03-20 17:12:09 +00:00
//describes the position of a certain joint
2014-12-18 04:12:38 +00:00
struct jointpos : prohibit_void_ptr < jointpos >
2013-12-22 22:03:07 +00:00
{
2018-12-30 00:43:59 +00:00
uint16_t jointnum ;
2006-03-20 17:12:09 +00:00
vms_angvec angles ;
2018-12-30 00:43:59 +00:00
} ;
2006-03-20 17:12:09 +00:00
//describes a list of joint positions
2013-12-22 22:03:07 +00:00
struct jointlist
{
2006-03-20 17:12:09 +00:00
short n_joints ;
short offset ;
2013-12-22 22:03:07 +00:00
} ;
2006-03-20 17:12:09 +00:00
2017-10-14 17:10:30 +00:00
constexpr std : : integral_constant < unsigned , 16 > ROBOT_NAME_LENGTH { } ;
2020-08-24 01:31:28 +00:00
struct d_level_shared_robot_joint_state {
unsigned N_robot_joints ;
} ;
2016-06-25 23:21:36 +00:00
}
2015-11-26 02:56:55 +00:00
# if defined(DXX_BUILD_DESCENT_I) || defined(DXX_BUILD_DESCENT_II)
2016-06-25 23:21:36 +00:00
namespace dsx {
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
//robot info flags
# define RIF_BIG_RADIUS 1 //pad the radius to fix robots firing through walls
# define RIF_THIEF 2 //this guy steals!
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
// Robot information
2015-01-23 03:55:04 +00:00
struct robot_info : prohibit_void_ptr < robot_info >
2013-12-22 22:03:07 +00:00
{
2006-03-20 17:12:09 +00:00
int model_num ; // which polygon model?
2020-05-02 21:18:42 +00:00
std : : array < vms_vector , MAX_GUNS > gun_points ; // where each gun model is
std : : array < uint8_t , MAX_GUNS > gun_submodels ; // which submodel is each gun in?
2015-12-03 03:26:48 +00:00
uint16_t score_value ; // Score from this robot.
2006-03-20 17:12:09 +00:00
short exp1_vclip_num ;
short exp1_sound_num ;
short exp2_vclip_num ;
short exp2_sound_num ;
2015-12-03 03:26:49 +00:00
weapon_id_type weapon_type ;
2015-12-03 03:26:48 +00:00
uint8_t n_guns ; // how many different gun positions
2006-03-20 17:12:09 +00:00
sbyte contains_id ; // ID of powerup this robot can contain.
sbyte contains_count ; // Max number of things this instance can contain.
sbyte contains_prob ; // Probability that this instance will contain something in N/16
sbyte contains_type ; // Type of thing contained, robot or powerup, in bitmaps.tbl, !0=robot, 0=powerup
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
# elif defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
sbyte kamikaze ; // !0 means commits suicide when hits you, strength thereof. 0 means no.
sbyte badass ; // Dies with badass explosion, and strength thereof, 0 means NO.
sbyte energy_drain ; // Points of energy drained at each collision.
2015-12-03 03:26:49 +00:00
weapon_id_type weapon_type2 ; // Secondary weapon number, -1 means none, otherwise gun #0 fires this weapon.
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
fix lighting ; // should this be here or with polygon model?
fix strength ; // Initial shields of robot
fix mass ; // how heavy is this thing?
fix drag ; // how much drag does it have?
2020-05-02 21:18:42 +00:00
std : : array < fix , NDL > field_of_view , // compare this value with forward_vector.dot.vector_to_player, if field_of_view <, then robot can see player
2015-02-28 19:36:01 +00:00
firing_wait , // time in seconds between shots
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2015-02-28 19:36:01 +00:00
firing_wait2 , // time in seconds between shots
2013-03-03 01:03:33 +00:00
# endif
2015-02-28 19:36:01 +00:00
turn_time , // time in seconds to rotate 360 degrees in a dimension
max_speed , // maximum speed attainable by this robot
circle_distance ; // distance at which robot circles player
2006-03-20 17:12:09 +00:00
2020-05-02 21:18:42 +00:00
std : : array < int8_t , NDL > rapidfire_count , // number of shots fired rapidly
2015-02-28 19:36:01 +00:00
evade_speed ; // rate at which robot can evade shots, 0=none, 4=very fast
2006-03-20 17:12:09 +00:00
sbyte cloak_type ; // 0=never, 1=always, 2=except-when-firing
sbyte attack_type ; // 0=firing, 1=charge (like green guy)
ubyte see_sound ; // sound robot makes when it first sees the player
ubyte attack_sound ; // sound robot makes when it attacks the player
ubyte claw_sound ; // sound robot makes as it claws you (attack_type should be 1)
2013-03-03 01:03:33 +00:00
sbyte boss_flag ; // 0 = not boss, 1 = boss. Is that surprising?
# if defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
ubyte taunt_sound ; // sound robot makes after you die
sbyte companion ; // Companion robot, leads you to things.
sbyte smart_blobs ; // how many smart blobs are emitted when this guy dies!
sbyte energy_blobs ; // how many smart blobs are emitted when this guy gets hit by energy weapon!
sbyte thief ; // !0 means this guy can steal when he collides with you!
sbyte pursuit ; // !0 means pursues player after he goes around a corner. 4 = 4/2 pursue up to 4/2 seconds after becoming invisible if up to 4 segments away
sbyte lightcast ; // Amount of light cast. 1 is default. 10 is very large.
sbyte death_roll ; // 0 = dies without death roll. !0 means does death roll, larger = faster and louder
//boss_flag, companion, thief, & pursuit probably should also be bits in the flags byte.
ubyte flags ; // misc properties
ubyte deathroll_sound ; // if has deathroll, what sound?
ubyte glow ; // apply this light to robot itself. stored as 4:4 fixed-point
2015-04-26 20:15:51 +00:00
ai_behavior behavior ; // Default behavior.
2006-03-20 17:12:09 +00:00
ubyte aim ; // 255 = perfect, less = more likely to miss. 0 != random, would look stupid. 0=45 degree spread. Specify in bitmaps.tbl in range 0.0..1.0
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
//animation info
2020-05-02 21:18:42 +00:00
std : : array < std : : array < jointlist , N_ANIM_STATES > , MAX_GUNS + 1 > anim_states ;
2006-03-20 17:12:09 +00:00
int always_0xabcd ; // debugging
2015-01-23 03:55:04 +00:00
} ;
2016-06-25 23:21:36 +00:00
}
2006-03-20 17:12:09 +00:00
2016-07-23 04:10:42 +00:00
constexpr auto weapon_none = weapon_id_type : : unspecified ;
2006-03-20 17:12:09 +00:00
2016-06-25 23:21:36 +00:00
namespace dsx {
2019-03-03 00:31:09 +00:00
imobjptridx_t robot_create ( unsigned id , vmsegptridx_t segnum , const vms_vector & pos , const vms_matrix * orient , fix size , ai_behavior behavior , const imsegidx_t hide_segment = segment_none ) ;
2017-01-22 09:55:42 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2016-06-25 23:21:36 +00:00
// maximum number of robot types
2017-10-14 17:10:30 +00:00
constexpr std : : integral_constant < unsigned , 30 > MAX_ROBOT_TYPES { } ;
constexpr std : : integral_constant < unsigned , 600 > MAX_ROBOT_JOINTS { } ;
2013-11-03 22:27:28 +00:00
2017-08-26 19:47:51 +00:00
static inline int robot_is_companion ( const robot_info & )
2013-11-03 22:27:28 +00:00
{
return 0 ;
}
2013-11-03 22:27:28 +00:00
2017-08-26 19:47:51 +00:00
static inline int robot_is_thief ( const robot_info & )
2013-11-03 22:27:28 +00:00
{
return 0 ;
}
2013-03-03 01:03:33 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2016-06-25 23:21:36 +00:00
// maximum number of robot types
2017-10-14 17:10:30 +00:00
constexpr std : : integral_constant < unsigned , 85 > MAX_ROBOT_TYPES { } ;
constexpr std : : integral_constant < unsigned , 1600 > MAX_ROBOT_JOINTS { } ;
2013-11-03 22:27:28 +00:00
2017-08-26 19:47:51 +00:00
static inline int robot_is_companion ( const robot_info & robptr )
2013-11-03 22:27:28 +00:00
{
2017-08-26 19:47:51 +00:00
return robptr . companion ;
2013-11-03 22:27:28 +00:00
}
2013-11-03 22:27:28 +00:00
2017-08-26 19:47:51 +00:00
static inline int robot_is_thief ( const robot_info & robptr )
2013-11-03 22:27:28 +00:00
{
2017-08-26 19:47:51 +00:00
return robptr . thief ;
2013-11-03 22:27:28 +00:00
}
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
//the array of robots types
2018-12-30 00:43:59 +00:00
struct d_level_shared_robot_info_state
{
2020-05-02 21:18:42 +00:00
using d_robot_info_array = std : : array < robot_info , MAX_ROBOT_TYPES > ;
2018-12-30 00:43:59 +00:00
//how many kinds of robots
unsigned N_robot_types ; // Number of robot types. We used to assume this was the same as N_polygon_models.
2018-12-30 00:43:59 +00:00
// Robot info for AI system, loaded from bitmaps.tbl.
d_robot_info_array Robot_info ;
} ;
extern d_level_shared_robot_info_state LevelSharedRobotInfoState ;
2018-09-19 02:13:29 +00:00
# if defined(DXX_BUILD_DESCENT_II)
// returns ptr to escort robot, or NULL
2018-12-30 00:43:59 +00:00
imobjptridx_t find_escort ( fvmobjptridx & vmobjptridx , const d_level_shared_robot_info_state : : d_robot_info_array & Robot_info ) ;
2018-09-19 02:13:29 +00:00
# endif
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2020-05-02 21:18:42 +00:00
using robot_names_array = std : : array < std : : array < char , ROBOT_NAME_LENGTH > , MAX_ROBOT_TYPES > ;
2016-07-09 17:58:34 +00:00
extern robot_names_array Robot_names ;
# endif
2018-12-30 00:43:59 +00:00
/* Robot joints can be customized by hxm files, which are per-level.
*/
2020-08-24 01:31:28 +00:00
struct d_level_shared_robot_joint_state : : : dcx : : d_level_shared_robot_joint_state
2018-12-30 00:43:59 +00:00
{
//Big array of joint positions. All robots index into this array
2020-05-02 21:18:42 +00:00
std : : array < jointpos , MAX_ROBOT_JOINTS > Robot_joints ;
2018-12-30 00:43:59 +00:00
} ;
extern d_level_shared_robot_joint_state LevelSharedRobotJointState ;
2016-06-25 23:21:36 +00:00
}
2006-03-20 17:12:09 +00:00
2016-06-25 23:21:36 +00:00
namespace dsx {
2006-03-20 17:12:09 +00:00
//given an object and a gun number, return position in 3-space of gun
//fills in gun_point
2016-04-09 21:40:27 +00:00
void calc_gun_point ( vms_vector & gun_point , const object_base & obj , unsigned gun_num ) ;
2006-03-20 17:12:09 +00:00
// Tells joint positions for a gun to be in a specified state.
// A gun can have associated with it any number of joints. In order to tell whether a gun is a certain
// state (such as FIRE or ALERT), you should call this function and check the returned joint positions
// against the robot's gun's joint positions. This function should also be called to determine how to
// move a gun into a desired position.
// For now (May 30, 1994), it is assumed that guns will linearly interpolate from one joint position to another.
// There is no ordering of joint movement, so it's impossible to guarantee that a strange starting position won't
// cause a gun to move through a robot's body, for example.
// Given:
// jp_list_ptr pointer to list of joint angles, on exit, this is pointing at a static array
// robot_type type of robot for which to get joint information. A particular type, not an instance of a robot.
// gun_num gun number. If in 0..Robot_info[robot_type].n_guns-1, then it is a gun, else it refers to non-animating parts of robot.
// state state about which to get information. Legal states in range 0..N_ANIM_STATES-1, defined in robot.h, are:
// AS_REST, AS_ALERT, AS_FIRE, AS_RECOIL, AS_FLINCH
// On exit:
// Returns number of joints in list.
// jp_list_ptr is stuffed with a pointer to a static array of joint positions. This pointer is valid forever.
2020-05-02 21:18:42 +00:00
partial_range_t < const jointpos * > robot_get_anim_state ( const d_level_shared_robot_info_state : : d_robot_info_array & , const std : : array < jointpos , MAX_ROBOT_JOINTS > & , unsigned robot_type , unsigned gun_num , unsigned state ) ;
2006-03-20 17:12:09 +00:00
/*
2016-01-09 16:38:14 +00:00
* reads n robot_info structs from a PHYSFS_File
2006-03-20 17:12:09 +00:00
*/
2015-01-23 03:55:04 +00:00
void robot_info_read ( PHYSFS_File * fp , robot_info & r ) ;
2016-08-06 19:55:24 +00:00
}
# endif
2006-03-20 17:12:09 +00:00
/*
2016-01-09 16:38:14 +00:00
* reads n jointpos structs from a PHYSFS_File
2006-03-20 17:12:09 +00:00
*/
2016-01-09 16:38:14 +00:00
void jointpos_read ( PHYSFS_File * fp , jointpos & jp ) ;
2015-12-04 03:36:31 +00:00
#if 0
2016-01-09 16:38:14 +00:00
void jointpos_write ( PHYSFS_File * fp , const jointpos & jp ) ;
2015-12-04 03:36:31 +00:00
# endif
2016-08-06 19:55:24 +00:00
# ifdef dsx
2016-04-09 21:40:27 +00:00
namespace dsx {
2020-05-02 21:18:42 +00:00
void robot_set_angles ( robot_info * r , polymodel * pm , std : : array < std : : array < vms_angvec , MAX_SUBMODELS > , N_ANIM_STATES > & angs ) ;
2015-12-03 03:26:49 +00:00
weapon_id_type get_robot_weapon ( const robot_info & ri , const unsigned gun_num ) ;
2017-02-24 12:21:44 +00:00
static inline void boss_link_see_sound ( const vcobjptridx_t objp )
{
# if defined(DXX_BUILD_DESCENT_I)
2018-05-13 03:14:34 +00:00
constexpr unsigned soundnum = SOUND_BOSS_SHARE_SEE ;
2017-02-24 12:21:44 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2018-12-30 00:43:59 +00:00
auto & Robot_info = LevelSharedRobotInfoState . Robot_info ;
2018-05-13 03:14:34 +00:00
const unsigned soundnum = Robot_info [ get_robot_id ( objp ) ] . see_sound ;
2017-02-24 12:21:44 +00:00
# endif
2018-05-13 03:14:34 +00:00
digi_link_sound_to_object2 ( soundnum , objp , 1 , F1_0 , sound_stack : : allow_stacking , vm_distance { F1_0 * 512 } ) ; // F1_0*512 means play twice as loud
2017-02-24 12:21:44 +00:00
}
2018-12-30 00:43:59 +00:00
}
2016-08-06 19:55:24 +00:00
# endif
2013-10-09 03:12:09 +00:00
2008-10-28 17:58:54 +00:00
# endif