From: Martin Taibr Date: Sat, 17 Aug 2019 18:30:52 +0000 (+0200) Subject: Merge branch 'master' into martin-t/globals X-Git-Tag: xonotic-v0.8.5~1258^2 X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=commitdiff_plain;h=8e69041898af22d651b6416745431cbaab84b0d5;hp=3c1e56f26fd675c3606d34b3afa94e3889ff4350 Merge branch 'master' into martin-t/globals --- diff --git a/qcsrc/client/csqcmodel_hooks.qc b/qcsrc/client/csqcmodel_hooks.qc index a064195560..1272758f76 100644 --- a/qcsrc/client/csqcmodel_hooks.qc +++ b/qcsrc/client/csqcmodel_hooks.qc @@ -540,8 +540,11 @@ void CSQCModel_Effects_Apply(entity this) 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 MF_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; diff --git a/qcsrc/client/teamradar.qc b/qcsrc/client/teamradar.qc index 26de41e724..c565651d4a 100644 --- a/qcsrc/client/teamradar.qc +++ b/qcsrc/client/teamradar.qc @@ -93,8 +93,8 @@ void draw_teamradar_player(vector coord3d, vector pangles, vector rgb) 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); + vector forward, right, up; + MAKE_VECTORS(pangles - '0 1 0' * teamradar_angle, forward, right, up); if(v_flipped) { forward.x = -forward.x; diff --git a/qcsrc/client/view.qc b/qcsrc/client/view.qc index 7c3c1068b1..dadf6069ab 100644 --- a/qcsrc/client/view.qc +++ b/qcsrc/client/view.qc @@ -133,8 +133,8 @@ void calc_followmodel_ofs(entity view) vel = view.velocity; else { - vector forward = '0 0 0', right = '0 0 0', up = '0 0 0'; - MAKEVECTORS(makevectors, view_angles, forward, right, up); + vector forward, right, up; + MAKE_VECTORS(view_angles, forward, right, up); vel.x = view.velocity * forward; vel.y = view.velocity * right * -1; vel.z = view.velocity * up; @@ -159,8 +159,8 @@ void calc_followmodel_ofs(entity view) 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); + vector forward, right, up; + MAKE_VECTORS(view_angles, forward, right, up); fixed_gunorg.x = gunorg * forward; fixed_gunorg.y = gunorg * right * -1; fixed_gunorg.z = gunorg * up; @@ -491,15 +491,16 @@ vector GetCurrentFov(float fov) curspeed = 0; else { - makevectors(view_angles); + vector forward, right, up; + MAKE_VECTORS(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; } } @@ -1727,18 +1728,19 @@ void CSQC_UpdateView(entity this, float w, float h) else if(eventchase_current_distance != chase_distance) eventchase_current_distance = chase_distance; - makevectors(view_angles); + vector forward, right, up; + MAKE_VECTORS(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); } @@ -1865,7 +1867,7 @@ void CSQC_UpdateView(entity this, float w, float h) // 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) @@ -2416,14 +2418,15 @@ void CSQC_UpdateView(entity this, float w, float h) setproperty(VF_ORIGIN, '0 0 0'); setproperty(VF_ANGLES, '0 0 0'); setproperty(VF_PERSPECTIVE, 1); - makevectors('0 0 0'); + vector forward, right, up; + MAKE_VECTORS('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 diff --git a/qcsrc/common/debug.qh b/qcsrc/common/debug.qh index 55b634a624..05064ca967 100644 --- a/qcsrc/common/debug.qh +++ b/qcsrc/common/debug.qh @@ -295,7 +295,7 @@ MUTATOR_HOOKFUNCTION(trace, SV_StartFrame) 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, { diff --git a/qcsrc/common/mutators/mutator/damagetext/cl_damagetext.qc b/qcsrc/common/mutators/mutator/damagetext/cl_damagetext.qc index 5e59fd9f32..899c6d63c1 100644 --- a/qcsrc/common/mutators/mutator/damagetext/cl_damagetext.qc +++ b/qcsrc/common/mutators/mutator/damagetext/cl_damagetext.qc @@ -74,9 +74,10 @@ CLASS(DamageText, Object) if (this.m_screen_coords) { screen_pos = this.origin + since_hit * autocvar_cl_damagetext_2d_velocity; } else { - makevectors(view_angles); + vector forward, right, up; + MAKE_VECTORS(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; diff --git a/qcsrc/common/mutators/mutator/dodging/sv_dodging.qc b/qcsrc/common/mutators/mutator/dodging/sv_dodging.qc index 6640cb8bf2..652f7a2b7b 100644 --- a/qcsrc/common/mutators/mutator/dodging/sv_dodging.qc +++ b/qcsrc/common/mutators/mutator/dodging/sv_dodging.qc @@ -113,20 +113,20 @@ REGISTER_MUTATOR(dodging, true); 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; } @@ -180,10 +180,11 @@ bool PM_dodging_checkpressedkeys(entity this) if ((time - this.last_dodging_time) < PHYS_DODGING_DELAY) return false; - makevectors(this.angles); + vector forward, right, up; + MAKE_VECTORS(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; @@ -221,11 +222,11 @@ void PM_dodging(entity this) return; } - // make sure v_up, v_right and v_forward are sane + vector 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 @@ -237,15 +238,15 @@ void PM_dodging(entity this) 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) diff --git a/qcsrc/common/mutators/mutator/spawn_near_teammate/sv_spawn_near_teammate.qc b/qcsrc/common/mutators/mutator/spawn_near_teammate/sv_spawn_near_teammate.qc index 73435841d8..2243c9872c 100644 --- a/qcsrc/common/mutators/mutator/spawn_near_teammate/sv_spawn_near_teammate.qc +++ b/qcsrc/common/mutators/mutator/spawn_near_teammate/sv_spawn_near_teammate.qc @@ -103,10 +103,15 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn) 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 + vector forward = '0 0 0'; vector right = '0 0 0'; vector up = '0 0 0'; 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 @@ -117,22 +122,22 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn) 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; } @@ -142,7 +147,7 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn) // 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 @@ -152,8 +157,9 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn) 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; @@ -171,7 +177,7 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn) // 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) diff --git a/qcsrc/common/weapons/weapon/shockwave.qc b/qcsrc/common/weapons/weapon/shockwave.qc index cdd0a0f92a..9b1dd6c0b8 100644 --- a/qcsrc/common/weapons/weapon/shockwave.qc +++ b/qcsrc/common/weapons/weapon/shockwave.qc @@ -663,9 +663,8 @@ void Draw_Shockwave(entity this) // 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 _forward, right, up; + VECTOR_VECTORS(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)); diff --git a/qcsrc/dpdefs/csprogsdefs.qh b/qcsrc/dpdefs/csprogsdefs.qh index 29d797585e..9453157f70 100644 --- a/qcsrc/dpdefs/csprogsdefs.qh +++ b/qcsrc/dpdefs/csprogsdefs.qh @@ -43,3 +43,35 @@ #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 diff --git a/qcsrc/dpdefs/dpextensions.qh b/qcsrc/dpdefs/dpextensions.qh index 2ed0f90638..d6f6a072a0 100644 --- a/qcsrc/dpdefs/dpextensions.qh +++ b/qcsrc/dpdefs/dpextensions.qh @@ -63,3 +63,20 @@ int() _buf_create = #460; #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 diff --git a/qcsrc/dpdefs/progsdefs.qh b/qcsrc/dpdefs/progsdefs.qh index ccdf9bc0c4..a8d8a4a486 100644 --- a/qcsrc/dpdefs/progsdefs.qh +++ b/qcsrc/dpdefs/progsdefs.qh @@ -29,3 +29,12 @@ MACRO_END #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 diff --git a/qcsrc/ecs/systems/physics.qc b/qcsrc/ecs/systems/physics.qc index ae5f119e7f..f73ade3d12 100644 --- a/qcsrc/ecs/systems/physics.qc +++ b/qcsrc/ecs/systems/physics.qc @@ -193,8 +193,8 @@ void sys_phys_simulate(entity this, float dt) // 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; + vector forward, right, up; + MAKE_VECTORS(yawangles, forward, right, up); vector spot = this.origin + 24 * forward; spot_z += 8; traceline(spot, spot, MOVE_NOMONSTERS, this); @@ -210,10 +210,12 @@ void sys_phys_simulate(entity this, float dt) } } } - 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 + + vector forward, right, up; + MAKE_VECTORS(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)) { diff --git a/qcsrc/lib/_all.inc b/qcsrc/lib/_all.inc index ab74531605..3bbb17ccf8 100644 --- a/qcsrc/lib/_all.inc +++ b/qcsrc/lib/_all.inc @@ -112,9 +112,11 @@ #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" diff --git a/qcsrc/lib/csqcmodel/interpolate.qc b/qcsrc/lib/csqcmodel/interpolate.qc index 4fd138360a..7600fdde60 100644 --- a/qcsrc/lib/csqcmodel/interpolate.qc +++ b/qcsrc/lib/csqcmodel/interpolate.qc @@ -58,7 +58,8 @@ void InterpolateOrigin_Note(entity this) if (this.iflags & IFLAG_ANGLES) { - fixedmakevectors(this.angles); + vector forward, right, up; + FIXED_MAKE_VECTORS(this.angles, forward, right, up); if (f0 & IFLAG_VALID) { this.iforward1 = this.iforward2; @@ -66,16 +67,17 @@ void InterpolateOrigin_Note(entity this) } 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); + vector forward, right, up; + FIXED_MAKE_VECTORS(this.v_angle, forward, right, up); if (f0 & IFLAG_VALID) { this.ivforward1 = this.ivforward2; @@ -83,11 +85,11 @@ void InterpolateOrigin_Note(entity this) } 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) { diff --git a/qcsrc/lib/deglobalization.qh b/qcsrc/lib/deglobalization.qh new file mode 100644 index 0000000000..3d7f820674 --- /dev/null +++ b/qcsrc/lib/deglobalization.qh @@ -0,0 +1,73 @@ +#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) + +// convenience for deglobalization 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 + +/// 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_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 + +/// 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 diff --git a/qcsrc/lib/float.qh b/qcsrc/lib/float.qh index b4d1f0bd76..b35494de44 100644 --- a/qcsrc/lib/float.qh +++ b/qcsrc/lib/float.qh @@ -2,3 +2,5 @@ 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; diff --git a/qcsrc/lib/vector.qh b/qcsrc/lib/vector.qh index 0d09ea8e6a..ca0e84f67a 100644 --- a/qcsrc/lib/vector.qh +++ b/qcsrc/lib/vector.qh @@ -93,13 +93,6 @@ float boxinsidebox(vector smins, vector smaxs, vector bmins, vector bmaxs) { ret #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 @@ -112,6 +105,13 @@ noref vector _vec2; 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) { diff --git a/qcsrc/lib/warpzone/anglestransform.qc b/qcsrc/lib/warpzone/anglestransform.qc index 9e98199f34..76e8d37f9a 100644 --- a/qcsrc/lib/warpzone/anglestransform.qc +++ b/qcsrc/lib/warpzone/anglestransform.qc @@ -4,34 +4,35 @@ // 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; + vector forward, right, up; + FIXED_MAKE_VECTORS(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); + vector forward, right, up; + FIXED_MAKE_VECTORS(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' + vector forward, right, up; + FIXED_MAKE_VECTORS(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); } diff --git a/qcsrc/lib/warpzone/anglestransform.qh b/qcsrc/lib/warpzone/anglestransform.qh index b287651a10..92362f982f 100644 --- a/qcsrc/lib/warpzone/anglestransform.qh +++ b/qcsrc/lib/warpzone/anglestransform.qh @@ -6,6 +6,7 @@ #if POSITIVE_PITCH_IS_DOWN #define fixedmakevectors makevectors + #define FIXED_MAKE_VECTORS MAKE_VECTORS noref vector _fixedvectoangles; #define fixedvectoangles(a) (_fixedvectoangles = vectoangles(a), _fixedvectoangles.x *= -1, _fixedvectoangles) noref vector _fixedvectoangles2; @@ -17,6 +18,11 @@ 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 fixedvectoangles2 vectoangles2 #define fixedvectoangles vectoangles #endif diff --git a/qcsrc/lib/warpzone/common.qc b/qcsrc/lib/warpzone/common.qc index b70e938fe7..3bff39be1f 100644 --- a/qcsrc/lib/warpzone/common.qc +++ b/qcsrc/lib/warpzone/common.qc @@ -71,8 +71,11 @@ void WarpZone_SetUp(entity e, vector my_org, vector my_ang, vector other_org, ve 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; + vector forward, right, up; + FIXED_MAKE_VECTORS(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); } @@ -201,7 +204,6 @@ void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end, float nomonsters_adjusted; float frac, sol, i; float contentshack; - vector o0, e0; entity wz; vector vf, vr, vu; @@ -231,8 +233,6 @@ void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end, vf = v_forward; vr = v_right; vu = v_up; - o0 = org; - e0 = end; switch(nomonsters) { diff --git a/qcsrc/lib/warpzone/mathlib.qc b/qcsrc/lib/warpzone/mathlib.qc index 4a7c886106..9105269ff3 100644 --- a/qcsrc/lib/warpzone/mathlib.qc +++ b/qcsrc/lib/warpzone/mathlib.qc @@ -24,8 +24,13 @@ bool isinf(float e) } 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) { @@ -217,6 +222,7 @@ float copysign(float e, float f) { 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); diff --git a/qcsrc/lib/warpzone/server.qc b/qcsrc/lib/warpzone/server.qc index 9958a5df4a..0244b40a9d 100644 --- a/qcsrc/lib/warpzone/server.qc +++ b/qcsrc/lib/warpzone/server.qc @@ -602,15 +602,16 @@ void WarpZone_InitStep_UpdateTransform(entity this) if(area > 0) { org = org - ((org - point) * norm) * norm; // project to plane - makevectors(ang); - if(norm * v_forward < 0) + vector forward, right, up; + MAKE_VECTORS(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), ")."); diff --git a/qcsrc/lib/warpzone/util_server.qc b/qcsrc/lib/warpzone/util_server.qc index d5533647f5..658716052f 100644 --- a/qcsrc/lib/warpzone/util_server.qc +++ b/qcsrc/lib/warpzone/util_server.qc @@ -15,8 +15,9 @@ void WarpZoneLib_ExactTrigger_Init(entity this) if (this.movedir == '0 0 0') if (this.angles != '0 0 0') { - makevectors (this.angles); - this.movedir = v_forward; + vector forward, _r, _u; + MAKE_VECTORS(this.angles, forward, _r, _u); + this.movedir = forward; } if(this.model == "") { diff --git a/qcsrc/server/spawnpoints.qc b/qcsrc/server/spawnpoints.qc index 730c92884f..5aa81a2a73 100644 --- a/qcsrc/server/spawnpoints.qc +++ b/qcsrc/server/spawnpoints.qc @@ -119,9 +119,10 @@ void relocate_spawnpoint(entity this) if (autocvar_r_showbboxes) { // show where spawnpoints point at too - makevectors(this.angles); + vector forward, right, up; + MAKE_VECTORS(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; } diff --git a/qcsrc/server/weapons/tracing.qc b/qcsrc/server/weapons/tracing.qc index 99fa2df749..ef7f1a832b 100644 --- a/qcsrc/server/weapons/tracing.qc +++ b/qcsrc/server/weapons/tracing.qc @@ -51,14 +51,14 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, .entity weaponentity, vect 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; + vector 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)) @@ -69,27 +69,27 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, .entity weaponentity, vect 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'); // TODO this is broken - see 637056bea7bf7f5c9c0fc6113e94731a2767476 for an attempted fix // which fixes issue #1957 but causes #2129 - vector dv = v_right * -vecs.y + v_up * vecs.z; + vector dv = right * -vecs.y + up * vecs.z; w_shotorg = ent.origin + ent.view_ofs + dv; // now move the shotorg forward as much as requested if possible if(antilag) { if(CS(ent).antilag_debug) - tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + v_forward * (vecs.x + nudge), MOVE_NORMAL, ent, CS(ent).antilag_debug); + tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + forward * (vecs.x + nudge), MOVE_NORMAL, ent, CS(ent).antilag_debug); else - tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + v_forward * (vecs.x + nudge), MOVE_NORMAL, ent, ANTILAG_LATENCY(ent)); + tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + forward * (vecs.x + nudge), MOVE_NORMAL, ent, ANTILAG_LATENCY(ent)); } else - tracebox(w_shotorg, mi, ma, w_shotorg + v_forward * (vecs.x + nudge), MOVE_NORMAL, ent); - w_shotorg = trace_endpos - v_forward * nudge; + tracebox(w_shotorg, mi, ma, w_shotorg + forward * (vecs.x + nudge), MOVE_NORMAL, ent); + w_shotorg = trace_endpos - forward * nudge; // calculate the shotdir from the chosen shotorg if(W_DualWielding(ent)) w_shotdir = s_forward; diff --git a/qcsrc/server/weapons/weaponsystem.qc b/qcsrc/server/weapons/weaponsystem.qc index b75881127a..5702c2e3c1 100644 --- a/qcsrc/server/weapons/weaponsystem.qc +++ b/qcsrc/server/weapons/weaponsystem.qc @@ -373,10 +373,6 @@ void weapon_thinkf(entity actor, .entity weaponentity, WFRAME fr, float t, void( 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; @@ -386,10 +382,6 @@ void weapon_thinkf(entity actor, .entity weaponentity, WFRAME fr, float t, void( 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?"); @@ -507,10 +499,8 @@ void W_WeaponFrame(Player actor, .entity weaponentity) 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; + vector fo, ri, up; + MAKE_VECTORS(actor.v_angle, fo, ri, up); // Change weapon if (this.m_weapon != this.m_switchweapon) diff --git a/qcsrc/tools/compilationunits.sh b/qcsrc/tools/compilationunits.sh index e3d1eb0136..68f2eb9d56 100755 --- a/qcsrc/tools/compilationunits.sh +++ b/qcsrc/tools/compilationunits.sh @@ -38,6 +38,7 @@ QCCDEFS="${QCCDEFS[@]}" declare -a QCCFLAGS=( -std=gmqcc + -O3 # optimization to accept variable initialization inside `if (1)` blocks and avoid warnings -Wall -Werror -futf8 -freturn-assignments