Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
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>
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
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
85 }
86}
87
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
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));
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
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 {
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
200STATIC_INIT_LATE(viewloc_cursor)
201{
202 // fix the mouse position on init so it isn't in the corner
204}
205
206#endif
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition bits.qh:8
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
int spectatee_status
the -1 disables HUD panels before CSQC receives necessary data
Definition main.qh:197
#define PHYS_INPUT_BUTTON_CROUCH(s)
Definition player.qh:154
#define PHYS_CS(s)
Definition player.qh:258
const int FL_DUCKED
Definition constants.qh:89
float flags
const float MOVE_NOMONSTERS
const float VF_CL_VIEWANGLES
const float VF_ORIGIN
vector input_movevalues
vector trace_endpos
float input_buttons
const float VF_ANGLES
float player_localentnum
float entnum
float tag_networkviewloc
angles_y
Definition ent_cs.qc:119
entity CSQCModel_server2csqc(int i)
Definition cl_model.qc:314
#define LOG_TRACE(...)
Definition log.qh:76
const int VIEWLOC_CAM_SNAP_HARD
Definition viewloc.qh:9
const int VIEWLOC_FREEAIM
Definition viewloc.qh:5
const int VIEWLOC_CAM_TRACK
Definition viewloc.qh:7
const int VIEWLOC_FREEMOVE
Definition viewloc.qh:6
const int VIEWLOC_CAM_SNAP_CLOSE
Definition viewloc.qh:11
const int VIEWLOC_CAM_SNAP_UNLOCK
Definition viewloc.qh:10
entity viewloc
Definition viewloc.qh:13
const int VIEWLOC_CAM_NOANGLE
Definition viewloc.qh:8
vector vectoangles(vector v)
string vtos(vector v)
float min(float f,...)
vector normalize(vector v)
entity findfloat(entity start,.float field, float match)
float max(float f,...)
ERASEABLE vector vec_bounds_in(vector point, vector a, vector b)
Definition p2mathlib.qc:51
ERASEABLE vector aim_vec(vector org, vector targ)
Definition p2mathlib.qc:95
ERASEABLE vector angle_snap_vec(vector v, float increment)
Definition p2mathlib.qc:85
ERASEABLE vector vec_to_min(vector a, vector b)
Definition p2mathlib.qc:30
ERASEABLE vector vec_to_max(vector a, vector b)
Definition p2mathlib.qc:40
ERASEABLE float angle_snap_f(float f, float increment)
Definition p2mathlib.qc:73
#define NULL
Definition post.qh:14
vector
Definition self.qh:92
#define STATIC_INIT_LATE(func)
directly after STATIC_INIT
Definition static.qh:37
#define vec2(...)
Definition vector.qh:90
#define vec3(_x, _y, _z)
Definition vector.qh:95
vector freeze_ang
Definition view.qc:641
vector freeze_org
Definition view.qc:641
vector viewloc_mousepos
Definition view.qh:110
int autocvar_vid_conwidth
Definition view.qh:75
int autocvar_vid_conheight
Definition view.qh:74
void viewloc_SetViewLocation()
Definition viewloc.qc:97
vector CursorToWorldCoord(vector mpos)
Definition viewloc.qc:88
void viewloc_SetTags(entity this)
Definition viewloc.qc:74
vector old_camera_angle
Definition viewloc.qc:96
void viewloc_PlayerPhysics(entity this)
Definition viewloc.qc:13
int max_shot_distance
Definition weapon.qh:203