if(self.tag_entity && wasfreed(self.tag_entity))
self.tag_entity = world;
- if(self.viewloc && wasfreed(self.viewloc))
- self.viewloc = world;
-
- if(self.viewloc.entnum != self.tag_networkviewloc)
- self.viewloc = findfloat(world, entnum, self.tag_networkviewloc);
+ viewloc_SetTags();
if(self.tag_networkentity)
{
../common/net_notice.qc
../common/notifications.qc
../common/playerstats.qc
+../common/p2mathlib.qc
../common/test.qc
../common/urllib.qc
../common/util.qc
CSQCModel_Hook_PostUpdate(isnew, isplayer, islocalplayer);
#define CSQCMODEL_HOOK_PREDRAW \
CSQCModel_Hook_PreDraw(isplayer);
-#define CSQCPLAYER_HOOK_POSTCAMERASETUP
+#define CSQCPLAYER_HOOK_POSTCAMERASETUP \
+ CSQCPlayer_SetViewLocation();
// force updates of player entities that often even if unchanged
#define CSQCPLAYER_FORCE_UPDATES 0.25
--- /dev/null
+/*
+ Copyright (C) 2015 Micah Talkiewicz.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+vector vec_bias(vector v, float f){
+ vector c;
+ c_x = v_x + f;
+ c_y = v_y + f;
+ c_z = v_z + f;
+ return c;
+}
+vector vec_to_min (vector a, vector b) {
+ vector c;
+ c_x = min (a_x, b_x);
+ c_y = min (a_y, b_y);
+ c_z = min (a_z, b_z);
+ return c;
+}
+
+vector vec_to_max (vector a, vector b) {
+ vector c;
+ c_x = max (a_x, b_x);
+ c_y = max (a_y, b_y);
+ c_z = max (a_z, b_z);
+ return c;
+}
+
+// there may already be a function for bounding a vector in this manner, however my very quick search did not reveal one -- Player_2
+vector vec_bounds_in (vector point, vector a, vector b) {
+ vector c, d, e;
+
+ d = vec_to_min(a,b);
+ e = vec_to_max(a,b);
+
+ c = vec_to_max(point, d);
+ c = vec_to_min(c, e);
+
+ return c;
+
+}
+
+vector vec_bounds_out (vector point, vector a, vector b) {
+ vector c, d, e;
+
+ d = vec_to_max(a,b);
+ e = vec_to_min(a,b);
+
+ c = vec_to_max(point, d);
+ c = vec_to_min(c, e);
+
+ return c;
+
+}
+
+float angle_snap_f (float f, float increment){
+
+ float i;
+ for (i = 0; i <= 360; ){
+ if (f <= i - increment)
+ return i - increment;
+ i = i + increment;
+ }
+
+ return 0;
+}
+
+vector angle_snap_vec (vector v, float increment) {
+ vector c;
+ c_x = angle_snap_f (v_x, increment);
+ c_y = angle_snap_f (v_y, increment);
+ c_z = angle_snap_f (v_z, increment);
+ return c;
+}
+
+vector aim_vec (vector origin, vector target) {
+ vector v;
+ //we float around x and y, but rotate around z
+ v_x = target_x - origin_x;
+ v_y = target_y - origin_y;
+ v_z = origin_z - target_z;
+ //get the angles actual
+ return vectoangles(normalize(v));
+}
--- /dev/null
+/*
+ Copyright (C) 2015 Micah Talkiewicz.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+vector vec_bias(vector v, float f);
+
+
+vector vec_to_min (vector a, vector b);
+vector vec_to_max (vector a, vector b);
+
+// there may already be a function for bounding a vector in this manner, however my very quick search did not reveal one -- Player_2
+vector vec_bounds_in (vector point, vector a, vector b);
+vector vec_bounds_out (vector point, vector a, vector b);
+
+float angle_snap_f (float f, float increment);
+vector angle_snap_vec (vector v, float increment);
+
+vector aim_vec (vector origin, vector target);
--- /dev/null
+//#define COMPAT_VEX
+
+#ifndef COMPAT_VEX
+#include "util.qh"
+
+#if defined(CSQC)
+ #include "../dpdefs/csprogsdefs.qh"
+ #include "../client/defs.qh"
+ #include "constants.qh"
+#elif defined(MENUQC)
+#elif defined(SVQC)
+ #include "../server/defs.qh"
+#endif
+#endif
+
+#ifdef SVQC
+
+// client movement
+void viewloc_PlayerPhysics()
+{
+ if(self.viewloc)
+ {
+ self.disableclientprediction = 1;
+ vector oldmovement = self.movement;
+ self.movement_x = oldmovement_y;
+ self.movement_y = 0;
+
+ if(self.movement_x < 0)
+ self.movement_x = -self.movement_x;
+
+ vector level_start, level_end;
+ level_start = self.viewloc.enemy.origin;
+ level_end = self.viewloc.goalentity.origin;
+ vector forward, backward;
+ forward = vectoangles(normalize(level_end - level_start));
+ backward = vectoangles(normalize(level_start - level_end));
+
+ if(self.movement_x < 0) // left
+ self.angles = backward;
+ if(self.movement_x > 0) // right
+ self.angles = forward;
+
+ if(oldmovement_x > 0)
+ self.v_angle_x = self.angles_x = -50;
+
+ if(!self.BUTTON_CROUCH)
+ self.BUTTON_CROUCH = (oldmovement_x < 0);
+ }
+}
+
+#elif defined(CSQC)
+
+void viewloc_SetTags()
+{
+#ifdef COMPAT_VEX
+ entity self = CSQCModel_server2csqc(player_localentnum);
+#endif
+
+ if(self.viewloc && wasfreed(self.viewloc))
+ self.viewloc = world;
+
+ if(self.viewloc.entnum != self.tag_networkviewloc)
+ if(self.tag_networkviewloc == 0)
+ self.viewloc = world;
+ else
+ self.viewloc = findfloat(world, entnum, self.tag_networkviewloc);
+}
+
+#ifdef COMPAT_VEX
+entity view;
+#endif
+void viewloc_SetViewLocation()
+{
+#ifdef COMPAT_VEX
+ if(!view) { view = spawn(); }
+
+ view.viewloc = findfloat(world, entnum, getstati(STAT_VIEWLOC));
+ view.origin = pmove_org;
+#else
+ entity view = CSQCModel_server2csqc(player_localentnum);
+#endif
+ if(!view) { return; }
+ //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
+ if(view.viewloc && !wasfreed(view.viewloc) && view.viewloc.enemy && view.viewloc.goalentity)
+ {
+ vector position_a, position_b, camera_position, camera_angle, forward, backward;
+ //vector scratch;
+
+ position_a = view.viewloc.enemy.origin;
+ position_b = view.viewloc.goalentity.origin;
+
+#if 0
+ /*TODO: have the camera only move when a player moves too much from the center of the camera
+ * basically the player can move around in a "box" in the center of th screen with out changing the camera position or angles
+ */
+ if (cvar("cam_box")) {
+ camera_position = vec_bounds_in(view.origin, position_a, position_b);
+ }
+ else
+#endif
+ camera_position = vec_bounds_in(view.origin, position_a, position_b);
+
+
+ camera_angle = '0 0 0';
+
+ // a tracking camera follows the player when it leaves the world box
+ if (cvar("cam_track")) {
+ camera_angle = aim_vec (camera_position, view.origin);
+ }
+
+ // hard snap changes the angle as soon as it crosses over the nearest 90 degree mark
+ if (cvar("cam_snap_hard")){
+ camera_angle = angle_snap_vec(aim_vec(camera_position, view.origin), 90);
+ }
+
+ // tries to avoid snapping unless it *really* needs to
+ if (cvar("cam_snap_close")){
+
+ // like hard snap, but don't snap angles yet.
+ camera_angle = aim_vec(camera_position, view.origin);
+
+ /* if the difference between the old and new angle is 60 degrees or more, switch angles.
+ * NOTE: bug/feature: this will use non-snaped angles for one frame.
+ * doing this resualts in less code, faster code, and a smoother transisition between angles.
+ */
+ float camera_angle_diff = max(camera_angle_y, old_camera_angle_y) - min(camera_angle_y, old_camera_angle_y);
+
+ if ( camera_angle_diff >= 60)
+ old_camera_angle_y = angle_snap_f(camera_angle_y, 90);
+ else
+ camera_angle_y = old_camera_angle_y;
+ }
+
+ //unlocking this allows the camera to look up and down. this also allows a top-down view.
+ if (!cvar("cam_snap_unlock")) {
+ camera_angle_x = 0;
+ camera_angle_z = 0;
+ }
+
+#if 0
+ dprint(vtos(camera_position), "\n");
+ dprint(vtos(old_camera_angle), "\n");
+ dprint(vtos(camera_angle), "\n");
+#endif
+
+ freeze_org = getpropertyvec(VF_ORIGIN);
+ freeze_ang = getpropertyvec(VF_ANGLES);
+ setproperty(VF_ORIGIN, camera_position);
+ setproperty(VF_ANGLES, camera_angle);
+
+ forward = vectoangles(normalize(vec_to_min(position_b, position_a) - vec_to_max(position_b, position_a)));
+ backward = vectoangles(normalize(vec_to_max(position_b, position_a) - vec_to_min(position_b, position_a)));
+
+ if(input_movevalues_y < 0) // left
+ view.angles = backward;
+ if(input_movevalues_y > 0) // favour right
+ view.angles = forward;
+
+ setproperty(VF_CL_VIEWANGLES, view.angles);
+ }
+}
+
+#endif
--- /dev/null
+#ifndef VIEWLOC_H
+#define VIEWLOC_H
+
+.entity viewloc;
+
+#ifdef SVQC
+
+void viewloc_PlayerPhysics();
+
+#elif defined(CSQC)
+
+void viewloc_SetViewLocation();
+void viewloc_SetTags();
+
+#endif
+
+#endif
/*
* Copyright (c) 2011 Rudolf Polzer
+ * Copyright (c) 2015 Micah Talkiewicz
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
#include "../dpdefs/csprogsdefs.qh"
#include "../client/defs.qh"
#include "../common/constants.qh"
+ #include "../common/p2mathlib.qh"
#include "../common/stats.qh"
#include "../common/util.qh"
#include "interpolate.qh"
return (self == csqcplayer);
}
-vector addtovector(vector v, float f){
- vector c;
- c.x = v.x + f;
- c.y = v.y + f;
- c.z = v.z + f;
- return c;
-}
-vector vectomin (vector a, vector b) {
- vector c;
- c.x = min (a.x, b.x);
- c.y = min (a.y, b.y);
- c.z = min (a.z, b.z);
- return c;
-}
-
-vector vectomax (vector a, vector b) {
- vector c;
- c.x = max (a.x, b.x);
- c.y = max (a.y, b.y);
- c.z = max (a.z, b.z);
- return c;
-}
-
-// there may already be a function for bounding a vector in this manner, however my very quick search did not reveal one -- Player_2
-vector vecinbounds (vector point, vector a, vector b) {
- vector c, d, e;
-
- d = vectomin(a,b);
- e = vectomax(a,b);
-
- c = vectomax(point, d);
- c = vectomin(c, e);
-
- return c;
-
-}
-
-vector vecoutbounds (vector point, vector a, vector b) {
- vector c, d, e;
-
- d = vectomax(a,b);
- e = vectomin(a,b);
-
- c = vectomax(point, d);
- c = vectomin(c, e);
-
- return c;
-
-}
-
-//does QC have a static type? I'll just use a global I guess...
-vector old_camera_position = '0 0 0';
void CSQCPlayer_SetViewLocation()
{
- if(self.viewloc && !wasfreed(self.viewloc) && self.viewloc.enemy && self.viewloc.goalentity)
- {
- entity view = CSQCModel_server2csqc(player_localentnum);
- if(!view) { return; }
-
- vector position_a, position_b, camera_position, camera_angle, forward, backward;
-
- position_a = self.viewloc.enemy.origin;
- position_b = self.viewloc.goalentity.origin;
-
- if (cvar("cam_box")) {
- camera_position = vecinbounds(view.origin, position_a, position_b);
- }
- else
- camera_position = vecinbounds(view.origin, position_a, position_b);
-
-
- //for a world box set camera_angle to no angle
- camera_angle = '0 0 0';
-
- // a tracking camera follows the player when it leaves the world box
- if (cvar("cam_track")) {
- //we float around x and y, but rotate around z
- camera_angle.x = view.origin.x - camera_position.x;
- camera_angle.y = view.origin.y - camera_position.y;
- camera_angle.z = camera_position.z - view.origin.z;
- //get the angles actual
- camera_angle = vectoangles(normalize(camera_angle));
- }
-
- dprint(vtos(camera_position), "\n");
- dprint(vtos(camera_angle), "\n");
-
- freeze_org = getpropertyvec(VF_ORIGIN);
- freeze_ang = getpropertyvec(VF_ANGLES);
- setproperty(VF_ORIGIN, camera_position);
- setproperty(VF_ANGLES, camera_angle);
-
- forward = vectoangles(normalize(vectomin(position_b, position_a) - vectomax(position_b, position_a)));
- backward = vectoangles(normalize(vectomax(position_b, position_a) - vectomin(position_b, position_a)));
-
- if(input_movevalues_y < 0) // left
- view.angles = backward;
- if(input_movevalues_y > 0) // favour right
- view.angles = forward;
-
- if(input_buttons & 256) // forward
- view.v_angle_x = view.angles_x = -50;
-
- setproperty(VF_CL_VIEWANGLES, view.angles);
- }
+ viewloc_SetViewLocation();
}
void CSQCPlayer_SetCamera()
refdefflags |= REFDEFFLAG_INTERMISSION;
V_CalcRefdef(view, refdefflags);
-
- CSQCPlayer_SetViewLocation();
}
else
{
if(time < self.ladder_time)
self.disableclientprediction = 1;
- if(self.viewloc)
- {
- self.disableclientprediction = 1;
- vector oldmovement = self.movement;
- self.movement_x = oldmovement_y;
- self.movement_y = 0;
-
- if(self.movement_x < 0)
- self.movement_x = -self.movement_x;
-
- vector level_start, level_end;
- level_start = self.viewloc.enemy.origin;
- level_end = self.viewloc.goalentity.origin;
- vector forward, backward;
- forward = vectoangles(normalize(level_end - level_start));
- backward = vectoangles(normalize(level_start - level_end));
-
- if(self.movement_x < 0) // left
- self.angles = backward;
- if(self.movement_x > 0) // right
- self.angles = forward;
-
- if(oldmovement_x > 0)
- self.v_angle_x = self.angles_x = -50;
-
- if(!self.BUTTON_CROUCH)
- self.BUTTON_CROUCH = (oldmovement_x < 0);
- }
+ viewloc_PlayerPhysics();
if(self.frozen)
{
../common/net_notice.qc
../common/notifications.qc
../common/playerstats.qc
+../common/p2mathlib.qc
../common/test.qc
../common/turrets/targettrigger.qc
../common/turrets/sv_turrets.qc
+#ifndef COMPAT_VEX
#if defined(CSQC)
#elif defined(MENUQC)
#elif defined(SVQC)
#include "defs.qh"
#include "t_viewloc.qh"
#endif
+#endif
#ifdef SVQC