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.  * Code for controlling player movement
  23.  *
  24.  */
  25.  
  26.  
  27. #include <algorithm>
  28. #include <stdlib.h>
  29. #include "key.h"
  30. #include "joy.h"
  31. #include "timer.h"
  32. #include "dxxerror.h"
  33. #include "inferno.h"
  34. #include "game.h"
  35. #include "object.h"
  36. #include "player.h"
  37. #include "weapon.h"
  38. #include "bm.h"
  39. #include "controls.h"
  40. #include "render.h"
  41. #include "args.h"
  42. #include "palette.h"
  43. #include "mouse.h"
  44. #include "kconfig.h"
  45. #if defined(DXX_BUILD_DESCENT_II)
  46. #include "laser.h"
  47. #include "multi.h"
  48. #include "vclip.h"
  49. #include "fireball.h"
  50.  
  51. //look at keyboard, mouse, joystick, CyberMan, whatever, and set
  52. //physics vars rotvel, velocity
  53.  
  54. fix Afterburner_charge=f1_0;
  55.  
  56. #define AFTERBURNER_USE_SECS    3                               //use up in 3 seconds
  57. #define DROP_DELTA_TIME                 (f1_0/15)       //drop 3 per second
  58. #endif
  59.  
  60. using std::min;
  61. using std::max;
  62.  
  63. namespace dsx {
  64. void read_flying_controls(object &obj)
  65. {
  66.         fix     forward_thrust_time;
  67.  
  68.         Assert(FrameTime > 0);          //Get MATT if hit this!
  69.  
  70. #if defined(DXX_BUILD_DESCENT_II)
  71.         if (obj.type != OBJ_PLAYER || get_player_id(obj) != Player_num)
  72.                 return; //references to player_ship require that this obj be the player
  73.  
  74.         const auto control_guided_missile = [&] {
  75.                 const auto &&gimobj = LevelUniqueObjectState.Guided_missile.get_player_active_guided_missile(LevelUniqueObjectState.get_objects().vmptr, Player_num);
  76.                 if (gimobj == nullptr)
  77.                         return false;
  78.                 auto &gmobj = *gimobj;
  79.                 const auto gmid = get_weapon_id(gmobj);
  80.                 const auto speed = Weapon_info[gmid].speed[GameUniqueState.Difficulty_level];
  81.                 vms_angvec rotangs;
  82.                 //this is a horrible hack.  guided missile stuff should not be
  83.                 //handled in the middle of a routine that is dealing with the player
  84.  
  85.                 vm_vec_zero(obj.mtype.phys_info.rotthrust);
  86.  
  87.                 const auto Seismic_tremor_magnitude = LevelUniqueSeismicState.Seismic_tremor_magnitude;
  88.                 rotangs.p = Controls.pitch_time / 2 + Seismic_tremor_magnitude/64;
  89.                 rotangs.b = Controls.bank_time / 2 + Seismic_tremor_magnitude/16;
  90.                 rotangs.h = Controls.heading_time / 2 + Seismic_tremor_magnitude/64;
  91.  
  92.                 const auto &&rotmat = vm_angles_2_matrix(rotangs);
  93.                 gmobj.orient = vm_matrix_x_matrix(gmobj.orient, rotmat);
  94.  
  95.                 vm_vec_copy_scale(gmobj.mtype.phys_info.velocity, gmobj.orient.fvec, speed);
  96.                 if (Game_mode & GM_MULTI)
  97.                         multi_send_guided_info(gmobj, 0);
  98.                 return true;
  99.         };
  100.         if (!control_guided_missile())
  101. #endif
  102.         {
  103.                 auto &rotthrust = obj.mtype.phys_info.rotthrust;
  104.                 rotthrust.x = Controls.pitch_time;
  105.                 rotthrust.y = Controls.heading_time;
  106.                 rotthrust.z = Controls.bank_time;
  107.         }
  108.  
  109.         forward_thrust_time = Controls.forward_thrust_time;
  110.  
  111. #if defined(DXX_BUILD_DESCENT_II)
  112.         auto &player_info = obj.ctype.player_info;
  113.         if (player_info.powerup_flags & PLAYER_FLAGS_AFTERBURNER)
  114.         {
  115.                 if (Controls.state.afterburner) {                       //player has key down
  116.                         {
  117.                                 fix afterburner_scale;
  118.                                 int old_count,new_count;
  119.        
  120.                                 //add in value from 0..1
  121.                                 afterburner_scale = f1_0 + min(f1_0/2,Afterburner_charge) * 2;
  122.        
  123.                                 forward_thrust_time = fixmul(FrameTime,afterburner_scale);      //based on full thrust
  124.        
  125.                                 old_count = (Afterburner_charge / (DROP_DELTA_TIME/AFTERBURNER_USE_SECS));
  126.  
  127.                                 Afterburner_charge -= FrameTime/AFTERBURNER_USE_SECS;
  128.  
  129.                                 if (Afterburner_charge < 0)
  130.                                         Afterburner_charge = 0;
  131.  
  132.                                 new_count = (Afterburner_charge / (DROP_DELTA_TIME/AFTERBURNER_USE_SECS));
  133.  
  134.                                 if (old_count != new_count)
  135.                                         Drop_afterburner_blob_flag = 1; //drop blob (after physics called)
  136.                         }
  137.                 }
  138.                 else {
  139.                         fix cur_energy,charge_up;
  140.        
  141.                         //charge up to full
  142.                         charge_up = min(FrameTime/8,f1_0 - Afterburner_charge); //recharge over 8 seconds
  143.        
  144.                         auto &energy = player_info.energy;
  145.                         cur_energy = max(energy - i2f(10), 0);  //don't drop below 10
  146.  
  147.                         //maybe limit charge up by energy
  148.                         charge_up = min(charge_up,cur_energy/10);
  149.        
  150.                         Afterburner_charge += charge_up;
  151.        
  152.                         energy -= charge_up * 100 / 10; //full charge uses 10% of energy
  153.                 }
  154.         }
  155. #endif
  156.  
  157.         // Set object's thrust vector for forward/backward
  158.         vm_vec_copy_scale(obj.mtype.phys_info.thrust, obj.orient.fvec, forward_thrust_time );
  159.        
  160.         // slide left/right
  161.         vm_vec_scale_add2(obj.mtype.phys_info.thrust, obj.orient.rvec, Controls.sideways_thrust_time );
  162.  
  163.         // slide up/down
  164.         vm_vec_scale_add2(obj.mtype.phys_info.thrust, obj.orient.uvec, Controls.vertical_thrust_time );
  165.  
  166.         if (obj.mtype.phys_info.flags & PF_WIGGLE)
  167.         {
  168.                 auto swiggle = fix_fastsin(static_cast<fix>(GameTime64));
  169.                 if (FrameTime < F1_0) // Only scale wiggle if getting at least 1 FPS, to avoid causing the opposite problem.
  170.                         swiggle = fixmul(swiggle*DESIGNATED_GAME_FPS, FrameTime); //make wiggle fps-independent (based on pre-scaled amount of wiggle at DESIGNATED_GAME_FPS)
  171.                 vm_vec_scale_add2(obj.mtype.phys_info.velocity, obj.orient.uvec, fixmul(swiggle, Player_ship->wiggle));
  172.         }
  173.  
  174.         // As of now, obj.mtype.phys_info.thrust & obj->mtype.phys_info.rotthrust are
  175.         // in units of time... In other words, if thrust==FrameTime, that
  176.         // means that the user was holding down the Max_thrust key for the
  177.         // whole frame.  So we just scale them up by the max, and divide by
  178.         // FrameTime to make them independant of framerate
  179.  
  180.         //      Prevent divide overflows on high frame rates.
  181.         //      In a signed divide, you get an overflow if num >= div<<15
  182.         {
  183.                 fix     ft = FrameTime;
  184.  
  185.                 //      Note, you must check for ft < F1_0/2, else you can get an overflow  on the << 15.
  186.                 if ((ft < F1_0/2) && (ft << 15 <= Player_ship->max_thrust)) {
  187.                         ft = (Player_ship->max_thrust >> 15) + 1;
  188.                 }
  189.  
  190.                 vm_vec_scale(obj.mtype.phys_info.thrust, fixdiv(Player_ship->max_thrust, ft));
  191.  
  192.                 if ((ft < F1_0/2) && (ft << 15 <= Player_ship->max_rotthrust)) {
  193.                         ft = (Player_ship->max_thrust >> 15) + 1;
  194.                 }
  195.  
  196.                 vm_vec_scale(obj.mtype.phys_info.rotthrust, fixdiv(Player_ship->max_rotthrust, ft));
  197.         }
  198.  
  199.         // moved here by WraithX
  200.         if (Player_dead_state != player_dead_state::no)
  201.         {
  202.                 //vm_vec_zero(&obj.mtype.phys_info.rotthrust); // let dead players rotate, changed by WraithX
  203.                 vm_vec_zero(obj.mtype.phys_info.thrust);  // don't let dead players move, changed by WraithX
  204.                 return;
  205.         }// end if
  206.  
  207. }
  208. }
  209.