tref = EFFECT_TR_BLOOD.m_id;
if(this.csqcmodel_modelflags & MF_ROTATE)
{
+ // This will be hard to replace with MAKE_VECTORS because it's called as part of the predraw function
+ // as documented in csprogs.h in the engine. The globals can then be read in many places in the engine.
+ // However MR_ROTATE is currently only used in one place - might be possible to get rid of it entirely.
this.renderflags |= RF_USEAXIS;
- MAKEVECTORS(makevectors, this.angles + '0 100 0' * fmod(time, 3.6), v_forward, v_right, v_up);
+ makevectors(this.angles + '0 100 0' * fmod(time, 3.6));
}
if(this.csqcmodel_modelflags & MF_TRACER)
tref = EFFECT_TR_WIZSPIKE.m_id;
coord = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(coord3d));
- vector forward = '0 0 0', right = '0 0 0', up = '0 0 0';
- MAKEVECTORS(makevectors, pangles - '0 1 0' * teamradar_angle, forward, right, up);
+ MAKE_VECTORS_NEW(pangles - '0 1 0' * teamradar_angle, forward, right, up);
if(v_flipped)
{
forward.x = -forward.x;
vel = view.velocity;
else
{
- vector forward = '0 0 0', right = '0 0 0', up = '0 0 0';
- MAKEVECTORS(makevectors, view_angles, forward, right, up);
+ MAKE_VECTORS_NEW(view_angles, forward, right, up);
vel.x = view.velocity * forward;
vel.y = view.velocity * right * -1;
vel.z = view.velocity * up;
if (autocvar_cl_followmodel_velocity_absolute)
{
vector fixed_gunorg;
- vector forward = '0 0 0', right = '0 0 0', up = '0 0 0';
- MAKEVECTORS(makevectors, view_angles, forward, right, up);
+ MAKE_VECTORS_NEW(view_angles, forward, right, up);
fixed_gunorg.x = gunorg * forward;
fixed_gunorg.y = gunorg * right * -1;
fixed_gunorg.z = gunorg * up;
vector pos = view_origin;
vector dir = view_forward;
- makevectors(((autocvar_chase_active) ? warpzone_save_view_angles : view_angles));
- pos += v_right * -wepent.movedir.y
- + v_up * wepent.movedir.z;
+ MAKE_VECTORS_NEW(autocvar_chase_active ? warpzone_save_view_angles : view_angles, forward, right, up);
+ pos += right * -wepent.movedir.y
+ + up * wepent.movedir.z;
if (wepent.angles_held_status)
{
- makevectors(wepent.angles_held);
- dir = v_forward;
+ MAKE_VECTORS(wepent.angles_held, forward, right, up);
+ dir = forward;
}
wepent.polyline[0] = pos;
{
vector ang = vectoangles2(trace_plane_normal, dir);
ang.x = -ang.x;
- makevectors(ang);
- if (!CheckWireframeBox(this, pos - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward))
+ MAKE_VECTORS(ang, forward, right, up);
+ if (!CheckWireframeBox(this, pos - 48 * right - 48 * up + 16 * forward, 96 * right, 96 * up, 96 * forward))
{
n = max(2, idx);
break;
curspeed = 0;
else
{
- makevectors(view_angles);
+ MAKE_VECTORS_NEW(view_angles, forward, right, up);
v = pmove_vel;
if(csqcplayer)
v = csqcplayer.velocity;
switch(autocvar_cl_velocityzoom_type)
{
- case 3: curspeed = max(0, v_forward * v); break;
- case 2: curspeed = (v_forward * v); break;
+ case 3: curspeed = max(0, forward * v); break;
+ case 2: curspeed = (forward * v); break;
case 1: default: curspeed = vlen(v); break;
}
}
else if(eventchase_current_distance != chase_distance)
eventchase_current_distance = chase_distance;
- makevectors(view_angles);
+ MAKE_VECTORS_NEW(view_angles, forward, right, up);
- vector eventchase_target_origin = (current_view_origin - (v_forward * eventchase_current_distance));
+ vector eventchase_target_origin = (current_view_origin - (forward * eventchase_current_distance));
WarpZone_TraceBox(current_view_origin, autocvar_cl_eventchase_mins, autocvar_cl_eventchase_maxs, eventchase_target_origin, MOVE_WORLDONLY, this);
// If the boxtrace fails, revert back to line tracing.
if(!local_player.viewloc)
if(trace_startsolid)
{
- eventchase_target_origin = (current_view_origin - (v_forward * eventchase_current_distance));
+ eventchase_target_origin = (current_view_origin - (forward * eventchase_current_distance));
WarpZone_TraceLine(current_view_origin, eventchase_target_origin, MOVE_WORLDONLY, this);
- setproperty(VF_ORIGIN, (trace_endpos - (v_forward * autocvar_cl_eventchase_mins.z)));
+ setproperty(VF_ORIGIN, (trace_endpos - (forward * autocvar_cl_eventchase_mins.z)));
}
else { setproperty(VF_ORIGIN, trace_endpos); }
// Render the Scene
view_origin = getpropertyvec(VF_ORIGIN);
view_angles = getpropertyvec(VF_ANGLES);
- MAKEVECTORS(makevectors, view_angles, view_forward, view_right, view_up);
+ MAKE_VECTORS(view_angles, view_forward, view_right, view_up);
#ifdef BLURTEST
if(time > blurtest_time0 && time < blurtest_time1)
setproperty(VF_ORIGIN, '0 0 0');
setproperty(VF_ANGLES, '0 0 0');
setproperty(VF_PERSPECTIVE, 1);
- makevectors('0 0 0');
+ MAKE_VECTORS_NEW('0 0 0', forward, right, up);
vector v1, v2;
cvar_set("vid_conwidth", "800");
cvar_set("vid_conheight", "600");
- v1 = cs_project(v_forward);
+ v1 = cs_project(forward);
cvar_set("vid_conwidth", "640");
cvar_set("vid_conheight", "480");
- v2 = cs_project(v_forward);
+ v2 = cs_project(forward);
if(v1 == v2)
cs_project_is_b0rked = 1;
else
it.solid = SOLID_BBOX;
});
vector forward = '0 0 0'; vector right = '0 0 0'; vector up = '0 0 0';
- MAKEVECTORS(makevectors, it.v_angle, forward, right, up);
+ MAKE_VECTORS(it.v_angle, forward, right, up);
vector pos = it.origin + it.view_ofs;
traceline(pos, pos + forward * max_shot_distance, MOVE_NORMAL, it);
FOREACH_ENTITY(true, {
if (this.m_screen_coords) {
screen_pos = this.origin + since_hit * autocvar_cl_damagetext_2d_velocity;
} else {
- makevectors(view_angles);
+ MAKE_VECTORS_NEW(view_angles, forward, right, up);
vector world_offset = since_hit * autocvar_cl_damagetext_velocity_world + autocvar_cl_damagetext_offset_world;
- vector world_pos = this.origin + world_offset.x * v_forward + world_offset.y * v_right + world_offset.z * v_up;
+ vector world_pos = this.origin + world_offset.x * forward + world_offset.y * right + world_offset.z * up;
screen_pos = project_3d_to_2d(world_pos) + since_hit * autocvar_cl_damagetext_velocity_screen + autocvar_cl_damagetext_offset_screen;
}
screen_pos.y += size / 2;
return true;
// returns true if the player is close to a wall
-bool is_close_to_wall(entity this, float threshold)
+bool is_close_to_wall(entity this, float threshold, vector forward, vector right)
{
- X(v_right);
- X(-v_right);
- X(v_forward);
- X(-v_forward);
+ X(right);
+ X(-right);
+ X(forward);
+ X(-forward);
return false;
}
-bool is_close_to_ground(entity this, float threshold)
+bool is_close_to_ground(entity this, float threshold, vector up)
{
if (IS_ONGROUND(this)) return true;
- X(-v_up); // necessary for dodging down a slope using doubletap (using `+dodge` works anyway)
+ X(-up); // necessary for dodging down a slope using doubletap (using `+dodge` works anyway)
return false;
}
if ((time - this.last_dodging_time) < PHYS_DODGING_DELAY)
return false;
- makevectors(this.angles);
+ MAKE_VECTORS_NEW(this.angles, forward, right, up);
- bool can_dodge = (is_close_to_ground(this, PHYS_DODGING_HEIGHT_THRESHOLD) && (PHYS_DODGING_MAXSPEED == 0 || vdist(this.velocity, <, PHYS_DODGING_MAXSPEED)));
- bool can_wall_dodge = (PHYS_DODGING_WALL && is_close_to_wall(this, PHYS_DODGING_DISTANCE_THRESHOLD));
+ bool can_dodge = (is_close_to_ground(this, PHYS_DODGING_HEIGHT_THRESHOLD, up) && (PHYS_DODGING_MAXSPEED == 0 || vdist(this.velocity, <, PHYS_DODGING_MAXSPEED)));
+ bool can_wall_dodge = (PHYS_DODGING_WALL && is_close_to_wall(this, PHYS_DODGING_DISTANCE_THRESHOLD, forward, right));
bool can_air_dodge = (PHYS_DODGING_AIR && (PHYS_DODGING_AIR_MAXSPEED == 0 || vdist(this.velocity, <, PHYS_DODGING_AIR_MAXSPEED)));
if (!can_dodge && !can_wall_dodge && !can_air_dodge) return false;
return;
}
- // make sure v_up, v_right and v_forward are sane
+ NEW_VECS(forward, right, up);
if(PHYS_DODGING_AIR)
- makevectors(this.v_angle);
+ MAKE_VECTORS(this.v_angle, forward, right, up);
else
- makevectors(this.angles);
+ MAKE_VECTORS(this.angles, forward, right, up);
// fraction of the force to apply each frame
// if we have e.g. 0.5 sec ramptime and a frametime of 0.25, then the ramp code
float velocity_increase = min(common_factor * this.dodging_force_total, this.dodging_force_remaining);
this.dodging_force_remaining -= velocity_increase;
- this.velocity += this.dodging_direction.x * velocity_increase * v_forward
- + this.dodging_direction.y * velocity_increase * v_right;
+ this.velocity += this.dodging_direction.x * velocity_increase * forward
+ + this.dodging_direction.y * velocity_increase * right;
// the up part of the dodge is a single shot action
if (this.dodging_single_action == 1)
{
UNSET_ONGROUND(this);
- this.velocity += PHYS_DODGING_UP_SPEED * v_up;
+ this.velocity += PHYS_DODGING_UP_SPEED * up;
#ifdef SVQC
if (autocvar_sv_dodging_sound)
vector horiz_vel = vec2(it.velocity);
// when walking slowly sideways, we assume the player wants a clear shot ahead - spawn behind him according to where he's looking
// when running fast, spawn behind him according to his direction of movement to prevent colliding with the newly spawned player
+ NEW_VECS(forward, right, up);
if (vdist(horiz_vel, >, autocvar_sv_maxspeed + 50))
- fixedmakevectors(vectoangles(horiz_vel));
+ {
+ FIXED_MAKE_VECTORS(vectoangles(horiz_vel), forward, right, up);
+ }
else
- fixedmakevectors(it.angles); // .angles is the angle of the model - usually/always 0 pitch
+ {
+ FIXED_MAKE_VECTORS(it.angles, forward, right, up);
+ }
// test different spots close to mate - trace upwards so it works on uneven surfaces
// don't spawn in front of player or directly behind to avoid players shooting each other
switch(i)
{
case 0:
- tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin - v_forward * 64 + v_right * 128 + v_up * 64, MOVE_NOMONSTERS, it);
+ tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin - forward * 64 + right * 128 + up * 64, MOVE_NOMONSTERS, it);
break;
case 1:
- tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin - v_forward * 64 - v_right * 128 + v_up * 64, MOVE_NOMONSTERS, it);
+ tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin - forward * 64 - right * 128 + up * 64, MOVE_NOMONSTERS, it);
break;
case 2:
- tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin + v_right * 192 + v_up * 64, MOVE_NOMONSTERS, it);
+ tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin + right * 192 + up * 64, MOVE_NOMONSTERS, it);
break;
case 3:
- tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin - v_right * 192 + v_up * 64, MOVE_NOMONSTERS, it);
+ tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin - right * 192 + up * 64, MOVE_NOMONSTERS, it);
break;
case 4:
- tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin - v_forward * 128 + v_right * 64 + v_up * 64, MOVE_NOMONSTERS, it);
+ tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin - forward * 128 + right * 64 + up * 64, MOVE_NOMONSTERS, it);
break;
case 5:
- tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin - v_forward * 128 - v_right * 64 + v_up * 64, MOVE_NOMONSTERS, it);
+ tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin - forward * 128 - right * 64 + up * 64, MOVE_NOMONSTERS, it);
break;
}
// 400 is about the height of a typical laser jump (in overkill)
// not traceline because we need space for the whole player, not just his origin
- tracebox(horizontal_trace_endpos, STAT(PL_MIN, player), STAT(PL_MAX, player), horizontal_trace_endpos - '0 0 400', MOVE_NORMAL, it);
+ tracebox(horizontal_trace_endpos, STAT(PL_MIN, player), STAT(PL_MAX, player), horizontal_trace_endpos - 400 * up, MOVE_NORMAL, it);
vector vectical_trace_endpos = trace_endpos;
//te_lightning1(NULL, horizontal_trace_endpos, vectical_trace_endpos);
if (trace_startsolid) goto skip; // inside another player
if (tracebox_hits_trigger_hurt(horizontal_trace_endpos, STAT(PL_MIN, player), STAT(PL_MAX, player), vectical_trace_endpos)) goto skip;
// make sure the spawned player will have floor ahead (or at least a wall - he shouldn't fall as soon as he starts moving)
- vector floor_test_start = vectical_trace_endpos + v_up * STAT(PL_MAX, player).z + v_forward * STAT(PL_MAX, player).x; // top front of player's bbox - highest point we know is not inside solid
- traceline(floor_test_start, floor_test_start + v_forward * 100 - v_up * 128, MOVE_NOMONSTERS, it);
+ // top front of player's bbox - highest point we know is not inside solid
+ vector floor_test_start = vectical_trace_endpos + up * STAT(PL_MAX, player).z + forward * STAT(PL_MAX, player).x;
+ traceline(floor_test_start, floor_test_start + forward * 100 - up * 128, MOVE_NOMONSTERS, it);
//te_beam(NULL, floor_test_start, trace_endpos);
if (trace_fraction == 1.0) goto skip;
// here, we know we found a good spot
RandomSelection_Add(it, 0, string_null, vectical_trace_endpos, 1, 1);
- //te_lightning1(NULL, vectical_trace_endpos, vectical_trace_endpos + v_forward * 10);
+ //te_lightning1(NULL, vectical_trace_endpos, vectical_trace_endpos + forward * 10);
LABEL(skip)
if (i % 2 == 1 && RandomSelection_chosen_ent)
// WEAPONTODO: trace to find what we actually hit
vector endpos = (this.sw_shotorg + (this.sw_shotdir * this.sw_distance));
- vectorvectors(this.sw_shotdir);
- vector right = v_right; // save this for when we do makevectors later
- vector up = v_up; // save this for when we do makevectors later
+ VECTOR_VECTORS_NEW(this.sw_shotdir, _forward, right, up);
// WEAPONTODO: combine and simplify these calculations
vector min_end = ((this.sw_shotorg + (this.sw_shotdir * SW_DISTTOMIN)) + (up * this.sw_spread_min));
#define use use1
.void(entity this, entity actor, entity trigger) use;
#define touch move_touch
+
+// deglobalization:
+
+void(vector ang) _makevectors_hidden = #1;
+//#define makevectors DO_NOT_USE_GLOBALS_PREFER_MAKE_VECTORS_MACRO_INSTEAD
+
+#define makestatic DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
+
+#define skel_get_bonerel DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
+
+vector(float skel, float bonenum) _skel_get_boneabs_hidden = #270;
+//#define skel_get_boneabs DO_NOT_USE_GLOBALS_PREFER_SKEL_GET_BONE_ABS_MACRO_INSTEAD
+
+void(float skel, float bonenum, vector org) _skel_set_bone_hidden = #271;
+//#define skel_set_bone DO_NOT_USE_GLOBALS_PREFER_SKEL_SET_BONE_MACRO_INSTEAD
+
+#define skel_mul_bone DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
+
+#define skel_mul_bones DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
+
+void(vector org, float radius, vector lightcolours) _adddynamiclight_hidden = #305;
+//#define adddynamiclight DO_NOT_USE_GLOBALS_PREFER_ADD_DYNAMIC_LIGHT_MACRO_INSTEAD
+#define adddynamiclight2 DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
+
+void(vector dir) _vectorvectors_hidden = #432;
+#define vectorvectors DO_NOT_USE_GLOBALS_PREFER_VECTOR_VECTORS_MACRO_INSTEAD
+
+vector(entity ent, float tagindex) _gettaginfo_hidden = #452;
+//#define gettaginfo DO_NOT_USE_GLOBALS_PREFER_GET_TAG_INFO_MACRO_INSTEAD
+
+#define getentity DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
+#define getentityvec DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
#define buf_create _buf_create
#pragma noref 0
+
+// deglobalization:
+
+#define skel_get_bonerel DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
+
+vector(float skel, float bonenum) _skel_get_boneabs_hidden = #270;
+//#define skel_get_boneabs DO_NOT_USE_GLOBALS_PREFER_SKEL_GET_BONE_ABS_MACRO_INSTEAD
+
+void(float skel, float bonenum, vector org) _skel_set_bone_hidden = #271;
+//#define skel_set_bone DO_NOT_USE_GLOBALS_PREFER_SKEL_SET_BONE_MACRO_INSTEAD
+
+#define skel_mul_bone DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
+
+#define skel_mul_bones DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
+
+vector(entity ent, float tagindex) _gettaginfo_hidden = #452;
+//#define gettaginfo DO_NOT_USE_GLOBALS_PREFER_GET_TAG_INFO_MACRO_INSTEAD
#define use use1
.void(entity this, entity actor, entity trigger) use;
+
+// deglobalization:
+
+void(vector ang) _makevectors_hidden = #1;
+//#define makevectors DO_NOT_USE_GLOBALS_PREFER_MAKE_VECTORS_MACRO_INSTEAD
+
+#define aim DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
+
+#define makestatic DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
// this mimics quakeworld code
if (this.com_in_jump && this.waterlevel == WATERLEVEL_SWIMMING && this.velocity_z >= -180 && !this.viewloc) {
vector yawangles = '0 1 0' * this.v_angle.y;
- makevectors(yawangles);
- vector forward = v_forward;
+ MAKE_VECTORS_NEW(yawangles, forward, right, up);
vector spot = this.origin + 24 * forward;
spot_z += 8;
traceline(spot, spot, MOVE_NOMONSTERS, this);
}
}
}
- makevectors(vmul(this.v_angle, (this.com_phys_vel_2d ? '0 1 0' : '1 1 1')));
- // wishvel = v_forward * PHYS_CS(this).movement.x + v_right * PHYS_CS(this).movement.y + v_up * PHYS_CS(this).movement.z;
- vector wishvel = v_forward * PHYS_CS(this).movement.x
- + v_right * PHYS_CS(this).movement.y
+
+ MAKE_VECTORS_NEW(vmul(this.v_angle, (this.com_phys_vel_2d ? '0 1 0' : '1 1 1')), forward, right, up);
+ // wishvel = forward * PHYS_CS(this).movement.x + right * PHYS_CS(this).movement.y + up * PHYS_CS(this).movement.z;
+ vector wishvel = forward * PHYS_CS(this).movement.x
+ + right * PHYS_CS(this).movement.y
+ '0 0 1' * PHYS_CS(this).movement.z * (this.com_phys_vel_2d ? 0 : 1);
if (this.com_phys_water) {
if (PHYS_INPUT_BUTTON_CROUCH(this)) {
#include "counting.qh"
#include "cvar.qh"
#include "defer.qh"
+#include "deglobalization.qh"
#include "draw.qh"
#include "enumclass.qh"
#include "file.qh"
+#include "float.qh"
#include "functional.qh"
#include "i18n.qh"
#include "intrusivelist.qh"
if (this.iflags & IFLAG_ANGLES)
{
- fixedmakevectors(this.angles);
+ FIXED_MAKE_VECTORS_NEW(this.angles, forward, right, up);
if (f0 & IFLAG_VALID)
{
this.iforward1 = this.iforward2;
}
else
{
- this.iforward1 = v_forward;
- this.iup1 = v_up;
+ this.iforward1 = forward;
+ this.iup1 = up;
}
- this.iforward2 = v_forward;
- this.iup2 = v_up;
+ this.iforward2 = forward;
+ this.iup2 = up;
}
if (this.iflags & IFLAG_V_ANGLE)
{
- fixedmakevectors(this.v_angle);
+ FIXED_MAKE_VECTORS_NEW(this.v_angle, forward, right, up);
if (f0 & IFLAG_VALID)
{
this.ivforward1 = this.ivforward2;
}
else
{
- this.ivforward1 = v_forward;
- this.ivup1 = v_up;
+ this.ivforward1 = forward;
+ this.ivup1 = up;
}
- this.ivforward2 = v_forward;
- this.ivup2 = v_up;
+ this.ivforward2 = forward;
+ this.ivup2 = up;
}
else if (this.iflags & IFLAG_V_ANGLE_X)
{
--- /dev/null
+#include "lib/float.qh"
+#include "lib/misc.qh"
+#include "lib/static.qh"
+#include "lib/vector.qh"
+
+// These macros wrap functions which use globals so mutation only occurs inside them and is not visible from outside.
+// Functions for which all usages are replaced with these macros can be hidden by #defines inside our `*defs.qh` files
+// to prevent anyone from using them accidentally in the future
+
+// TODO stuff in the engine that uses the v_forward/v_right/v_up globals and is not wrapped yet:
+// - RF_USEAXIS, addentities, predraw,
+// - CL_GetEntityMatrix (in engine but is called from other functions so transitively any of them can use the globals - e.g. V_CalcRefdef, maybe others)
+// - however RF_USEAXIS is only used if MF_ROTATE is used which is only set in one place
+// - e.camera_transform / CL_VM_TransformView (in engine
+// - this is the only used function that both sets and gets the globals (aim does too but isn't used in our code)
+
+#define NEW_VECS(...) EVAL(OVERLOAD(NEW_VECS, __VA_ARGS__))
+#define NEW_VECS_3(forward, right, up) vector forward = '0 0 0'; vector right = '0 0 0'; vector up = '0 0 0';
+#define NEW_VECS_4(forward, right, up, origin) NEW_VECS_3(forward, right, up); vector origin = '0 0 0';
+
+// convenience for deglobalized code - don't use these just to hide that globals are still used
+#define CLEAR_V_GLOBALS() v_forward = VEC_NAN; v_right = VEC_NAN; v_up = VEC_NAN;
+#define GET_V_GLOBALS(forward, right, up) forward = v_forward; right = v_right; up = v_up;
+#define SET_V_GLOBALS(forward, right, up) v_forward = forward; v_right = right; v_up = up;
+
+#ifdef GAMEQC
+STATIC_INIT(globals) {
+ // set to NaN to more easily detect uninitialized use
+ // TODO when all functions are wrapped and the raw functions are not used anymore,
+ // uncomment the defines in *progs.qh files that hide the raw functions
+ // and assert that the global vectors are NaN before calling the raw functions here
+ // to make sure nobody (even builtins) is accidentally using them - NaN is the most likely value to expose remaining usages
+
+ CLEAR_V_GLOBALS();
+}
+#endif
+
+/// Same as the `makevectors` builtin but uses the provided locals instead of the `v_*` globals.
+/// Always use this instead of raw `makevectors` to make the data flow clear.
+/// Note that you might prefer `FIXED_MAKE_VECTORS` for new code.
+#define MAKE_VECTORS(angles, forward, right, up) MACRO_BEGIN { \
+ _makevectors_hidden(angles); \
+ GET_V_GLOBALS(forward, right, up); \
+ CLEAR_V_GLOBALS(); \
+} MACRO_END
+
+/// Same as `MAKE_VECTORS` but also creates the locals for convenience.
+#define MAKE_VECTORS_NEW(angles, forward, right, up) \
+ NEW_VECS(forward, right, up); \
+ MAKE_VECTORS(angles, forward, right, up);
+
+/// Returns all 4 vectors by assigning to them (instead of returning a value) for consistency (and sanity)
+#define SKEL_GET_BONE_ABS(skel, bonenum, forward, right, up, origin) MACRO_BEGIN { \
+ origin = _skel_get_boneabs_hidden(skel, bonenum) \
+ GET_V_GLOBALS(forward, right, up); \
+ CLEAR_V_GLOBALS(); \
+} MACRO_END
+
+#define SKEL_GET_BONE_ABS_NEW(skel, bonenum, forward, right, up, origin) \
+ NEW_VECS(forward, right, up, origin); \
+ SKEL_GET_BONE_ABS(skel, bonenum, forward, right, up, origin)
+
+#define SKEL_SET_BONE(skel, bonenum, org, forward, right, up) MACRO_BEGIN { \
+ SET_V_GLOBALS(forward, right, up); \
+ _skel_set_bone_hidden(skel, bonenum, org); \
+ CLEAR_V_GLOBALS(); \
+} MACRO_END
+
+#define ADD_DYNAMIC_LIGHT(org, radius, lightcolours, forward, right, up) MACRO_BEGIN { \
+ SET_V_GLOBALS(forward, right, up); \
+ _adddynamiclight_hidden(org, radius, lightcolours); \
+ CLEAR_V_GLOBALS(); \
+} MACRO_END
+
+#define VECTOR_VECTORS(forward_in, forward, right, up) MACRO_BEGIN { \
+ _vectorvectors_hidden(forward_in); \
+ GET_V_GLOBALS(forward, right, up); \
+ CLEAR_V_GLOBALS(); \
+} MACRO_END
+
+#define VECTOR_VECTORS_NEW(forward_in, forward, right, up) \
+ NEW_VECS(forward, right, up); \
+ VECTOR_VECTORS(forward_in, forward, right, up);
+
+/// Note that this only avoids the v_* globals, not the gettaginfo_* ones
+#define GET_TAG_INFO(ent, tagindex, forward, right, up, origin) MACRO_BEGIN { \
+ origin = _gettaginfo_hidden(ent, tagindex); \
+ GET_V_GLOBALS(forward, right, up); \
+ CLEAR_V_GLOBALS(); \
+} MACRO_END
+
+#define GET_TAG_INFO_NEW(ent, tagindex, forward, right, up, origin) \
+ NEW_VECS(forward, right, up, origin); \
+ GET_TAG_INFO(ent, tagindex, forward, right, up, origin);
const float FLOAT_MAX = 340282346638528859811704183484516925440.0f;
const float FLOAT_EPSILON = 0.00000011920928955078125f;
+/// Always use `isnan` function to compare because `float x = FLOAT_NAN; x == x;` gives true
+const float FLOAT_NAN = 0.0 / 0.0;
#define YAW(v) ((v).y)
#define ROLL(v) ((v).z)
-#define MAKEVECTORS(f, angles, forward, right, up) MACRO_BEGIN { \
- f(angles); \
- forward = v_forward; \
- right = v_right; \
- up = v_up; \
-} MACRO_END
-
//pseudo prototypes:
// vector vec2(vector v); // returns a vector with just the x and y components of the given vector
// vector vec2(float x, float y); // returns a vector with the given x and y components
noref vector _vec3;
#define vec3(_x, _y, _z) (_vec3.x = (_x), _vec3.y = (_y), _vec3.z = (_z), _vec3)
+#define VEC_NAN vec3(FLOAT_NAN, FLOAT_NAN, FLOAT_NAN);
+
+ERASEABLE
+bool is_all_nans(vector v) {
+ return isnan(v.x) && isnan(v.y) && isnan(v.z);
+}
+
ERASEABLE
vector Rotate(vector v, float a)
{
// angles in fixedmakevectors/fixedvectoangles space
vector AnglesTransform_Apply(vector transform, vector v)
{
- fixedmakevectors(transform);
- return v_forward * v.x
- + v_right * (-v.y)
- + v_up * v.z;
+ FIXED_MAKE_VECTORS_NEW(transform, forward, right, up);
+ return forward * v.x + right * (-v.y) + up * v.z;
}
vector AnglesTransform_Multiply(vector t1, vector t2)
{
- vector m_forward, m_up;
- fixedmakevectors(t2); m_forward = v_forward; m_up = v_up;
- m_forward = AnglesTransform_Apply(t1, m_forward); m_up = AnglesTransform_Apply(t1, m_up);
- return fixedvectoangles2(m_forward, m_up);
+ FIXED_MAKE_VECTORS_NEW(t2, forward, right, up);
+ forward = AnglesTransform_Apply(t1, forward);
+ up = AnglesTransform_Apply(t1, up);
+ return fixedvectoangles2(forward, up);
}
vector AnglesTransform_Invert(vector transform)
{
vector i_forward, i_up;
- fixedmakevectors(transform);
- // we want angles that turn v_forward into '1 0 0', v_right into '0 1 0' and v_up into '0 0 1'
+ FIXED_MAKE_VECTORS_NEW(transform, forward, right, up);
+ // we want angles that turn forward into '1 0 0', right into '0 1 0' and up into '0 0 1'
// but these are orthogonal unit vectors!
// so to invert, we can simply fixedvectoangles the TRANSPOSED matrix
// TODO is this always -transform?
- i_forward.x = v_forward.x;
- i_forward.y = -v_right.x;
- i_forward.z = v_up.x;
- i_up.x = v_forward.z;
- i_up.y = -v_right.z;
- i_up.z = v_up.z;
+ i_forward.x = forward.x;
+ i_forward.y = -right.x;
+ i_forward.z = up.x;
+ i_up.x = forward.z;
+ i_up.y = -right.z;
+ i_up.z = up.z;
return fixedvectoangles2(i_forward, i_up);
}
#if POSITIVE_PITCH_IS_DOWN
#define fixedmakevectors makevectors
+ #define FIXED_MAKE_VECTORS MAKE_VECTORS
+ #define FIXED_MAKE_VECTORS_NEW MAKE_VECTORS_NEW
noref vector _fixedvectoangles;
#define fixedvectoangles(a) (_fixedvectoangles = vectoangles(a), _fixedvectoangles.x *= -1, _fixedvectoangles)
noref vector _fixedvectoangles2;
a.x = -a.x;
makevectors(a);
}
+ #define FIXED_MAKE_VECTORS(angles, forward, right, up) MACRO_BEGIN { \
+ fixedmakevectors(angles); \
+ GET_V_GLOBALS(forward, right, up); \
+ CLEAR_V_GLOBALS(); \
+ } MACRO_END
+ #define FIXED_MAKE_VECTORS_NEW(angles, forward, right, up) \
+ VECS_NEW(forward, right, up); \
+ FIXED_MAKE_VECTORS(angles, forward, right, up);
#define fixedvectoangles2 vectoangles2
#define fixedvectoangles vectoangles
#endif
e.warpzone_targetorigin = other_org;
e.warpzone_angles = my_ang;
e.warpzone_targetangles = other_ang;
- fixedmakevectors(my_ang); e.warpzone_forward = v_forward;
- fixedmakevectors(other_ang); e.warpzone_targetforward = v_forward;
+ FIXED_MAKE_VECTORS_NEW(my_ang, forward, right, up);
+ e.warpzone_forward = forward;
+ FIXED_MAKE_VECTORS(other_ang, forward, right, up);
+ e.warpzone_targetforward = forward;
setcamera_transform(e, WarpZone_camera_transform);
}
float nomonsters_adjusted;
float frac, sol, i;
float contentshack;
- vector o0, e0;
entity wz;
vector vf, vr, vu;
vf = v_forward;
vr = v_right;
vu = v_up;
- o0 = org;
- e0 = end;
switch(nomonsters)
{
}
bool isnan(float e)
{
- float f = e;
- return (e != f);
+ // the sane way to detect NaN is broken because of a compiler bug
+ // (works with constants but breaks when assigned to variables)
+ // use conversion to string instead
+
+ //float f = e;
+ //return (e != f);
+ return ftos(e) == "-nan";
}
bool isnormal(float e)
{
{
return fabs(e) * ((f>0) ? 1 : -1);
}
+/// Always use `isnan` function to compare because `float x = nan(); x == x;` gives true
float nan(string tag)
{
return sqrt(-1);
if(area > 0)
{
org = org - ((org - point) * norm) * norm; // project to plane
- makevectors(ang);
- if(norm * v_forward < 0)
+ MAKE_VECTORS_NEW(ang, forward, right, up);
+ if(norm * forward < 0)
{
LOG_INFO("Position target of trigger_warpzone near ", vtos(this.aiment.origin), " points into trigger_warpzone. BEWARE.");
norm = -1 * norm;
}
- ang = vectoangles2(norm, v_up); // keep rotation, but turn exactly against plane
+ ang = vectoangles2(norm, up); // keep rotation, but turn exactly against plane
ang.x = -ang.x;
- if(norm * v_forward < 0.99)
+ if(norm * forward < 0.99)
LOG_INFO("trigger_warpzone near ", vtos(this.aiment.origin), " has been turned to match plane orientation (", vtos(this.aiment.angles), " -> ", vtos(ang));
if(vdist(org - this.aiment.origin, >, 0.5))
LOG_INFO("trigger_warpzone near ", vtos(this.aiment.origin), " has been moved to match the plane (", vtos(this.aiment.origin), " -> ", vtos(org), ").");
if (this.movedir == '0 0 0')
if (this.angles != '0 0 0')
{
- makevectors (this.angles);
- this.movedir = v_forward;
+ MAKE_VECTORS_NEW(this.angles, forward, _r, _u);
+ this.movedir = forward;
}
if(this.model == "")
{
if (autocvar_r_showbboxes)
{
// show where spawnpoints point at too
- makevectors(this.angles);
+ MAKE_VECTORS_NEW(this.angles, forward, right, up);
entity e = new(info_player_foo);
- setorigin(e, this.origin + v_forward * 24);
+ setorigin(e, this.origin + forward * 24);
setsize(e, '-8 -8 -8', '8 8 8');
e.solid = SOLID_TRIGGER;
}
WarpZone_TraceLine(ent.origin + ent.view_ofs, ent.origin + ent.view_ofs + s_forward * range, MOVE_NOMONSTERS, ent);
ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
- vector vf, vr, vu;
- vf = v_forward;
- vr = v_right;
- vu = v_up;
+ NEW_VECS(forward, right, up);
+ forward = v_forward;
+ right = v_right;
+ up = v_up;
w_shotend = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos); // warpzone support
- v_forward = vf;
- v_right = vr;
- v_up = vu;
+ v_forward = forward;
+ v_right = right;
+ v_up = up;
// un-adjust trueaim if shotend is too close
if(vdist(w_shotend - (ent.origin + ent.view_ofs), <, autocvar_g_trueaim_minrange))
accuracy_add(ent, wep, maxdamage, 0);
if(IS_PLAYER(ent))
- W_HitPlotAnalysis(ent, wep, v_forward, v_right, v_up);
+ W_HitPlotAnalysis(ent, wep, forward, right, up);
vector md = ent.(weaponentity).movedir;
vector vecs = ((md.x > 0) ? md : '0 0 0');
- vector dv = v_forward * vecs.x + v_right * -vecs.y + v_up * vecs.z;
+ vector dv = forward * vecs.x + right * -vecs.y + up * vecs.z;
w_shotorg = ent.origin + ent.view_ofs;
// now move the shotorg forward as much as requested if possible
restartanim = fr != WFRAME_IDLE;
}
- vector of = v_forward;
- vector or = v_right;
- vector ou = v_up;
-
vector a = '0 0 0';
this.wframe = fr;
if (fr == WFRAME_IDLE) a = this.anim_idle;
a = this.anim_reload;
a.z *= g_weaponratefactor;
- v_forward = of;
- v_right = or;
- v_up = ou;
-
if (this.weapon_think == w_ready && func != w_ready && this.state == WS_RAISE) backtrace(
"Tried to override initial weapon think function - should this really happen?");
return;
}
- makevectors(actor.v_angle);
- vector fo = v_forward; // save them in case the weapon think functions change it
- vector ri = v_right;
- vector up = v_up;
+ MAKE_VECTORS_NEW(actor.v_angle, fo, ri, up);
// Change weapon
if (this.m_weapon != this.m_switchweapon)