Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Portions of this file are copyright Rebirth contributors and licensed as
  3.  * described in COPYING.txt.
  4.  * Portions of this file are copyright Parallax Software and licensed
  5.  * according to the Parallax license below.
  6.  * See COPYING.txt for license details.
  7.  
  8. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  9. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  10. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  11. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  12. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  13. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  14. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  15. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  16. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  17. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  18. */
  19.  
  20. /*
  21.  *
  22.  * Header for robot.c
  23.  *
  24.  */
  25.  
  26. #pragma once
  27.  
  28. #include "vecmat.h"
  29. #include "game.h"
  30.  
  31. #ifdef __cplusplus
  32. #include "pack.h"
  33. #include "ai.h"
  34. #include "aistruct.h"
  35. #include "polyobj.h"
  36. #include "weapon_id.h"
  37. #include "object.h"
  38. #include "fwd-partial_range.h"
  39.  
  40. #define MAX_GUNS 8      //should be multiple of 4 for ubyte array
  41.  
  42. //Animation states
  43. #define AS_REST         0
  44. #define AS_ALERT        1
  45. #define AS_FIRE         2
  46. #define AS_RECOIL       3
  47. #define AS_FLINCH       4
  48. #define N_ANIM_STATES   5
  49.  
  50. #define RI_CLOAKED_ALWAYS           1
  51.  
  52. namespace dcx {
  53.  
  54. //describes the position of a certain joint
  55. struct jointpos : prohibit_void_ptr<jointpos>
  56. {
  57.         uint16_t jointnum;
  58.         vms_angvec angles;
  59. };
  60.  
  61. //describes a list of joint positions
  62. struct jointlist
  63. {
  64.         short n_joints;
  65.         short offset;
  66. };
  67.  
  68. constexpr std::integral_constant<unsigned, 16> ROBOT_NAME_LENGTH{};
  69. }
  70.  
  71. #if defined(DXX_BUILD_DESCENT_I) || defined(DXX_BUILD_DESCENT_II)
  72. namespace dsx {
  73. #if defined(DXX_BUILD_DESCENT_II)
  74. //robot info flags
  75. #define RIF_BIG_RADIUS  1   //pad the radius to fix robots firing through walls
  76. #define RIF_THIEF       2   //this guy steals!
  77. #endif
  78.  
  79. //  Robot information
  80. struct robot_info : prohibit_void_ptr<robot_info>
  81. {
  82.         int     model_num;                  // which polygon model?
  83.         std::array<vms_vector, MAX_GUNS>  gun_points;   // where each gun model is
  84.         std::array<uint8_t, MAX_GUNS>   gun_submodels;    // which submodel is each gun in?
  85.         uint16_t score_value;                                           //      Score from this robot.
  86.         short   exp1_vclip_num;
  87.         short   exp1_sound_num;
  88.         short   exp2_vclip_num;
  89.         short   exp2_sound_num;
  90.         weapon_id_type weapon_type;
  91.         uint8_t   n_guns;         // how many different gun positions
  92.         sbyte   contains_id;    //  ID of powerup this robot can contain.
  93.  
  94.         sbyte   contains_count; //  Max number of things this instance can contain.
  95.         sbyte   contains_prob;  //  Probability that this instance will contain something in N/16
  96.         sbyte   contains_type;  //  Type of thing contained, robot or powerup, in bitmaps.tbl, !0=robot, 0=powerup
  97. #if defined(DXX_BUILD_DESCENT_I)
  98. #elif defined(DXX_BUILD_DESCENT_II)
  99.         sbyte   kamikaze;       //  !0 means commits suicide when hits you, strength thereof. 0 means no.
  100.  
  101.         sbyte   badass;         //  Dies with badass explosion, and strength thereof, 0 means NO.
  102.         sbyte   energy_drain;   //  Points of energy drained at each collision.
  103.         weapon_id_type   weapon_type2;   //  Secondary weapon number, -1 means none, otherwise gun #0 fires this weapon.
  104. #endif
  105.         fix     lighting;       // should this be here or with polygon model?
  106.         fix     strength;       // Initial shields of robot
  107.  
  108.         fix     mass;           // how heavy is this thing?
  109.         fix     drag;           // how much drag does it have?
  110.  
  111.         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
  112.                 firing_wait,   //  time in seconds between shots
  113. #if defined(DXX_BUILD_DESCENT_II)
  114.                 firing_wait2,  //  time in seconds between shots
  115. #endif
  116.                 turn_time,     // time in seconds to rotate 360 degrees in a dimension
  117.                 max_speed,         //  maximum speed attainable by this robot
  118.                 circle_distance;   //  distance at which robot circles player
  119.  
  120.         std::array<int8_t, NDL>   rapidfire_count,   //  number of shots fired rapidly
  121.                 evade_speed;       //  rate at which robot can evade shots, 0=none, 4=very fast
  122.         sbyte   cloak_type;     //  0=never, 1=always, 2=except-when-firing
  123.         sbyte   attack_type;    //  0=firing, 1=charge (like green guy)
  124.  
  125.         ubyte   see_sound;      //  sound robot makes when it first sees the player
  126.         ubyte   attack_sound;   //  sound robot makes when it attacks the player
  127.         ubyte   claw_sound;     //  sound robot makes as it claws you (attack_type should be 1)
  128.         sbyte   boss_flag;      //  0 = not boss, 1 = boss.  Is that surprising?
  129. #if defined(DXX_BUILD_DESCENT_II)
  130.         ubyte   taunt_sound;    //  sound robot makes after you die
  131.  
  132.         sbyte   companion;      //  Companion robot, leads you to things.
  133.         sbyte   smart_blobs;    //  how many smart blobs are emitted when this guy dies!
  134.         sbyte   energy_blobs;   //  how many smart blobs are emitted when this guy gets hit by energy weapon!
  135.  
  136.         sbyte   thief;          //  !0 means this guy can steal when he collides with you!
  137.         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
  138.         sbyte   lightcast;      //  Amount of light cast. 1 is default.  10 is very large.
  139.         sbyte   death_roll;     //  0 = dies without death roll. !0 means does death roll, larger = faster and louder
  140.  
  141.         //boss_flag, companion, thief, & pursuit probably should also be bits in the flags byte.
  142.         ubyte   flags;          // misc properties
  143.  
  144.         ubyte   deathroll_sound;    // if has deathroll, what sound?
  145.         ubyte   glow;               // apply this light to robot itself. stored as 4:4 fixed-point
  146.         ai_behavior behavior;           //  Default behavior.
  147.         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
  148. #endif
  149.         //animation info
  150.         std::array<std::array<jointlist, N_ANIM_STATES>, MAX_GUNS+1> anim_states;
  151.         int     always_0xabcd;      // debugging
  152. };
  153. }
  154.  
  155. constexpr auto weapon_none = weapon_id_type::unspecified;
  156.  
  157. namespace dsx {
  158. 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);
  159.  
  160. #if defined(DXX_BUILD_DESCENT_I)
  161. // maximum number of robot types
  162. constexpr std::integral_constant<unsigned, 30> MAX_ROBOT_TYPES{};
  163. constexpr std::integral_constant<unsigned, 600> MAX_ROBOT_JOINTS{};
  164.  
  165. static inline int robot_is_companion(const robot_info &)
  166. {
  167.         return 0;
  168. }
  169.  
  170. static inline int robot_is_thief(const robot_info &)
  171. {
  172.         return 0;
  173. }
  174. #elif defined(DXX_BUILD_DESCENT_II)
  175. // maximum number of robot types
  176. constexpr std::integral_constant<unsigned, 85> MAX_ROBOT_TYPES{};
  177. constexpr std::integral_constant<unsigned, 1600> MAX_ROBOT_JOINTS{};
  178.  
  179. static inline int robot_is_companion(const robot_info &robptr)
  180. {
  181.         return robptr.companion;
  182. }
  183.  
  184. static inline int robot_is_thief(const robot_info &robptr)
  185. {
  186.         return robptr.thief;
  187. }
  188. #endif
  189.  
  190. //the array of robots types
  191. struct d_level_shared_robot_info_state
  192. {
  193.         using d_robot_info_array = std::array<robot_info, MAX_ROBOT_TYPES>;
  194.         //how many kinds of robots
  195.         unsigned N_robot_types;      // Number of robot types.  We used to assume this was the same as N_polygon_models.
  196.         // Robot info for AI system, loaded from bitmaps.tbl.
  197.         d_robot_info_array Robot_info;
  198. };
  199.  
  200. extern d_level_shared_robot_info_state LevelSharedRobotInfoState;
  201.  
  202. #if defined(DXX_BUILD_DESCENT_II)
  203. // returns ptr to escort robot, or NULL
  204. imobjptridx_t find_escort(fvmobjptridx &vmobjptridx, const d_level_shared_robot_info_state::d_robot_info_array &Robot_info);
  205. #endif
  206.  
  207. #if DXX_USE_EDITOR
  208. using robot_names_array = std::array<std::array<char, ROBOT_NAME_LENGTH>, MAX_ROBOT_TYPES>;
  209. extern robot_names_array Robot_names;
  210. #endif
  211.  
  212. /* Robot joints can be customized by hxm files, which are per-level.
  213.  */
  214. struct d_level_shared_robot_joint_state
  215. {
  216.         //Big array of joint positions.  All robots index into this array
  217.         std::array<jointpos, MAX_ROBOT_JOINTS> Robot_joints;
  218. };
  219.  
  220. extern d_level_shared_robot_joint_state LevelSharedRobotJointState;
  221. }
  222.  
  223. namespace dcx {
  224.  
  225. extern unsigned N_robot_joints;
  226. }
  227.  
  228. namespace dsx {
  229. //given an object and a gun number, return position in 3-space of gun
  230. //fills in gun_point
  231. void calc_gun_point(vms_vector &gun_point, const object_base &obj, unsigned gun_num);
  232.  
  233. //  Tells joint positions for a gun to be in a specified state.
  234. //  A gun can have associated with it any number of joints.  In order to tell whether a gun is a certain
  235. //  state (such as FIRE or ALERT), you should call this function and check the returned joint positions
  236. //  against the robot's gun's joint positions.  This function should also be called to determine how to
  237. //  move a gun into a desired position.
  238. //  For now (May 30, 1994), it is assumed that guns will linearly interpolate from one joint position to another.
  239. //  There is no ordering of joint movement, so it's impossible to guarantee that a strange starting position won't
  240. //  cause a gun to move through a robot's body, for example.
  241.  
  242. //  Given:
  243. //      jp_list_ptr     pointer to list of joint angles, on exit, this is pointing at a static array
  244. //      robot_type      type of robot for which to get joint information.  A particular type, not an instance of a robot.
  245. //      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.
  246. //      state           state about which to get information.  Legal states in range 0..N_ANIM_STATES-1, defined in robot.h, are:
  247. //                          AS_REST, AS_ALERT, AS_FIRE, AS_RECOIL, AS_FLINCH
  248.  
  249. //  On exit:
  250. //      Returns number of joints in list.
  251. //      jp_list_ptr is stuffed with a pointer to a static array of joint positions.  This pointer is valid forever.
  252. 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);
  253.  
  254. /*
  255.  * reads n robot_info structs from a PHYSFS_File
  256.  */
  257. void robot_info_read(PHYSFS_File *fp, robot_info &r);
  258. }
  259. #endif
  260.  
  261. /*
  262.  * reads n jointpos structs from a PHYSFS_File
  263.  */
  264. void jointpos_read(PHYSFS_File *fp, jointpos &jp);
  265. #if 0
  266. void jointpos_write(PHYSFS_File *fp, const jointpos &jp);
  267. #endif
  268. #ifdef dsx
  269. namespace dsx {
  270. void robot_set_angles(robot_info *r,polymodel *pm, std::array<std::array<vms_angvec, MAX_SUBMODELS>, N_ANIM_STATES> &angs);
  271. weapon_id_type get_robot_weapon(const robot_info &ri, const unsigned gun_num);
  272.  
  273. static inline void boss_link_see_sound(const vcobjptridx_t objp)
  274. {
  275. #if defined(DXX_BUILD_DESCENT_I)
  276.         constexpr unsigned soundnum = SOUND_BOSS_SHARE_SEE;
  277. #elif defined(DXX_BUILD_DESCENT_II)
  278.         auto &Robot_info = LevelSharedRobotInfoState.Robot_info;
  279.         const unsigned soundnum = Robot_info[get_robot_id(objp)].see_sound;
  280. #endif
  281.         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
  282. }
  283. }
  284. #endif
  285.  
  286. #endif
  287.