5 #include "../client/defs.qh"
6 #include "constants.qh"
9 #include "../server/defs.qh"
13 void viewloc_PlayerPhysics(entity this)
17 if(this.viewloc.goalentity == this.viewloc.enemy)
18 return; // we can't side-scroll in this case
20 vector old_movement = PHYS_CS(this).movement;
21 PHYS_CS(this).movement_x = old_movement_y;
22 if((this.viewloc.spawnflags & VIEWLOC_FREEMOVE) && !(time < this.ladder_time))
23 PHYS_CS(this).movement_y = old_movement_x;
25 PHYS_CS(this).movement_y = 0;
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));
33 if((this.viewloc.spawnflags & VIEWLOC_FREEMOVE) && this.angles_y < 0 && !(time < this.ladder_time))
34 PHYS_CS(this).movement_y = -PHYS_CS(this).movement_y;
36 if(this.viewloc.spawnflags & VIEWLOC_FREEAIM)
39 PHYS_CS(this).movement_x = -PHYS_CS(this).movement_x;
43 if(PHYS_CS(this).movement_x < 0)
44 PHYS_CS(this).movement_x = -PHYS_CS(this).movement_x;
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;
52 //if(!PHYS_INPUT_BUTTON_CROUCH(this) && !IS_DUCKED(this))
53 if(!(this.viewloc.spawnflags & VIEWLOC_FREEMOVE))
56 //PHYS_INPUT_BUTTON_CROUCH(this) = (old_movement_x < 0);
57 if (old_movement.x < 0)
58 PHYS_INPUT_BUTTON_CROUCH(this) = true;
60 if (old_movement.x < 0)
62 input_buttons |= BIT(4);
63 this.flags |= FL_DUCKED;
65 //else { input_buttons &= ~16; this.flags &= ~FL_DUCKED; }
74 void viewloc_SetTags(entity this)
76 if(this.viewloc && wasfreed(this.viewloc))
79 if(this.viewloc.entnum != this.tag_networkviewloc)
81 if(this.tag_networkviewloc == 0)
84 this.viewloc = findfloat(NULL, entnum, this.tag_networkviewloc);
88 vector CursorToWorldCoord(vector mpos)
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);
96 vector old_camera_angle = '0 0 0';
97 bool autocvar_cam_snap_close;
98 bool autocvar_cam_track;
99 bool autocvar_cam_snap_hard;
100 bool autocvar_cam_snap_unlock;
101 bool autocvar_cam_useangle = true;
102 void viewloc_SetViewLocation()
104 entity view = CSQCModel_server2csqc(player_localentnum - 1);
106 //NOTE: the "cam_" cvars sould probably be changed out with a spawnflag or an entity key. I have it like this for my testing -- Player_2
107 if(view.viewloc && !wasfreed(view.viewloc) && view.viewloc.enemy && view.viewloc.goalentity)
109 bool have_sidescroll = (view.viewloc.enemy != view.viewloc.goalentity);
110 vector position_a = view.viewloc.enemy.origin;
111 vector position_b = view.viewloc.goalentity.origin;
112 vector camera_angle = '0 0 0';
113 vector camera_position;
115 /*TODO: have the camera only move when a player moves too much from the center of the camera
116 * basically the player would move around in a small "box" in the center of the screen with out changing the camera position or angles */
117 camera_position = vec_bounds_in(view.origin, position_a, position_b);
119 // use camera's angle when possible
120 if (autocvar_cam_useangle) {
121 camera_angle = view.viewloc.enemy.movedir;
124 // a tracking camera follows the player when it leaves the world box
125 if (autocvar_cam_track || !have_sidescroll) {
126 camera_angle = aim_vec (camera_position, view.origin);
129 // hard snap changes the angle as soon as it crosses over the nearest 90 degree mark
130 if (autocvar_cam_snap_hard) {
131 camera_angle = angle_snap_vec(aim_vec(camera_position, view.origin), 90);
134 // tries to avoid snapping unless it *really* needs to
135 if (autocvar_cam_snap_close) {
136 // like hard snap, but don't snap angles yet.
137 camera_angle = aim_vec(camera_position, view.origin);
139 /* if the difference between the old and new angle is 60 degrees or more, switch angles.
140 * NOTE: bug/feature: this will use non-snaped angles for one frame.
141 * doing this results in less code, faster code, and a smoother transisition between angles.
143 float camera_angle_diff = max(camera_angle.y, old_camera_angle.y) - min(camera_angle.y, old_camera_angle.y);
145 if (60 <= camera_angle_diff) { // use new angles
146 old_camera_angle.y = angle_snap_f(camera_angle.y, 90);
147 } else { // use old angles
148 camera_angle.y = old_camera_angle.y;
152 //unlocking this allows the camera to look up and down. this also allows a top-down view.
153 if (!autocvar_cam_snap_unlock) {
159 LOG_TRACE(vtos(camera_position));
160 LOG_TRACE(vtos(old_camera_angle));
161 LOG_TRACE(vtos(camera_angle));
164 freeze_org = getpropertyvec(VF_ORIGIN);
165 freeze_ang = getpropertyvec(VF_ANGLES);
166 setproperty(VF_ORIGIN, camera_position);
167 setproperty(VF_ANGLES, camera_angle);
170 return; // if spectating, don't replace angles or inputs!
172 if (have_sidescroll) {
173 vector view_angle = view.angles;
174 if (!(view.viewloc.spawnflags & VIEWLOC_FREEAIM)) {
175 vector avatar_facing_dir;
176 // get the player's forward-facing direction, based on positions a and b
177 if (0 == input_movevalues.y) {
178 avatar_facing_dir = view_angle; // default to the previous values
179 } else if (0 > input_movevalues.y) { // left is forward
180 avatar_facing_dir = vectoangles(normalize(vec_to_max(position_b, position_a) - vec_to_min(position_b, position_a)));
181 } else { // right is forward
182 avatar_facing_dir = vectoangles(normalize(vec_to_min(position_b, position_a) - vec_to_max(position_b, position_a)));
184 view_angle.y = avatar_facing_dir.y; // snap avatar to look on along the correct axis
186 // if (0 == input_movevalues.x) look straight ahead
187 if (!(view.viewloc.spawnflags & VIEWLOC_FREEMOVE)) {
188 if (0 > input_movevalues.x) { // look up
190 } else if (0 < input_movevalues.x) { // look down
195 vector mpos = CursorToWorldCoord(viewloc_mousepos);
196 mpos.x = view.origin.x; // replace the cursor's x position with the player's
197 view_angle = aim_vec(view.origin + view.view_ofs, mpos); // get new angles
199 view.angles_y = view_angle.y;
200 setproperty(VF_CL_VIEWANGLES, view_angle);
205 STATIC_INIT_LATE(viewloc_cursor)
207 // fix the mouse position on init so it isn't in the corner
208 viewloc_mousepos = '0.5 0 0' * autocvar_vid_conwidth + '0 0.5 0' * autocvar_vid_conheight;