Xonotic
viewloc.qc
Go to the documentation of this file.
1 #include "viewloc.qh"
2 
3 #if defined(CSQC)
4  #include <common/util.qh>
5  #include <common/constants.qh>
6 #elif defined(MENUQC)
7 #elif defined(SVQC)
8  #include <common/stats.qh>
9  #include <common/weapons/_all.qh>
10 #endif
11 
12 // client movement
14 {
15  if(this.viewloc)
16  {
17  if(this.viewloc.goalentity == this.viewloc.enemy)
18  return; // we can't side-scroll in this case
19 
20  vector old_movement = PHYS_CS(this).movement;
21  PHYS_CS(this).movement_x = old_movement_y;
22  if((this.viewloc.spawnflags & VIEWLOC_FREEMOVE) && !this.ladder_entity)
23  PHYS_CS(this).movement_y = old_movement_x;
24  else
25  PHYS_CS(this).movement_y = 0;
26 
27  vector level_start, level_end;
28  level_start = this.viewloc.enemy.origin;
29  level_end = this.viewloc.goalentity.origin;
30  vector forward = vectoangles(normalize(level_end - level_start));
31  vector backward = vectoangles(normalize(level_start - level_end));
32 
33  if((this.viewloc.spawnflags & VIEWLOC_FREEMOVE) && this.angles_y < 0 && !this.ladder_entity)
34  PHYS_CS(this).movement_y = -PHYS_CS(this).movement_y;
35 
36  if(this.viewloc.spawnflags & VIEWLOC_FREEAIM)
37  {
38  if(this.angles_y > 0)
39  PHYS_CS(this).movement_x = -PHYS_CS(this).movement_x;
40  }
41  else
42  {
43  if(PHYS_CS(this).movement_x < 0)
44  PHYS_CS(this).movement_x = -PHYS_CS(this).movement_x;
45 
46  if(PHYS_CS(this).movement_x < 0) // left
47  this.angles_y = backward.y;
48  if(PHYS_CS(this).movement_x > 0) // right
49  this.angles_y = forward.y;
50  }
51  #if 0
52  //if(!PHYS_INPUT_BUTTON_CROUCH(this) && !IS_DUCKED(this))
53  if(!(this.viewloc.spawnflags & VIEWLOC_FREEMOVE))
54  {
55 #ifdef SVQC
56  //PHYS_INPUT_BUTTON_CROUCH(this) = (old_movement_x < 0);
57  if (old_movement.x < 0)
58  PHYS_INPUT_BUTTON_CROUCH(this) = true;
59 #elif defined(CSQC)
60  if (old_movement.x < 0)
61  {
62  input_buttons |= BIT(4);
63  this.flags |= FL_DUCKED;
64  }
65  //else { input_buttons &= ~16; this.flags &= ~FL_DUCKED; }
66 #endif
67  }
68  #endif
69  }
70 }
71 
72 #ifdef CSQC
73 
74 void viewloc_SetTags(entity this)
75 {
76  if(this.viewloc && wasfreed(this.viewloc))
77  this.viewloc = NULL;
78 
79  if(this.viewloc.entnum != this.tag_networkviewloc)
80  {
81  if(this.tag_networkviewloc == 0)
82  this.viewloc = NULL;
83  else
84  this.viewloc = findfloat(NULL, entnum, this.tag_networkviewloc);
85  }
86 }
87 
88 vector CursorToWorldCoord(vector mpos)
89 {
90  vector wnear = cs_unproject(vec2(mpos)); // determine the world coordinate for the mouse cursor upon the near clip plane
91  vector wfar = cs_unproject(vec3(mpos.x, mpos.y, max_shot_distance)); // determine the world coordinate for the mouse cursor upon the far clip plane, with an outrageously large value as a workaround for dp.
92  traceline(wnear, wfar, MOVE_NOMONSTERS, NULL);
93  return trace_endpos;
94 }
95 
96 vector old_camera_angle = '0 0 0';
97 void viewloc_SetViewLocation()
98 {
100  if (!view) return;
101  entity viewloc_ent = view.viewloc;
102  if(viewloc_ent && !wasfreed(viewloc_ent) && viewloc_ent.enemy && viewloc_ent.goalentity)
103  {
104  bool have_sidescroll = (viewloc_ent.enemy != viewloc_ent.goalentity);
105  vector position_a = viewloc_ent.enemy.origin;
106  vector position_b = viewloc_ent.goalentity.origin;
107  vector camera_angle = '0 0 0';
108  vector camera_position;
109 
110  /*TODO: have the camera only move when a player moves too much from the center of the camera
111  * basically the player would move around in a small "box" in the center of the screen with out changing the camera position or angles */
112  camera_position = vec_bounds_in(view.origin, position_a, position_b);
113 
114  // use camera's angle when possible
115  if (!(viewloc_ent.spawnflags & VIEWLOC_CAM_NOANGLE)) {
116  camera_angle = viewloc_ent.enemy.movedir;
117  }
118 
119  // a tracking camera follows the player when it leaves the world box
120  if ((viewloc_ent.spawnflags & VIEWLOC_CAM_TRACK) || !have_sidescroll) {
121  camera_angle = aim_vec (camera_position, view.origin);
122  }
123 
124  // hard snap changes the angle as soon as it crosses over the nearest 90 degree mark
125  if (viewloc_ent.spawnflags & VIEWLOC_CAM_SNAP_HARD) {
126  camera_angle = angle_snap_vec(aim_vec(camera_position, view.origin), 90);
127  }
128 
129  // tries to avoid snapping unless it *really* needs to
130  if (viewloc_ent.spawnflags & VIEWLOC_CAM_SNAP_CLOSE) {
131  // like hard snap, but don't snap angles yet.
132  camera_angle = aim_vec(camera_position, view.origin);
133 
134  /* if the difference between the old and new angle is 60 degrees or more, switch angles.
135  * NOTE: bug/feature: this will use non-snaped angles for one frame.
136  * doing this results in less code, faster code, and a smoother transisition between angles.
137  */
138  float camera_angle_diff = max(camera_angle.y, old_camera_angle.y) - min(camera_angle.y, old_camera_angle.y);
139 
140  if (60 <= camera_angle_diff) { // use new angles
141  old_camera_angle.y = angle_snap_f(camera_angle.y, 90);
142  } else { // use old angles
143  camera_angle.y = old_camera_angle.y;
144  }
145  }
146 
147  //unlocking this allows the camera to look up and down. this also allows a top-down view.
148  if (!(viewloc_ent.spawnflags & VIEWLOC_CAM_SNAP_UNLOCK)) {
149  camera_angle.x = 0;
150  camera_angle.z = 0;
151  }
152 
153 #if 0
154  LOG_TRACE(vtos(camera_position));
155  LOG_TRACE(vtos(old_camera_angle));
156  LOG_TRACE(vtos(camera_angle));
157 #endif
158 
159  freeze_org = getpropertyvec(VF_ORIGIN);
160  freeze_ang = getpropertyvec(VF_ANGLES);
161  setproperty(VF_ORIGIN, camera_position);
162  setproperty(VF_ANGLES, camera_angle);
163 
164  if(spectatee_status)
165  return; // if spectating, don't replace angles or inputs!
166 
167  if (have_sidescroll) {
168  vector view_angle = view.angles;
169  if (!(viewloc_ent.spawnflags & VIEWLOC_FREEAIM)) {
170  vector avatar_facing_dir;
171  // get the player's forward-facing direction, based on positions a and b
172  if (0 == input_movevalues.y) {
173  avatar_facing_dir = view_angle; // default to the previous values
174  } else if (0 > input_movevalues.y) { // left is forward
175  avatar_facing_dir = vectoangles(normalize(vec_to_max(position_b, position_a) - vec_to_min(position_b, position_a)));
176  } else { // right is forward
177  avatar_facing_dir = vectoangles(normalize(vec_to_min(position_b, position_a) - vec_to_max(position_b, position_a)));
178  }
179  view_angle.y = avatar_facing_dir.y; // snap avatar to look on along the correct axis
180 
181  // if (0 == input_movevalues.x) look straight ahead
182  if (!(viewloc_ent.spawnflags & VIEWLOC_FREEMOVE)) {
183  if (0 > input_movevalues.x) { // look up
184  view_angle.x = 50;
185  } else if (0 < input_movevalues.x) { // look down
186  view_angle.x = -50;
187  }
188  }
189  } else {
190  vector mpos = CursorToWorldCoord(viewloc_mousepos);
191  mpos.x = view.origin.x; // replace the cursor's x position with the player's
192  view_angle = aim_vec(view.origin + view.view_ofs, mpos); // get new angles
193  }
194  view.angles_y = view_angle.y;
195  setproperty(VF_CL_VIEWANGLES, view_angle);
196  }
197  }
198 }
199 
200 STATIC_INIT_LATE(viewloc_cursor)
201 {
202  // fix the mouse position on init so it isn't in the corner
204 }
205 
206 #endif
vector input_movevalues
Definition: csprogsdefs.qc:61
const int VIEWLOC_CAM_TRACK
Definition: viewloc.qh:7
#define PHYS_INPUT_BUTTON_CROUCH(s)
Definition: player.qh:150
entity CSQCModel_server2csqc(int i)
Definition: cl_model.qc:314
const float VF_CL_VIEWANGLES
Definition: csprogsdefs.qc:194
entity() spawn
#define vec3(_x, _y, _z)
Definition: vector.qh:95
float input_buttons
Definition: csprogsdefs.qc:62
vector freeze_ang
Definition: view.qc:574
const int VIEWLOC_FREEAIM
Definition: viewloc.qh:5
ERASEABLE vector aim_vec(vector org, vector targ)
Definition: p2mathlib.qc:95
const int VIEWLOC_CAM_SNAP_CLOSE
Definition: viewloc.qh:11
void viewloc_PlayerPhysics(entity this)
Definition: viewloc.qc:13
ERASEABLE vector vec_to_max(vector a, vector b)
Definition: p2mathlib.qc:40
vector freeze_org
Definition: view.qc:574
const int VIEWLOC_CAM_NOANGLE
Definition: viewloc.qh:8
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition: bits.qh:8
vector viewloc_mousepos
Definition: view.qh:106
const float MOVE_NOMONSTERS
Definition: csprogsdefs.qc:253
ERASEABLE vector vec_to_min(vector a, vector b)
Definition: p2mathlib.qc:30
#define NULL
Definition: post.qh:17
vector trace_endpos
Definition: csprogsdefs.qc:37
#define STATIC_INIT_LATE(func)
directly after STATIC_INIT
Definition: static.qh:37
float player_localentnum
Definition: csprogsdefs.qc:19
vector(float skel, float bonenum) _skel_get_boneabs_hidden
const int VIEWLOC_CAM_SNAP_UNLOCK
Definition: viewloc.qh:10
entity viewloc
Definition: viewloc.qh:13
float spectatee_status
Definition: main.qh:166
const float VF_ANGLES
Definition: csprogsdefs.qc:186
float flags
Definition: csprogsdefs.qc:129
#define LOG_TRACE(...)
Definition: log.qh:81
ERASEABLE vector angle_snap_vec(vector v, float increment)
Definition: p2mathlib.qc:85
const int VIEWLOC_FREEMOVE
Definition: viewloc.qh:6
int autocvar_vid_conwidth
Definition: view.qh:72
ERASEABLE float angle_snap_f(float f, float increment)
Definition: p2mathlib.qc:73
#define vec2(...)
Definition: vector.qh:90
const int VIEWLOC_CAM_SNAP_HARD
Definition: viewloc.qh:9
int autocvar_vid_conheight
Definition: view.qh:71
ERASEABLE vector vec_bounds_in(vector point, vector a, vector b)
Definition: p2mathlib.qc:51
float entnum
Definition: csprogsdefs.qc:94
const float VF_ORIGIN
Definition: csprogsdefs.qc:182