diff --git a/.gitignore b/.gitignore index efe312d8..56eec320 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,7 @@ Quake/quakespasm [Rr]elease/ x64/ build/ +build2/ [Bb]in/ [Oo]bj/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e1ab430..bf011cc3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.8) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -project(quakevr VERSION 0.0.5 LANGUAGES CXX) +project(quakevr VERSION 0.0.7 LANGUAGES CXX) set(source_list "Quake/bgmusic.cpp" @@ -58,6 +58,8 @@ set(source_list "Quake/pr_edict.cpp" "Quake/pr_exec.cpp" "Quake/pr_ext.cpp" + "Quake/qcvm.cpp" + "Quake/quakeglm_qvec3.cpp" "Quake/quakeglm.cpp" "Quake/r_alias.cpp" "Quake/r_brush.cpp" @@ -91,6 +93,7 @@ set(source_list "Quake/sv_move.cpp" "Quake/sv_phys.cpp" "Quake/sv_user.cpp" + "Quake/util.cpp" "Quake/view.cpp" "Quake/vr_cvars.cpp" "Quake/vr_showfn.cpp" @@ -129,6 +132,11 @@ endif() add_executable(${QUAKEVR_TARGET_NAME} "${source_list}") set_target_properties(${QUAKEVR_TARGET_NAME} PROPERTIES LINKER_LANGUAGE CXX) +target_precompile_headers( + ${QUAKEVR_TARGET_NAME} PRIVATE + "Quake/pch.hpp" +) + target_compile_features(${QUAKEVR_TARGET_NAME} PUBLIC cxx_std_17) target_compile_options(${QUAKEVR_TARGET_NAME} PRIVATE -Wall -Wextra -Wno-missing-field-initializers -Wpedantic -Wimplicit-fallthrough @@ -189,6 +197,11 @@ set_property(TARGET ${QUAKEVR_TARGET_NAME} PROPERTY CXX_STANDARD 17) include(FindOpenGL) +find_package(Boost 1.36.0 REQUIRED) +if(Boost_FOUND) + include_directories(${Boost_INCLUDE_DIRS}) +endif() + if (WIN32) set(SDL2_LIBRARIES "C:/OHWorkspace/quakevr/Windows/SDL2/lib64/SDL2main.lib" diff --git a/CMakeSettings.json b/CMakeSettings.json new file mode 100644 index 00000000..30030679 --- /dev/null +++ b/CMakeSettings.json @@ -0,0 +1,15 @@ +{ + "configurations": [ + { + "name": "x64-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "clang_cl_x64" ], + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "" + } + ] +} \ No newline at end of file diff --git a/QC/client.qc b/QC/client.qc index 82a7b80d..a90fc3d8 100644 --- a/QC/client.qc +++ b/QC/client.qc @@ -1050,6 +1050,10 @@ void() PutClientInServer = VRSetMainHandGrabbingBit(self, FALSE); VRSetMainHandPrevGrabbingBit(self, FALSE); VRSet2HAiming(self, FALSE); + VRSetOffHandReloadFlickingBit(self, FALSE); + VRSetOffHandPrevReloadFlickingBit(self, FALSE); + VRSetMainHandReloadFlickingBit(self, FALSE); + VRSetMainHandPrevReloadFlickingBit(self, FALSE); self.offhand_forcegrabbing = FALSE; self.mainhand_forcegrabbing = FALSE; diff --git a/QC/frikbot/bot_fight.qc b/QC/frikbot/bot_fight.qc index 1f3a4fb1..608f7cc3 100644 --- a/QC/frikbot/bot_fight.qc +++ b/QC/frikbot/bot_fight.qc @@ -378,6 +378,10 @@ void() bot_setvrfields = VRSetMainHandGrabbingBit(self, TRUE); VRSetMainHandPrevGrabbingBit(self, TRUE); VRSet2HAiming(self, FALSE); + VRSetOffHandReloadFlickingBit(self, TRUE); + VRSetOffHandPrevReloadFlickingBit(self, TRUE); + VRSetMainHandReloadFlickingBit(self, TRUE); + VRSetMainHandPrevReloadFlickingBit(self, TRUE); } void() bot_shoot = diff --git a/QC/items.qc b/QC/items.qc index 46d2d127..6b1c6a09 100644 --- a/QC/items.qc +++ b/QC/items.qc @@ -744,6 +744,11 @@ AMMO void() ammo_touch = { + if (self.model == string_null || self.solid == SOLID_NOT) + { + return; + } + entity stemp; if(self.weapon == AID_SHELLS) @@ -1575,6 +1580,7 @@ void() DropBackpack = item.handtouch = BackpackTouch; MakeGrabbable(item); + item.solid = SOLID_NOT_BUT_TOUCHABLE; item.flags |= FL_FORCEGRABBABLE; diff --git a/QC/pak11.pak b/QC/pak11.pak index c4185917..12316c39 100644 Binary files a/QC/pak11.pak and b/QC/pak11.pak differ diff --git a/QC/vr_defs.qc b/QC/vr_defs.qc index ad0a8e50..924cdb65 100644 --- a/QC/vr_defs.qc +++ b/QC/vr_defs.qc @@ -269,16 +269,20 @@ float QVR_VRFORCEGRABMODE_INSTANT = 3; // Flags for VR bits: `vrbits0` // ---------------------------------------------------------------------------- -float QVR_VRBITS0_TELEPORTING = VRUTIL_POWER_OF_TWO(0); -float QVR_VRBITS0_OFFHAND_GRABBING = VRUTIL_POWER_OF_TWO(1); -float QVR_VRBITS0_OFFHAND_PREVGRABBING = VRUTIL_POWER_OF_TWO(2); -float QVR_VRBITS0_MAINHAND_GRABBING = VRUTIL_POWER_OF_TWO(3); -float QVR_VRBITS0_MAINHAND_PREVGRABBING = VRUTIL_POWER_OF_TWO(4); -float QVR_VRBITS0_2H_AIMING = VRUTIL_POWER_OF_TWO(5); -float QVR_VRBITS0_OFFHAND_RELOADING = VRUTIL_POWER_OF_TWO(6); -float QVR_VRBITS0_OFFHAND_PREVRELOADING = VRUTIL_POWER_OF_TWO(7); -float QVR_VRBITS0_MAINHAND_RELOADING = VRUTIL_POWER_OF_TWO(8); -float QVR_VRBITS0_MAINHAND_PREVRELOADING = VRUTIL_POWER_OF_TWO(9); +float QVR_VRBITS0_TELEPORTING = VRUTIL_POWER_OF_TWO(0); +float QVR_VRBITS0_OFFHAND_GRABBING = VRUTIL_POWER_OF_TWO(1); +float QVR_VRBITS0_OFFHAND_PREVGRABBING = VRUTIL_POWER_OF_TWO(2); +float QVR_VRBITS0_MAINHAND_GRABBING = VRUTIL_POWER_OF_TWO(3); +float QVR_VRBITS0_MAINHAND_PREVGRABBING = VRUTIL_POWER_OF_TWO(4); +float QVR_VRBITS0_2H_AIMING = VRUTIL_POWER_OF_TWO(5); +float QVR_VRBITS0_OFFHAND_RELOADING = VRUTIL_POWER_OF_TWO(6); +float QVR_VRBITS0_OFFHAND_PREVRELOADING = VRUTIL_POWER_OF_TWO(7); +float QVR_VRBITS0_MAINHAND_RELOADING = VRUTIL_POWER_OF_TWO(8); +float QVR_VRBITS0_MAINHAND_PREVRELOADING = VRUTIL_POWER_OF_TWO(9); +float QVR_VRBITS0_OFFHAND_RELOADFLICKING = VRUTIL_POWER_OF_TWO(10); +float QVR_VRBITS0_OFFHAND_PREVRELOADFLICKING = VRUTIL_POWER_OF_TWO(11); +float QVR_VRBITS0_MAINHAND_RELOADFLICKING = VRUTIL_POWER_OF_TWO(12); +float QVR_VRBITS0_MAINHAND_PREVRELOADFLICKING = VRUTIL_POWER_OF_TWO(13); // // diff --git a/QC/vr_handgrabutil.qc b/QC/vr_handgrabutil.qc index 3384bc9c..2a65d891 100644 --- a/QC/vr_handgrabutil.qc +++ b/QC/vr_handgrabutil.qc @@ -12,7 +12,9 @@ void(entity xEntPlayer, float xLastGrabTime, float* xOutLastGrabTime, float xLastReleaseTime, - float* xOutLastReleaseTime) + float* xOutLastReleaseTime, + float xCurrReloadFlickingBit, + float xPrevReloadFlickingBit) VR_HandGrabUtil_Impl_UpdateStateForHand = { if(!xPrevBit && xCurrBit) // Rising edge (grab) @@ -66,7 +68,9 @@ void(entity xEntPlayer) VR_HandGrabUtil_UpdateState = xEntPlayer.offhand_lastgrabtime, &xEntPlayer.offhand_lastgrabtime, xEntPlayer.offhand_lastreleasetime, - &xEntPlayer.offhand_lastreleasetime + &xEntPlayer.offhand_lastreleasetime, + VRGetOffHandReloadFlickingBit(xEntPlayer), + VRGetOffHandPrevReloadFlickingBit(xEntPlayer) ); VR_HandGrabUtil_Impl_UpdateStateForHand( @@ -77,11 +81,12 @@ void(entity xEntPlayer) VR_HandGrabUtil_UpdateState = xEntPlayer.mainhand_lastgrabtime, &xEntPlayer.mainhand_lastgrabtime, xEntPlayer.mainhand_lastreleasetime, - &xEntPlayer.mainhand_lastreleasetime + &xEntPlayer.mainhand_lastreleasetime, + VRGetMainHandReloadFlickingBit(xEntPlayer), + VRGetMainHandPrevReloadFlickingBit(xEntPlayer) ); } - float(entity xEntPlayer, float xHand) VR_HandGrabUtil_IsHandGrabbing = { return VRIsEntHandGrabbingBit(xEntPlayer, xHand); @@ -111,3 +116,13 @@ float(entity xEntPlayer, float xHand) VR_HandGrabUtil_StoppedHandGrabbing = return VRIsEntHandPrevGrabbingBit(xEntPlayer, xHand) && !VRIsEntHandGrabbingBit(xEntPlayer, xHand); } + +float(entity xEntPlayer, float xHand) VR_HandGrabUtil_IsHandReloadFlicking = +{ + return VRIsEntHandReloadFlickingBit(xEntPlayer, xHand); +} + +float(entity xEntPlayer, float xHand) VR_HandGrabUtil_IsHandPrevReloadFlicking = +{ + return VRIsEntHandPrevReloadFlickingBit(xEntPlayer, xHand); +} diff --git a/QC/vr_util.qc b/QC/vr_util.qc index 00413913..b761d9a4 100644 --- a/QC/vr_util.qc +++ b/QC/vr_util.qc @@ -374,6 +374,17 @@ float(entity e, float xHand) VRGetEntForceGrabbing = else return e.mainhand_forcegrabbing; } +float(entity e, float xHand) VRIsEntHandReloadFlickingBit = +{ + if(xHand == cVR_OffHand) return VRGetOffHandReloadFlickingBit(e); + else return VRGetMainHandReloadFlickingBit(e); +} + +float(entity e, float xHand) VRIsEntHandPrevReloadFlickingBit = +{ + if(xHand == cVR_OffHand) return VRGetOffHandPrevReloadFlickingBit(e); + else return VRGetMainHandPrevReloadFlickingBit(e); +} void(entity e, float xHand, float v) VRSetEntForceGrabbing = { @@ -480,6 +491,26 @@ float(entity ent) VRGetMainHandPrevReloadingBit = return VRHasBit(ent.vrbits0, QVR_VRBITS0_MAINHAND_PREVRELOADING); } +float(entity ent) VRGetOffHandReloadFlickingBit = +{ + return VRHasBit(ent.vrbits0, QVR_VRBITS0_OFFHAND_RELOADFLICKING); +} + +float(entity ent) VRGetOffHandPrevReloadFlickingBit = +{ + return VRHasBit(ent.vrbits0, QVR_VRBITS0_OFFHAND_PREVRELOADFLICKING); +} + +float(entity ent) VRGetMainHandReloadFlickingBit = +{ + return VRHasBit(ent.vrbits0, QVR_VRBITS0_MAINHAND_RELOADFLICKING); +} + +float(entity ent) VRGetMainHandPrevReloadFlickingBit = +{ + return VRHasBit(ent.vrbits0, QVR_VRBITS0_MAINHAND_PREVRELOADFLICKING); +} + void(entity ent, float value) VRSetTeleporting = { @@ -531,6 +562,26 @@ void(entity ent, float value) VRSetMainHandPrevReloadingBit = ent.vrbits0 = VRSetBit(ent.vrbits0, QVR_VRBITS0_MAINHAND_PREVRELOADING, value); } +void(entity ent, float value) VRSetOffHandReloadFlickingBit = +{ + ent.vrbits0 = VRSetBit(ent.vrbits0, QVR_VRBITS0_OFFHAND_RELOADFLICKING, value); +} + +void(entity ent, float value) VRSetOffHandPrevReloadFlickingBit = +{ + ent.vrbits0 = VRSetBit(ent.vrbits0, QVR_VRBITS0_OFFHAND_PREVRELOADFLICKING, value); +} + +void(entity ent, float value) VRSetMainHandReloadFlickingBit = +{ + ent.vrbits0 = VRSetBit(ent.vrbits0, QVR_VRBITS0_MAINHAND_RELOADFLICKING, value); +} + +void(entity ent, float value) VRSetMainHandPrevReloadFlickingBit = +{ + ent.vrbits0 = VRSetBit(ent.vrbits0, QVR_VRBITS0_MAINHAND_PREVRELOADFLICKING, value); +} + float() VRIsWeaponReloadingEnabled = { return (cvar_hget(cvarh_vr_reload_mode) != QVR_RELOADMODE_NONE) && @@ -543,3 +594,10 @@ float(entity ent, float xHand) VRIsWeaponReloadingEnabledFor = VRIsWeaponReloadingEnabled() && WeaponIdToSupportsReload(VRGetWeapon(xHand)); } + +float(entity ent, float xHand) VRIsWeaponReloadFlickingEnabledFor = +{ + return ent.ishuman && + VRIsWeaponReloadingEnabled() && + WeaponIdToSupportsReloadFlicking(VRGetWeapon(xHand)); +} diff --git a/QC/vr_weaponutil.qc b/QC/vr_weaponutil.qc index 89fd5104..a17d3347 100644 --- a/QC/vr_weaponutil.qc +++ b/QC/vr_weaponutil.qc @@ -412,6 +412,26 @@ float(float wid) WeaponIdToSupportsReload = return -1; } +float(float wid) WeaponIdToSupportsReloadFlicking = +{ + if(wid == WID_FIST) { return FALSE; } + if(wid == WID_GRAPPLE) { return FALSE; } + if(wid == WID_AXE) { return FALSE; } + if(wid == WID_MJOLNIR) { return FALSE; } + if(wid == WID_SHOTGUN) { return FALSE; } + if(wid == WID_SUPER_SHOTGUN) { return TRUE; } + if(wid == WID_NAILGUN) { return FALSE; } + if(wid == WID_SUPER_NAILGUN) { return FALSE; } + if(wid == WID_GRENADE_LAUNCHER) { return FALSE; } + if(wid == WID_PROXIMITY_GUN) { return FALSE; } + if(wid == WID_ROCKET_LAUNCHER) { return FALSE; } + if(wid == WID_LIGHTNING) { return FALSE; } + if(wid == WID_LASER_CANNON) { return FALSE; } + + ASSERT(FALSE); + return -1; +} + float(float wid) WeaponIdToBaseClipSize = { if(wid == WID_FIST) { return 0; } diff --git a/QC/vrprogs.dat b/QC/vrprogs.dat index a07a3174..34fd44e8 100644 Binary files a/QC/vrprogs.dat and b/QC/vrprogs.dat differ diff --git a/QC/weapons.qc b/QC/weapons.qc index a064e66a..82051e51 100644 --- a/QC/weapons.qc +++ b/QC/weapons.qc @@ -3346,13 +3346,15 @@ void() wpnthrow_stabilize = void() forcegrabbable_think_impl = { - if(self.throwhit == QVR_THROWHIT_FORCEGRAB && - time > GetThrownWeaponForcegrabTime(self) + 0.4) + if(self.throwhit == QVR_THROWHIT_FORCEGRAB) { - // After a long linear forcegrab, restore the movement type to "toss". + if(time > GetThrownWeaponForcegrabTime(self) + 0.4) + { + // After a long linear forcegrab, restore the movement type to "toss". - self.throwhit = QVR_THROWHIT_NEVER_HIT; - self.movetype = MOVETYPE_TOSS; + self.throwhit = QVR_THROWHIT_NEVER_HIT; + self.movetype = MOVETYPE_TOSS; + } } if(self.throwhit == QVR_THROWHIT_FORCEGRAB_PARABOLA) @@ -3361,35 +3363,54 @@ void() forcegrabbable_think_impl = self.velocity += normalize(handDiff); } - if(self.waterlevel == 1) + if(self.waterlevel >= 1) { - if(fabs(self.velocity_x) > 10) + if(self.ammocounter < 2) { - self.velocity_x *= 0.85; + self.ammocounter += 1; } - else + else if (self.ammocounter > 0) { - self.velocity_x = 0; + self.ammocounter -= 1; } - if(fabs(self.velocity_y) > 10) + if(self.ammocounter > 1) { - self.velocity_y *= 0.85; - } - else - { - self.velocity_y = 0; - } + if(fabs(self.velocity_x) > 10) + { + self.velocity_x *= 0.85; + } + else + { + self.velocity_x = 0; + } - self.velocity_z = 45; - self.flags = self.flags | FL_INWATER; - self.throwhit = QVR_THROWHIT_HIT; - self.solid = SOLID_NOT_BUT_TOUCHABLE; - self.avelocity = '0 0 0'; + if(fabs(self.velocity_y) > 10) + { + self.velocity_y *= 0.85; + } + else + { + self.velocity_y = 0; + } + + self.velocity_z = 45; + self.flags = self.flags | FL_INWATER; + self.throwhit = QVR_THROWHIT_HIT; + self.solid = SOLID_NOT_BUT_TOUCHABLE; + self.avelocity = '0 0 0'; + } } else if((time - self.lastwatertime) > 0.15) { self.flags = self.flags & ~FL_INWATER; + self.ammocounter = 0; + self.waterlevel = 0; + } + else if (self.ammocounter > 0) + { + self.ammocounter -= 1; + self.waterlevel = 0; } if(cvar_hget(cvarh_vr_weapondrop_particles) && (self.flags & (FL_ONGROUND | FL_INWATER))) @@ -3806,6 +3827,7 @@ void MakeThrown(entity newmis, float xBaseDamage) { MakeGrabbable(newmis); + newmis.solid = SOLID_NOT_BUT_TOUCHABLE; SetThrownWeaponDisappearOnHit(newmis, xDisappearOnHit); SetThrownWeaponDealDamage(newmis, xDealDamage); @@ -3832,6 +3854,8 @@ void MakeThrown(entity newmis, + tmp_handavel_y * v_right * -30 + tmp_handavel_z * v_up * -30; + newmis.waterlevel = 0; + newmis.ammocounter = 0; // water frame counter newmis.think = wpnthrow_think; newmis.nextthink = time + 0.02; @@ -4063,6 +4087,8 @@ void(entity ent, float xHand, float otherHandEmpty = VRIsHandEmpty(ent, VRGetOtherHand(xHand)); float triggerPressed = VRGetEntFireButtonPressed(ent, xHand); float startedHandGrabbing = VR_HandGrabUtil_StartedHandGrabbing(ent, xHand); + float handReloadFlicking = VR_HandGrabUtil_IsHandReloadFlicking(ent, xHand); + float handPrevReloadFlicking = VR_HandGrabUtil_IsHandPrevReloadFlicking(ent, xHand); vector handPos = VRGetHandPos(xHand); vector handRot = VRGetHandRot(xHand); @@ -4159,6 +4185,13 @@ void(entity ent, float xHand, VRTryReloadWeapon(ent, xHand, xWeapon, xWeaponFlags, xWeaponClip, xOutWeaponClip); } } + else if(handReloadFlicking) + { + if(VRIsWeaponReloadingEnabledFor(ent, xHand) && VRIsWeaponReloadFlickingEnabledFor(ent, xHand)) + { + VRTryReloadWeapon(ent, xHand, xWeapon, xWeaponFlags, xWeaponClip, xOutWeaponClip); + } + } } // Not holding a weapon, grabbing the controller, and pressing the trigger. else if(handEmpty && triggerPressed) diff --git a/Quake/.clang-tidy b/Quake/.clang-tidy index be5f60b1..e69de29b 100644 --- a/Quake/.clang-tidy +++ b/Quake/.clang-tidy @@ -1 +0,0 @@ -Checks: 'modernize-avoid-bind,modernize-avoid-c-arrays,modernize-concat-nested-namespaces,modernize-deprecated-headers,modernize-deprecated-ios-base-aliases,modernize-loop-convert,modernize-make-shared,modernize-make-unique,modernize-pass-by-value,modernize-raw-string-literal,modernize-redundant-void-arg,modernize-replace-auto-ptr,modernize-replace-random-shuffle,modernize-return-braced-init-list,modernize-shrink-to-fit,modernize-unary-static-assert,modernize-use-auto,modernize-use-bool-literals,modernize-use-default-member-init,modernize-use-emplace,modernize-use-equals-default,modernize-use-equals-delete,modernize-use-nodiscard,modernize-use-noexcept,modernize-use-nullptr,modernize-use-override,modernize-use-trailing-return-type,modernize-use-transparent-functors,modernize-use-uncaught-exceptions,modernize-use-using,readability-avoid-const-params-in-decls,readability-braces-around-statements,readability-const-return-type,readability-container-size-empty,readability-convert-member-functions-to-static,readability-deleted-default,readability-delete-null-pointer,readability-else-after-return,readability-identifier-naming,readability-implicit-bool-conversion,readability-inconsistent-declaration-parameter-name,readability-isolate-declaration,readability-magic-numbers,readability-misleading-indentation,readability-misplaced-array-index,readability-named-parameter,readability-non-const-parameter,readability-redundant-control-flow,readability-redundant-declaration,readability-redundant-function-ptr-dereference,readability-redundant-member-init,readability-redundant-preprocessor,readability-redundant-smartptr-get,readability-redundant-string-cstr,readability-redundant-string-init,readability-simplify-boolean-expr,readability-simplify-subscript-expr,readability-static-accessed-through-instance,readability-static-definition-in-anonymous-namespace,readability-string-compare,readability-uniqueptr-delete-release,readability-uppercase-literal-suffix' \ No newline at end of file diff --git a/Quake/cl_input.cpp b/Quake/cl_input.cpp index d5e429e7..b0a10dbd 100644 --- a/Quake/cl_input.cpp +++ b/Quake/cl_input.cpp @@ -67,7 +67,7 @@ kbutton_t in_strafe, in_speed, in_use, in_jump, in_attack, in_offhandattack, in_button3, in_button4, in_button5, in_button6, in_button7, in_button8; kbutton_t in_up, in_down; kbutton_t in_grableft, in_grabright; -kbutton_t in_reloadleft, in_reloadright; +kbutton_t in_reloadleft, in_reloadright, in_flickreloadleft, in_flickreloadright; int in_impulse; @@ -598,16 +598,16 @@ void CL_SendMove(const usercmd_t* cmd) MSG_WriteFloat(&buf, cl.mtime[0]); // so server can get ping times - const auto writeAngles = [&](const auto& angles) { + const auto writeAngles = [&](const auto& angles) + { for(int i = 0; i < 3; i++) { MSG_WriteAngle16(&buf, angles[i], cl.protocolflags); } }; - const auto writeVec = [&](const auto& vec) { - MSG_WriteVec3(&buf, vec, cl.protocolflags); - }; + const auto writeVec = [&](const auto& vec) + { MSG_WriteVec3(&buf, vec, cl.protocolflags); }; // aimangles writeAngles(cl.aimangles); @@ -798,4 +798,8 @@ void CL_InitInput() Cmd_AddCommand("-reloadleft", [] { KeyUp(&in_reloadleft); }); Cmd_AddCommand("+reloadright", [] { KeyDown(&in_reloadright); }); Cmd_AddCommand("-reloadright", [] { KeyUp(&in_reloadright); }); + Cmd_AddCommand("+flickreloadleft", [] { KeyDown(&in_flickreloadleft); }); + Cmd_AddCommand("-flickreloadleft", [] { KeyUp(&in_flickreloadleft); }); + Cmd_AddCommand("+flickreloadright", [] { KeyDown(&in_flickreloadright); }); + Cmd_AddCommand("-flickreloadright", [] { KeyUp(&in_flickreloadright); }); } diff --git a/Quake/cl_main.cpp b/Quake/cl_main.cpp index e32be475..65752715 100644 --- a/Quake/cl_main.cpp +++ b/Quake/cl_main.cpp @@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.hpp" #include "host.hpp" #include "bgmusic.hpp" +#include "server.hpp" #include "vr.hpp" #include "util.hpp" #include "cmd.hpp" diff --git a/Quake/cl_parse.cpp b/Quake/cl_parse.cpp index 3cd9a336..89e2bc25 100644 --- a/Quake/cl_parse.cpp +++ b/Quake/cl_parse.cpp @@ -1824,7 +1824,8 @@ static void CL_ParseUpdate(int bits) const auto doIt = [&](const auto fn, const int bit, auto& target, - const auto& baselineData, const int index) { + const auto& baselineData, const int index) + { if(bits & bit) { target[index] = fn(cl.protocolflags); @@ -3320,8 +3321,9 @@ void CL_ParseServerMessage() case svcfte_cgamepacket: if(cl.qcvm.extfuncs.CSQC_Parse_Event) { - QCVMGuard qg{&cl.qcvm}; + PR_SwitchQCVM(&cl.qcvm); PR_ExecuteProgram(cl.qcvm.extfuncs.CSQC_Parse_Event); + PR_SwitchQCVM(nullptr); } else { diff --git a/Quake/cl_tent.cpp b/Quake/cl_tent.cpp index 60805b82..516947af 100644 --- a/Quake/cl_tent.cpp +++ b/Quake/cl_tent.cpp @@ -74,7 +74,8 @@ beam_t* CL_ParseBeam(qmodel_t* m) const auto start = MSG_ReadVec3(cl.protocolflags); const auto end = MSG_ReadVec3(cl.protocolflags); - const auto initBeam = [&](beam_t& b) { + const auto initBeam = [&](beam_t& b) + { b.entity = ent; b.disambiguator = disambiguator; b.model = m; @@ -247,7 +248,9 @@ void CL_ParseTEnt() case TE_LIGHTNING1: // lightning bolts (shambler) { - if(beam_t* b = CL_ParseBeam(Mod_ForName("progs/bolt.mdl", true))) + static qmodel_t* model = Mod_ForName("progs/bolt.mdl", true); + + if(beam_t* b = CL_ParseBeam(model)) { b->spin = true; } @@ -257,7 +260,8 @@ void CL_ParseTEnt() case TE_LIGHTNING2: // lightning bolts (lighting gun, mjolnir, gremlin) { - qmodel_t* model = Mod_ForName("progs/bolt2.mdl", true); + static qmodel_t* model = Mod_ForName("progs/bolt2.mdl", true); + auto* hdr = (aliashdr_t*)Mod_Extradata(model); hdr->scale_origin = hdr->original_scale_origin * 0.5_qf; hdr->scale = hdr->original_scale * 0.5_qf; @@ -275,7 +279,9 @@ void CL_ParseTEnt() case TE_LIGHTNING3: // lightning bolts (boss) { - if(beam_t* b = CL_ParseBeam(Mod_ForName("progs/bolt3.mdl", true))) + static qmodel_t* model = Mod_ForName("progs/bolt3.mdl", true); + + if(beam_t* b = CL_ParseBeam(model)) { b->spin = true; } @@ -286,19 +292,24 @@ void CL_ParseTEnt() // PGM 01/21/97 case TE_BEAM: // grappling hook beam { - qmodel_t* model = Mod_ForName("progs/beam.mdl", true); - auto* hdr = (aliashdr_t*)Mod_Extradata(model); - hdr->scale_origin = hdr->original_scale_origin * 0.25_qf; - hdr->scale = hdr->original_scale * 0.25_qf; + static qmodel_t* model = Mod_ForName("progs/beam.mdl", true); + static auto* hdr = [] + { + auto* hdr = (aliashdr_t*)Mod_Extradata(model); + hdr->scale_origin = hdr->original_scale_origin * 0.25_qf; + hdr->scale = hdr->original_scale * 0.25_qf; + + hdr->scale[0] = hdr->original_scale[0] * 0.12_qf; + hdr->scale_origin[0] = hdr->original_scale_origin[0] * 0.12_qf; + return hdr; + }(); - hdr->scale[0] = hdr->original_scale[0] * 0.12_qf; - hdr->scale_origin[0] = hdr->original_scale_origin[0] * 0.12_qf; + static const auto scaleRatioX = + hdr->scale[0] / hdr->original_scale[0]; if(beam_t* b = CL_ParseBeam(model)) { b->spin = false; - - const auto scaleRatioX = hdr->scale[0] / hdr->original_scale[0]; b->scaleRatioX = scaleRatioX; } @@ -482,9 +493,9 @@ void CL_UpdateTEnts() ent->origin = org; ent->model = b.model; - ent->angles[0] = pitch; - ent->angles[1] = yaw; - ent->angles[2] = b.spin ? rand() % 360 : 0; + ent->angles[PITCH] = pitch; + ent->angles[YAW] = yaw; + ent->angles[ROLL] = b.spin ? rand() % 360 : 0; // johnfitz -- use j instead of using i twice, so we don't corrupt // memory diff --git a/Quake/client.hpp b/Quake/client.hpp index 12f66af8..645cc186 100644 --- a/Quake/client.hpp +++ b/Quake/client.hpp @@ -198,6 +198,7 @@ struct client_state_t float handvelmag[2]; qvec3 handavel[2]; qvec3 headvel; + qvec3 visual_handrot[2]; qvec3 mvelocity[2]; // update by server, used for lean+bob // (0 is newest) @@ -418,10 +419,12 @@ bool anyViewmodel(client_state_t& clientState, F&& f) template void forAllViewmodels(client_state_t& clientState, F&& f) { - anyViewmodel(clientState, [&](entity_t& e) { - f(e); - return false; - }); + anyViewmodel(clientState, + [&](entity_t& e) + { + f(e); + return false; + }); } @@ -510,7 +513,7 @@ extern kbutton_t in_mlook, in_klook; extern kbutton_t in_strafe; extern kbutton_t in_speed; extern kbutton_t in_grableft, in_grabright; -extern kbutton_t in_reloadleft, in_reloadright; +extern kbutton_t in_reloadleft, in_reloadright, in_flickreloadleft, in_flickreloadright; void CL_InitInput(); void CL_AccumulateCmd(); // QSS @@ -546,7 +549,6 @@ void CL_TimeDemo_f(); // void CL_ParseServerMessage(); void CL_RegisterParticles(); // QSS -void CL_NewTranslation(int slot); // // view diff --git a/Quake/cmd.cpp b/Quake/cmd.cpp index d680cad3..f1cf5069 100644 --- a/Quake/cmd.cpp +++ b/Quake/cmd.cpp @@ -964,7 +964,7 @@ bool Cmd_ExecuteString(const char* text, cmd_source_t src) { if(cl.qcvm.extfuncs.CSQC_ConsoleCommand) { - QCVMGuard qg{&cl.qcvm}; + PR_SwitchQCVM(&cl.qcvm); G_INT(OFS_PARM0) = PR_MakeTempString(text); PR_ExecuteProgram(cl.qcvm.extfuncs.CSQC_ConsoleCommand); @@ -974,6 +974,7 @@ bool Cmd_ExecuteString(const char* text, cmd_source_t src) Con_Printf("gamecode cannot \"%s\"\n", Cmd_Argv(0)); } + PR_SwitchQCVM(nullptr); return ret; } else diff --git a/Quake/common.cpp b/Quake/common.cpp index 9e74a1a9..4d84ba69 100644 --- a/Quake/common.cpp +++ b/Quake/common.cpp @@ -52,6 +52,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #ifdef _WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + #include #include #include diff --git a/Quake/debugprint.hpp b/Quake/debugprint.hpp new file mode 100644 index 00000000..d4d6f749 --- /dev/null +++ b/Quake/debugprint.hpp @@ -0,0 +1,37 @@ +#pragma once + +#ifdef WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include +#include "debugapi.h" + +#undef min +#undef max +#endif + +#include "stringcat.hpp" + +namespace quake::util +{ + +template +void debugPrint([[maybe_unused]] const Ts&... xs) +{ +#ifdef WIN32 + OutputDebugStringA(stringCat(xs...).data()); +#endif +} + +template +void debugPrintSeparated([[maybe_unused]] const std::string_view separator, + [[maybe_unused]] const Ts&... xs) +{ +#ifdef WIN32 + OutputDebugStringA(stringCatSeparated(separator, xs...).data()); +#endif +} + +} // namespace quake::util diff --git a/Quake/fs_zip.cpp b/Quake/fs_zip.cpp index 5f717cf4..57b203ec 100644 --- a/Quake/fs_zip.cpp +++ b/Quake/fs_zip.cpp @@ -831,7 +831,7 @@ pack_t* FSZIP_LoadArchive(const char* packfile) numpackfiles = 0; newfiles = nullptr; - newfiles = (packfile_t*) Z_Malloc(sizeof(*newfiles) * zip.numfiles); + newfiles = (packfile_t*)Z_Malloc(sizeof(*newfiles) * zip.numfiles); for(numpackfiles = 0, i = 0; i < zip.numfiles; i++) { qofs_t startpos, datasize; diff --git a/Quake/gl_model.cpp b/Quake/gl_model.cpp index 399c4612..e8e58bc3 100644 --- a/Quake/gl_model.cpp +++ b/Quake/gl_model.cpp @@ -28,8 +28,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include "host.hpp" +#include "mathlib.hpp" #include "quakedef.hpp" -#include "util.hpp" +#include "common.hpp" #include "quakeglm_qvec3.hpp" #include "quakeglm_qvec3_togl.hpp" #include "console.hpp" @@ -38,6 +39,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "glquake.hpp" #include "byteorder.hpp" #include "gl_texmgr.hpp" +#include "server.hpp" #include "sys.hpp" #include "srcformat.hpp" diff --git a/Quake/gl_rmain.cpp b/Quake/gl_rmain.cpp index 43b66131..da0550a2 100644 --- a/Quake/gl_rmain.cpp +++ b/Quake/gl_rmain.cpp @@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.hpp" #include "quakedef_macros.hpp" #include "quakeglm_qvec3.hpp" +#include "server.hpp" #include "vr.hpp" #include "vr_showfn.hpp" #include "vr_cvars.hpp" @@ -548,18 +549,7 @@ to turn away from side, use a negative angle =============== */ #define DEG2RAD(a) ((a)*M_PI_DIV_180) -[[nodiscard]] qvec3 TurnVector( - const qvec3& forward, const qvec3& side, const float angle) noexcept -{ - const float scale_forward = cos(DEG2RAD(angle)); - const float scale_side = sin(DEG2RAD(angle)); - - qvec3 res; - res[0] = scale_forward * forward[0] + scale_side * side[0]; - res[1] = scale_forward * forward[1] + scale_side * side[1]; - res[2] = scale_forward * forward[2] + scale_side * side[2]; - return res; -} + /* =============== @@ -851,7 +841,8 @@ void R_DrawWorldText() // TODO VR: (P1) cleanup and optimize const auto drawCharacterQuad = [](const qvec3& pos, const qvec3& hInc, - const qvec3& zInc, const char num) { + const qvec3& zInc, const char num) + { const int row = num >> 4; const int col = num & 15; @@ -859,9 +850,8 @@ void R_DrawWorldText() const float fcol = col * 0.0625; const float size = 0.0625; - const auto doVertex = [&](const qvec3& p) { - glVertex3f(p.x, p.y, p.z); - }; + const auto doVertex = [&](const qvec3& p) + { glVertex3f(p.x, p.y, p.z); }; glTexCoord2f(fcol, frow); doVertex(pos); @@ -876,9 +866,9 @@ void R_DrawWorldText() doVertex(pos + zInc); }; - const auto forSplitStringView = [](const std::string_view str, - const std::string_view delims, - auto&& f) { + const auto forSplitStringView = + [](const std::string_view str, const std::string_view delims, auto&& f) + { for(auto first = str.data(), second = str.data(), last = first + str.size(); second != last && first != last; first = second + 1) @@ -895,7 +885,8 @@ void R_DrawWorldText() const auto drawString = [&](const qvec3& originalpos, const qvec3& angles, const std::string_view str, - const WorldText::HAlign hAlign) { + const WorldText::HAlign hAlign) + { static std::vector lines; // Split into lines @@ -911,9 +902,8 @@ void R_DrawWorldText() // Find longest line size (for centering) const std::size_t longestLineSize = std::max_element(lines.begin(), lines.end(), - [](const std::string_view& a, const std::string_view& b) { - return a.size() < b.size(); - })->size(); + [](const std::string_view& a, const std::string_view& b) + { return a.size() < b.size(); })->size(); // Angles and offsets const auto [fwd, right, up] = quake::util::getAngledVectors(angles); @@ -934,7 +924,8 @@ void R_DrawWorldText() { const std::size_t sizeDiff = longestLineSize - line.size(); - auto startPos = [&] { + auto startPos = [&] + { if(hAlign == WorldText::HAlign::Left) { return center + (zInc * static_cast(iLine)); @@ -1050,7 +1041,8 @@ void R_DrawString(const qvec3& originalpos, const qvec3& angles, // TODO VR: (P1) cleanup and optimize const auto drawCharacterQuad = [](const qvec3& pos, const qvec3& hInc, - const qvec3& zInc, const char num) { + const qvec3& zInc, const char num) + { const int row = num >> 4; const int col = num & 15; @@ -1058,9 +1050,8 @@ void R_DrawString(const qvec3& originalpos, const qvec3& angles, const float fcol = col * 0.0625; const float size = 0.0625; - const auto doVertex = [&](const qvec3& p) { - glVertex3f(p.x, p.y, p.z); - }; + const auto doVertex = [&](const qvec3& p) + { glVertex3f(p.x, p.y, p.z); }; glTexCoord2f(fcol, frow); doVertex(pos); @@ -1075,9 +1066,9 @@ void R_DrawString(const qvec3& originalpos, const qvec3& angles, doVertex(pos + zInc); }; - const auto forSplitStringView = [](const std::string_view str, - const std::string_view delims, - auto&& f) { + const auto forSplitStringView = + [](const std::string_view str, const std::string_view delims, auto&& f) + { for(auto first = str.data(), second = str.data(), last = first + str.size(); second != last && first != last; first = second + 1) @@ -1092,7 +1083,8 @@ void R_DrawString(const qvec3& originalpos, const qvec3& angles, } }; - const auto drawString = [&] { + const auto drawString = [&] + { static std::vector lines; // Split into lines @@ -1108,9 +1100,8 @@ void R_DrawString(const qvec3& originalpos, const qvec3& angles, // Find longest line size (for centering) const std::size_t longestLineSize = std::max_element(lines.begin(), lines.end(), - [](const std::string_view& a, const std::string_view& b) { - return a.size() < b.size(); - })->size(); + [](const std::string_view& a, const std::string_view& b) + { return a.size() < b.size(); })->size(); // Angles and offsets const auto [fwd, right, up] = quake::util::getAngledVectors(angles); @@ -1131,7 +1122,8 @@ void R_DrawString(const qvec3& originalpos, const qvec3& angles, { const std::size_t sizeDiff = longestLineSize - line.size(); - auto startPos = [&] { + auto startPos = [&] + { if(hAlign == WorldText::HAlign::Left) { return center + (zInc * static_cast(iLine)); @@ -1246,10 +1238,9 @@ void R_ShowBoundingBoxes() qcvm_t* oldvm = qcvm; PR_SwitchQCVM(nullptr); + PR_SwitchQCVM(&sv.qcvm); { - QCVMGuard qg{&sv.qcvm}; - int i; edict_t* ed; for(i = 0, ed = NEXT_EDICT(qcvm->edicts); i < qcvm->num_edicts; @@ -1290,6 +1281,7 @@ void R_ShowBoundingBoxes() } } + PR_SwitchQCVM(nullptr); PR_SwitchQCVM(oldvm); glColor3f(1, 1, 1); @@ -1351,7 +1343,8 @@ void R_ShowTris() } } - const auto doViewmodel = [&](entity_t& ent) { + const auto doViewmodel = [&](entity_t& ent) + { currententity = &ent; if(r_drawviewmodel.value && !chase_active.value && cl.stats[STAT_HEALTH] > 0 && !(cl.items & IT_INVISIBILITY) && @@ -1432,7 +1425,8 @@ void R_DrawShadows() } // TODO VR: (P1) viewent shadow looks weird - const auto drawViewentShadow = [](entity_t& ent) { + const auto drawViewentShadow = [](entity_t& ent) + { if(ent.model != nullptr) { currententity = &ent; @@ -1519,32 +1513,33 @@ void R_RenderScene() // VR: This is what draws the floating ammo text attached to weapons. const auto drawWeaponAmmoText = [](const textentity_t& textEnt, const int statClipIdx, - const int statClipSizeIdx, const int statAmmoCounterIdx) { - if(textEnt.hidden) - { - return; - } + const int statClipSizeIdx, const int statAmmoCounterIdx) + { + if(textEnt.hidden) + { + return; + } - qvec3 angles = textEnt.angles; - angles[PITCH] -= 180.f; - angles[ROLL] *= -1.f; + qvec3 angles = textEnt.angles; + angles[PITCH] -= 180.f; + angles[ROLL] *= -1.f; - char buf[64]; + char buf[64]; - if(quake::vr::get_weapon_reloading_enabled() && - cl.stats[statClipSizeIdx] != 0) - { - sprintf(buf, "%d/%d\n%d", cl.stats[statClipIdx], - cl.stats[statClipSizeIdx], cl.stats[statAmmoCounterIdx]); - } - else - { - sprintf(buf, "%d", cl.stats[statAmmoCounterIdx]); - } + if(quake::vr::get_weapon_reloading_enabled() && + cl.stats[statClipSizeIdx] != 0) + { + sprintf(buf, "%d/%d\n%d", cl.stats[statClipIdx], + cl.stats[statClipSizeIdx], cl.stats[statAmmoCounterIdx]); + } + else + { + sprintf(buf, "%d", cl.stats[statAmmoCounterIdx]); + } - R_DrawString(textEnt.origin, angles, buf, WorldText::HAlign::Center, - 0.10f * textEnt.scale); - }; + R_DrawString(textEnt.origin, angles, buf, WorldText::HAlign::Center, + 0.10f * textEnt.scale); + }; if(vr_show_weapon_text.value) { @@ -1575,7 +1570,8 @@ void R_RenderScene() R_DrawViewModel(&cl.right_upper_holster); // VR: This is what draws the hands. - const auto drawHand = [](auto& handEntities) { + const auto drawHand = [](auto& handEntities) + { R_DrawViewModel(&handEntities.base); R_DrawViewModel(&handEntities.f_thumb); R_DrawViewModel(&handEntities.f_index); diff --git a/Quake/gl_rmisc.cpp b/Quake/gl_rmisc.cpp index f91b0b17..78e90d23 100644 --- a/Quake/gl_rmisc.cpp +++ b/Quake/gl_rmisc.cpp @@ -359,24 +359,24 @@ void R_TranslateNewPlayerSkin(int playernum) if(paliashdr->numskins) { - // TODO: move these tests to the place where skinnum gets received from - // the server - if(skinnum < 0 || skinnum >= paliashdr->numskins) - { - Con_DPrintf("(%d): Invalid player skin #%d\n", playernum, skinnum); - skinnum = 0; - } + // TODO: move these tests to the place where skinnum gets received from + // the server + if(skinnum < 0 || skinnum >= paliashdr->numskins) + { + Con_DPrintf("(%d): Invalid player skin #%d\n", playernum, skinnum); + skinnum = 0; + } - pixels = (byte*)paliashdr + - paliashdr->texels[skinnum]; // This is not a persistent place! + pixels = (byte*)paliashdr + + paliashdr->texels[skinnum]; // This is not a persistent place! - // upload new image - q_snprintf(name, sizeof(name), "player_%i", playernum); - playertextures[playernum] = TexMgr_LoadImage(currententity->model, name, - paliashdr->skinwidth, paliashdr->skinheight, SRC_INDEXED, pixels, - paliashdr->gltextures[skinnum][0]->source_file, - paliashdr->gltextures[skinnum][0]->source_offset, - TEXPREF_PAD | TEXPREF_OVERWRITE); + // upload new image + q_snprintf(name, sizeof(name), "player_%i", playernum); + playertextures[playernum] = TexMgr_LoadImage(currententity->model, name, + paliashdr->skinwidth, paliashdr->skinheight, SRC_INDEXED, pixels, + paliashdr->gltextures[skinnum][0]->source_file, + paliashdr->gltextures[skinnum][0]->source_offset, + TEXPREF_PAD | TEXPREF_OVERWRITE); } else { diff --git a/Quake/gl_screen.cpp b/Quake/gl_screen.cpp index 9bc95afa..3bffb0a3 100644 --- a/Quake/gl_screen.cpp +++ b/Quake/gl_screen.cpp @@ -575,11 +575,10 @@ void SCR_Conwidth_f(cvar_t* var) (void)var; vid.recalc_refdef = 1; - vid.conwidth = (scr_conwidth.value > 0) - ? (int)scr_conwidth.value - : (scr_conscale.value > 0) - ? (int)(vid.width / scr_conscale.value) - : vid.width; + vid.conwidth = (scr_conwidth.value > 0) ? (int)scr_conwidth.value + : (scr_conscale.value > 0) + ? (int)(vid.width / scr_conscale.value) + : vid.width; vid.conwidth = CLAMP(320, vid.conwidth, vid.width); vid.conwidth &= 0xFFFFFFF8; vid.conheight = vid.conwidth * vid.height / vid.width; @@ -1461,13 +1460,19 @@ void SCR_UpdateScreen() // SCR_SetUpToDrawConsole(); + VR_UpdateFlick(); + if(vr_enabled.value && !con_forcedup) { // TODO VR: (P2) this is client side, but does use server logic. Should // be split accordingly and cleaned up. - QCVMGuard qg{&sv.qcvm}; + qcvm_t* oldvm = qcvm; + PR_SwitchQCVM(&sv.qcvm); + VR_UpdateScreenContent(); // phoboslab + + PR_SwitchQCVM(oldvm); } else { diff --git a/Quake/gl_vidsdl.cpp b/Quake/gl_vidsdl.cpp index 0671d05e..86f4c11f 100644 --- a/Quake/gl_vidsdl.cpp +++ b/Quake/gl_vidsdl.cpp @@ -788,11 +788,10 @@ static void VID_Restart() TexMgr_RecalcWarpImageSize(); // conwidth and conheight need to be recalculated - vid.conwidth = (scr_conwidth.value > 0) - ? (int)scr_conwidth.value - : (scr_conscale.value > 0) - ? (int)(vid.width / scr_conscale.value) - : vid.width; + vid.conwidth = (scr_conwidth.value > 0) ? (int)scr_conwidth.value + : (scr_conscale.value > 0) + ? (int)(vid.width / scr_conscale.value) + : vid.width; vid.conwidth = CLAMP(320, vid.conwidth, vid.width); vid.conwidth &= 0xFFFFFFF8; vid.conheight = vid.conwidth * vid.height / vid.width; @@ -1103,11 +1102,11 @@ static void GL_CheckExtensions() Con_Warning("texture_non_power_of_two not supported\n"); } - gl_texture_s3tc = GLEW_EXT_texture_compression_s3tc; - gl_texture_rgtc = GLEW_ARB_texture_compression_rgtc; - gl_texture_bptc = GLEW_EXT_texture_compression_bptc; - gl_texture_etc2 = GLEW_ARB_ES3_compatibility; - gl_texture_astc = GLEW_KHR_texture_compression_astc_ldr; + gl_texture_s3tc = GLEW_EXT_texture_compression_s3tc; + gl_texture_rgtc = GLEW_ARB_texture_compression_rgtc; + gl_texture_bptc = GLEW_EXT_texture_compression_bptc; + gl_texture_etc2 = GLEW_ARB_ES3_compatibility; + gl_texture_astc = GLEW_KHR_texture_compression_astc_ldr; // GLSL if(COM_CheckParm("-noglsl")) diff --git a/Quake/glquake.hpp b/Quake/glquake.hpp index 567b70ef..8067a1c0 100644 --- a/Quake/glquake.hpp +++ b/Quake/glquake.hpp @@ -411,7 +411,8 @@ void R_CullSurfaces(); bool R_CullBox(const qvec3& emins, const qvec3& emaxs); void R_StoreEfrags(efrag_t** ppefrag); bool R_CullModelForEntity(entity_t* e); -void R_RotateForEntity(const qvec3& origin, const qvec3& angles, unsigned char scale); +void R_RotateForEntity( + const qvec3& origin, const qvec3& angles, unsigned char scale); void R_MarkLights( dlight_t* light, const qvec3& lightorg, int num, mnode_t* node); diff --git a/Quake/host.cpp b/Quake/host.cpp index d6a9efb6..20d090a6 100644 --- a/Quake/host.cpp +++ b/Quake/host.cpp @@ -26,7 +26,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "host.hpp" #include "quakedef.hpp" #include "bgmusic.hpp" -#include #include "vr.hpp" #include "vr_cvars.hpp" #include "cmd.hpp" @@ -56,6 +55,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "developer.hpp" #include "qcvm.hpp" +#include +#include + /* A server can allways be started, even if the system started out as a client @@ -585,12 +587,17 @@ void SV_DropClient(bool crash) { // call the prog function for removing a client // this will set the body to a dead frame, among other things - QCVMGuardForce qgf{&sv.qcvm}; + qcvm_t* oldvm = qcvm; + PR_SwitchQCVM(nullptr); + PR_SwitchQCVM(&sv.qcvm); saveSelf = pr_global_struct->self; pr_global_struct->self = EDICT_TO_PROG(host_client->edict); PR_ExecuteProgram(pr_global_struct->ClientDisconnect); pr_global_struct->self = saveSelf; + + PR_SwitchQCVM(nullptr); + PR_SwitchQCVM(oldvm); } Sys_Printf("Client %s removed\n", host_client->name); @@ -706,9 +713,9 @@ void Host_ShutdownServer(bool crash) } // QSS - { - QCVMGuard qg{&sv.qcvm}; + PR_SwitchQCVM(&sv.qcvm); + { for(i = 0, host_client = svs.clients; i < svs.maxclients; i++, host_client++) { @@ -722,6 +729,8 @@ void Host_ShutdownServer(bool crash) qcvm->worldmodel = nullptr; } + PR_SwitchQCVM(nullptr); + // // clear structures // @@ -970,7 +979,7 @@ void _Host_Frame(double time) // QSS PR_ClearProgs(&cl.qcvm); if(pr_checkextension.value && !cl_nocsqc.value) { // only try to use csqc if qc extensions are enabled. - QCVMGuard qg{&cl.qcvm}; + PR_SwitchQCVM(&cl.qcvm); // try csprogs.dat first, then fall back on progs.dat in case // someone tried merging the two. we only care about it if it // actually contains a CSQC_DrawHud, otherwise its either just a @@ -1031,6 +1040,7 @@ void _Host_Frame(double time) // QSS { PR_ClearProgs(qcvm); } + PR_SwitchQCVM(nullptr); } cl.sendprespawn = false; @@ -1077,8 +1087,9 @@ void _Host_Frame(double time) // QSS if(sv.active) { - QCVMGuard qg{&sv.qcvm}; + PR_SwitchQCVM(&sv.qcvm); Host_ServerFrame(); + PR_SwitchQCVM(nullptr); } host_frametime = realframetime; diff --git a/Quake/host_cmd.cpp b/Quake/host_cmd.cpp index d4d3975f..4e2ac21f 100644 --- a/Quake/host_cmd.cpp +++ b/Quake/host_cmd.cpp @@ -22,6 +22,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#include "server.hpp" +#endif + +#ifdef WIN32 +#include +#include "debugapi.h" + +#undef min +#undef max +#endif + #include "host.hpp" #include "quakedef.hpp" #include "net.hpp" @@ -40,6 +53,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef_macros.hpp" #include "menu.hpp" #include "screen.hpp" +#include "server.hpp" #include "client.hpp" #include "sys.hpp" #include "saveutil.hpp" @@ -1023,10 +1037,9 @@ void Host_Map_f() *p = '\0'; } - { - QCVMGuard qg{&sv.qcvm}; - SV_SpawnServer(name, SpawnServerSrc::FromMapCmd); - } + PR_SwitchQCVM(&sv.qcvm); + SV_SpawnServer(name, SpawnServerSrc::FromMapCmd); + PR_SwitchQCVM(nullptr); if(!sv.active) { @@ -1127,13 +1140,13 @@ void Host_Changelevel_f() IN_UpdateGrabs(); // -- S.A. } - { - QCVMGuard qg{&sv.qcvm}; - SV_SaveSpawnparms(); + PR_SwitchQCVM(&sv.qcvm); + SV_SaveSpawnparms(); - q_strlcpy(level, Cmd_Argv(1), sizeof(level)); - SV_SpawnServer(level, SpawnServerSrc::FromChangelevelCmd); - } + q_strlcpy(level, Cmd_Argv(1), sizeof(level)); + SV_SpawnServer(level, SpawnServerSrc::FromChangelevelCmd); + + PR_SwitchQCVM(nullptr); // also issue an error if spawn failed -- O.S. if(!sv.active) @@ -1178,10 +1191,9 @@ void Host_Restart_f() // mapname gets cleared in spawnserver q_strlcpy(mapname, sv.name, sizeof(mapname)); - { - QCVMGuard qg{&sv.qcvm}; - SV_SpawnServer(mapname, SpawnServerSrc::FromRestart); - } + PR_SwitchQCVM(&sv.qcvm); + SV_SpawnServer(mapname, SpawnServerSrc::FromRestart); + PR_SwitchQCVM(nullptr); if(!sv.active) { @@ -1370,7 +1382,7 @@ bool Host_MakeSavegame( } // QSS - QCVMGuard qg{&sv.qcvm}; + PR_SwitchQCVM(&sv.qcvm); fprintf(f, "%i\n", SAVEGAME_VERSION); char comment[SAVEGAME_COMMENT_LENGTH + 1]; @@ -1466,6 +1478,7 @@ bool Host_MakeSavegame( Con_Printf("done.\n"); } + PR_SwitchQCVM(nullptr); return true; } @@ -2291,8 +2304,12 @@ void Host_Spawn_f() // VR: Force autosave on client spawn. if(!pr_global_struct->deathmatch && !pr_global_struct->coop) { - QCVMGuard qg{nullptr}; + qcvm_t* oldvm = qcvm; + PR_SwitchQCVM(nullptr); + quake::saveutil::doChangelevelAutosave(); + + PR_SwitchQCVM(oldvm); } } @@ -2790,8 +2807,9 @@ void Host_Give_f() } // TODO VR: (P2) docs - const auto updateAmmoCounter = [&](const float currentAmmo, - float& ammoCounter) { + const auto updateAmmoCounter = + [&](const float currentAmmo, float& ammoCounter) + { switch((int)(currentAmmo)) { case AID_NONE: @@ -2865,7 +2883,7 @@ edict_t* FindViewthing() edict_t* e = nullptr; // QSS - QCVMGuard qg{&sv.qcvm}; + PR_SwitchQCVM(&sv.qcvm); i = qcvm->num_edicts; if(i == qcvm->num_edicts) @@ -2898,6 +2916,7 @@ edict_t* FindViewthing() Con_Printf("No viewthing on map\n"); } + PR_SwitchQCVM(nullptr); return e; } @@ -2932,10 +2951,11 @@ void Host_Viewmodel_f() } // QSS - QCVMGuard qg{&sv.qcvm}; + PR_SwitchQCVM(&sv.qcvm); e->v.modelindex = m ? SV_Precache_Model(m->name) : 0; e->v.model = PR_SetEngineString(sv.model_precache[(int)e->v.modelindex]); e->v.frame = 0; + PR_SwitchQCVM(nullptr); } /* diff --git a/Quake/in_sdl.cpp b/Quake/in_sdl.cpp index f8c91787..8c9c00d6 100644 --- a/Quake/in_sdl.cpp +++ b/Quake/in_sdl.cpp @@ -389,7 +389,7 @@ void IN_MouseMotion(int dx, int dy, int wx, int wy) } else if(cl.qcvm.extfuncs.CSQC_InputEvent) { - QCVMGuard qg{&cl.qcvm}; + PR_SwitchQCVM(&cl.qcvm); if(cl.csqc_cursorforced) { @@ -416,6 +416,8 @@ void IN_MouseMotion(int dx, int dy, int wx, int wy) { dx = dy = 0; // if the qc says it handled it, swallow the movement. } + + PR_SwitchQCVM(nullptr); } total_dx += dx; diff --git a/Quake/keys.cpp b/Quake/keys.cpp index 2dfdc248..5c1c885d 100644 --- a/Quake/keys.cpp +++ b/Quake/keys.cpp @@ -1404,19 +1404,21 @@ void Key_GetGrabbedInput(int* lastkey, int* lastchar) bool CSQC_HandleKeyEvent(bool down, int keyc, int unic) { + bool inhibit = false; + if(cl.qcvm.extfuncs.CSQC_InputEvent && key_dest == key_game) { - QCVMGuard qg{&cl.qcvm}; - + PR_SwitchQCVM(&cl.qcvm); G_FLOAT(OFS_PARM0) = down ? CSIE_KEYDOWN : CSIE_KEYUP; G_VECTORSET(OFS_PARM1, Key_NativeToQC(keyc), 0, 0); // x G_VECTORSET(OFS_PARM2, unic, 0, 0); // y G_VECTORSET(OFS_PARM3, 0, 0, 0); // devid PR_ExecuteProgram(cl.qcvm.extfuncs.CSQC_InputEvent); - return G_FLOAT(OFS_RETURN); + inhibit = G_FLOAT(OFS_RETURN); + PR_SwitchQCVM(nullptr); } - return false; + return inhibit; } /* diff --git a/Quake/main_sdl.cpp b/Quake/main_sdl.cpp index 43b7f765..a7a239e9 100644 --- a/Quake/main_sdl.cpp +++ b/Quake/main_sdl.cpp @@ -103,7 +103,7 @@ int main(int argc, char* argv[]) // TODO VR: (P2) linux hack #ifdef WIN32 vr_working_directory = - vr_working_directory.substr(0, vr_working_directory.find_last_of("\\")); + vr_working_directory.substr(0, vr_working_directory.find_last_of('\\')); #else vr_working_directory = "/run/media/vittorioromeo/D2703413703400B1/OHWorkspace/quakevr/Windows/" diff --git a/Quake/mathlib.cpp b/Quake/mathlib.cpp index 2aafa787..edc6cd86 100644 --- a/Quake/mathlib.cpp +++ b/Quake/mathlib.cpp @@ -295,6 +295,64 @@ int BoxOnPlaneSide(const qvec3& emins, const qvec3& emaxs, mplane_t* p) return res; } +// johnfitz -- the opposite of AngleVectors. this takes forward and generates +// pitch yaw roll Spike: take right and up vectors to properly set yaw and roll +[[nodiscard]] qvec3 VectorAngles(const qvec3& forward, const qvec3& up) +{ + qvec3 angles{}; + + if(forward[0] == 0 && forward[1] == 0) + { // either vertically up or down + if(forward[2] > 0) + { + angles[PITCH] = -90; + angles[YAW] = atan2(-up[1], -up[0]) / M_PI_DIV_180; + } + else + { + angles[PITCH] = 90; + angles[YAW] = atan2(up[1], up[0]) / M_PI_DIV_180; + } + angles[ROLL] = 0; + } + else + { + angles[PITCH] = -atan2(forward[2], sqrt(DotProduct2(forward, forward))); + angles[YAW] = atan2(forward[1], forward[0]); + + + float cp = cos(angles[PITCH]), sp = sin(angles[PITCH]); + float cy = cos(angles[YAW]), sy = sin(angles[YAW]); + qvec3 tleft, tup; + tleft[0] = -sy; + tleft[1] = cy; + tleft[2] = 0; + tup[0] = sp * cy; + tup[1] = sp * sy; + tup[2] = cp; + angles[ROLL] = + -atan2(DotProduct(up, tleft), DotProduct(up, tup)) / M_PI_DIV_180; + + angles[PITCH] /= M_PI_DIV_180; + angles[YAW] /= M_PI_DIV_180; + } + + return angles; +} + +[[nodiscard]] qvec3 TurnVector( + const qvec3 forward, const qvec3 side, float angle) +{ + float scale_forward, scale_side; + + scale_forward = cos(DEG2RAD(angle)); + scale_side = sin(DEG2RAD(angle)); + + return qvec3{scale_forward * forward[0] + scale_side * side[0], + scale_forward * forward[1] + scale_side * side[1], + scale_forward * forward[2] + scale_side * side[2]}; +} + float VectorLength(vec3_t v) { return sqrt(DotProduct(v, v)); diff --git a/Quake/mathlib.hpp b/Quake/mathlib.hpp index 0fd4b875..bcbd13a1 100644 --- a/Quake/mathlib.hpp +++ b/Quake/mathlib.hpp @@ -92,6 +92,10 @@ static inline int IS_NAN(float x) } [[nodiscard]] qvec3 VectorAngles(const qvec3& forward) noexcept; // johnfitz +[[nodiscard]] qvec3 VectorAngles(const qvec3& forward, const qvec3& up); + +[[nodiscard]] qvec3 TurnVector( + const qvec3 forward, const qvec3 side, float angle); float VectorLength(vec3_t v); [[nodiscard]] qvec3 CrossProduct(const qvec3& v1, const qvec3& v2); diff --git a/Quake/menu.cpp b/Quake/menu.cpp index 135a577c..68970cb0 100644 --- a/Quake/menu.cpp +++ b/Quake/menu.cpp @@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.hpp" #include "bgmusic.hpp" #include "menu_util.hpp" +#include "server.hpp" #include "util.hpp" #include "vr.hpp" #include "vr_cvars.hpp" @@ -474,7 +475,8 @@ void M_Main_Key(int key) "allows you to choose what '.pak' file to get the starting map " "from."); - e->_printer = [&](char* buf, const int buf_size, const int x) { + e->_printer = [&](char* buf, const int buf_size, const int x) + { snprintf(buf, buf_size, "%s", loadedPakNames[x % loadedPakNames.size()].data()); }; @@ -767,8 +769,10 @@ void M_Save_Key(int k) [[nodiscard]] static quake::menu makeBotControlMenu() { - const auto runCmd = [](const char* cmd) { - return [cmd] { + const auto runCmd = [](const char* cmd) + { + return [cmd] + { quake::menu_util::playMenuSound("items/r_item2.wav", 0.5); Cmd_ExecuteString(cmd, cmd_source_t::src_command); }; @@ -1190,22 +1194,27 @@ void M_Net_Key(int k) quake::menu m{"Options", &M_Menu_Main_f}; m.add_action_entry("Controls", &M_Menu_Keys_f); - m.add_action_entry("Goto Console", [] { - m_state = m_none; - Con_ToggleConsole_f(); - }); - m.add_action_entry("Reset Config", [] { - if(SCR_ModalMessage("This will reset all controls\n" - "and stored cvars. Continue? (y/n)\n", - 15.0f)) + m.add_action_entry("Goto Console", + [] { - Cbuf_AddText("resetcfg\n"); - Cbuf_AddText("exec default.cfg\n"); - } - }); + m_state = m_none; + Con_ToggleConsole_f(); + }); + m.add_action_entry("Reset Config", + [] + { + if(SCR_ModalMessage("This will reset all controls\n" + "and stored cvars. Continue? (y/n)\n", + 15.0f)) + { + Cbuf_AddText("resetcfg\n"); + Cbuf_AddText("exec default.cfg\n"); + } + }); m.add_action_slider_entry( "Scale", - [](int dir) { + [](int dir) + { const float l = ((vid.width + 31) / 32) / 10.0; const float f = std::clamp(scr_conscale.value + dir * 0.1f, 1.f, l); @@ -1213,13 +1222,15 @@ void M_Net_Key(int k) Cvar_SetValue("scr_menuscale", f); Cvar_SetValue("scr_sbarscale", f); }, - [] { + [] + { const float l = (vid.width / 320.0) - 1; return l > 0 ? (scr_conscale.value - 1) / l : 0; }); m.add_action_slider_entry( "Screen Size", - [](int dir) { + [](int dir) + { const float f = std::clamp(scr_viewsize.value + dir * 10, 30.f, 120.f); Cvar_SetValue("viewsize", f); @@ -1231,7 +1242,8 @@ void M_Net_Key(int k) { m.add_action_slider_entry( "Brightness", - [](int dir) { + [](int dir) + { const float f = std::clamp(vid_gamma.value - dir * 0.05f, 0.5f, 1.f); Cvar_SetValue("gamma", f); @@ -1240,7 +1252,8 @@ void M_Net_Key(int k) m.add_action_slider_entry( "Contrast", - [](int dir) { + [](int dir) + { const float f = std::clamp(vid_contrast.value + dir * 0.1f, 1.f, 2.f); Cvar_SetValue("contrast", f); @@ -1250,7 +1263,8 @@ void M_Net_Key(int k) m.add_action_slider_entry( "Mouse Speed", - [](int dir) { + [](int dir) + { const float f = std::clamp(sensitivity.value + dir * 0.5f, 1.f, 11.f); Cvar_SetValue("sensitivity", f); @@ -1258,7 +1272,8 @@ void M_Net_Key(int k) [] { return (sensitivity.value - 1) / 10; }); m.add_action_slider_entry( "Statusbar Alpha", - [](int dir) { + [](int dir) + { const float f = std::clamp(scr_sbaralpha.value - dir * 0.05f, 0.f, 1.f); Cvar_SetValue("scr_sbaralpha", f); @@ -1266,14 +1281,16 @@ void M_Net_Key(int k) [] { return (1.0 - scr_sbaralpha.value); }); m.add_action_slider_entry( "Sound Volume", - [](int dir) { + [](int dir) + { const float f = std::clamp(sfxvolume.value + dir * 0.1f, 0.f, 1.f); Cvar_SetValue("volume", f); }, [] { return sfxvolume.value; }); m.add_action_slider_entry( "Music Volume", - [](int dir) { + [](int dir) + { const float f = std::clamp(bgmvolume.value + dir * 0.1f, 0.f, 1.f); Cvar_SetValue("bgmvolume", f); }, @@ -1282,16 +1299,18 @@ void M_Net_Key(int k) m.add_cvar_entry("Always Run", cl_alwaysrun); m.add_action_entry("Toggle Invert Mouse", [] { Cvar_SetValue("m_pitch", -m_pitch.value); }); - m.add_action_entry("Toggle Mouse Look", [] { - if(in_mlook.state & 1) + m.add_action_entry("Toggle Mouse Look", + [] { - Cbuf_AddText("-mlook"); - } - else - { - Cbuf_AddText("+mlook"); - } - }); + if(in_mlook.state & 1) + { + Cbuf_AddText("-mlook"); + } + else + { + Cbuf_AddText("+mlook"); + } + }); m.add_cvar_entry("Lookspring", lookspring); m.add_cvar_entry("Lookstrafe", lookstrafe); @@ -1521,7 +1540,8 @@ void M_Options_Key(int k) { auto e = m.add_cvar_entry("Turn", vr_snap_turn, {5, 0, 90}); e.tooltip("Joystick turn smooth mode or snap turn degrees."); - e->_printer = [](char* buf, const int buf_size, const int x) { + e->_printer = [](char* buf, const int buf_size, const int x) + { if(x == 0) { snprintf(buf, buf_size, "Smooth"); @@ -2201,11 +2221,13 @@ void M_Options_Key(int k) quake::menu m{"Torso Settings", &M_Menu_QuakeVRSettings_f}; - m.on_key([](int, quake::impl::menu_entry&) { - // TODO VR: (P2) hackish - VR_ModVRTorsoModel(); - VR_ModVRLegHolsterModel(); - }); + m.on_key( + [](int, quake::impl::menu_entry&) + { + // TODO VR: (P2) hackish + VR_ModVRTorsoModel(); + VR_ModVRLegHolsterModel(); + }); // ------------------------------------------------------------------------ @@ -2269,12 +2291,14 @@ void M_Options_Key(int k) quake::menu m{"Transparency Options", &M_Menu_QuakeVRSettings_f}; // TODO VR: (P1) what about this? - m.on_key([](const int key, quake::impl::menu_entry& entry) { - if(key == 'p') + m.on_key( + [](const int key, quake::impl::menu_entry& entry) { - quakeVRQuickSettingsMenu().add_entry_ptr(entry); - } - }); + if(key == 'p') + { + quakeVRQuickSettingsMenu().add_entry_ptr(entry); + } + }); extern cvar_t r_novis; m.add_cvar_entry("(!) No Vis", r_novis) @@ -2439,7 +2463,8 @@ static void forQVRSMenus(F&& f) { quake::menu m{"Quake VR - Settings", &M_Menu_Main_f}; - const auto makeGotoMenu = [&](quake::menu& xm, m_state_e s) { + const auto makeGotoMenu = [&](quake::menu& xm, m_state_e s) + { m.add_action_entry( xm.title(), [&xm, s] { quake::menu_util::setMenuState(xm, s); }); }; @@ -2480,7 +2505,8 @@ void M_QuakeVRSettings_Key(int k) { static bool wpnoff_offhand = false; - const auto getIdx = [] { + const auto getIdx = [] + { return wpnoff_offhand ? VR_GetOffHandWpnCvarEntry() : VR_GetMainHandWpnCvarEntry(); }; @@ -2499,14 +2525,17 @@ void M_QuakeVRSettings_Key(int k) quake::menu m{"Weapon Configuration (1) - Basics, Muzzle, 2H", &M_Menu_QuakeVRDevTools_f}; - m.on_key([](int, quake::impl::menu_entry&) { - // TODO VR: (P2) hackish - VR_ModAllWeapons(); - }); + m.on_key( + [](int, quake::impl::menu_entry&) + { + // TODO VR: (P2) hackish + VR_ModAllWeapons(); + }); // ------------------------------------------------------------------------ - const auto o_wpncvar = [&](const char* title, const WpnCVar c) { + const auto o_wpncvar = [&](const char* title, const WpnCVar c) + { return m.add_cvar_getter_entry( // title, // [getIdx, c] { return &VR_GetWpnCVar(getIdx(), c); }, // @@ -2514,7 +2543,8 @@ void M_QuakeVRSettings_Key(int k) ); }; - const auto r_wpncvar = [&](const char* title, const WpnCVar c) { + const auto r_wpncvar = [&](const char* title, const WpnCVar c) + { return m.add_cvar_getter_entry( // title, // [getIdx, c] { return &VR_GetWpnCVar(getIdx(), c); }, // @@ -2522,8 +2552,10 @@ void M_QuakeVRSettings_Key(int k) ); }; - const auto makeHoverFn = [&](int& implVar) { - return [&](const bool x) { + const auto makeHoverFn = [&](int& implVar) + { + return [&](const bool x) + { if(!x) { implVar = 0; @@ -2601,10 +2633,9 @@ void M_QuakeVRSettings_Key(int k) m.add_cvar_getter_entry( // "Muzzle Anchor Vertex", // - [getIdx] { - return &VR_GetWpnCVar(getIdx(), WpnCVar::MuzzleAnchorVertex); - }, // - {1, 0, 4096} // + [getIdx] + { return &VR_GetWpnCVar(getIdx(), WpnCVar::MuzzleAnchorVertex); }, // + {1, 0, 4096} // ) .hover(hoverMuzzle) .tooltip("Index of the mesh vertex where the muzzle will be attached."); @@ -2656,7 +2687,8 @@ void M_QuakeVRSettings_Key(int k) { static bool wpnoff_offhand = false; - const auto getIdx = [] { + const auto getIdx = [] + { return wpnoff_offhand ? VR_GetOffHandWpnCvarEntry() : VR_GetMainHandWpnCvarEntry(); }; @@ -2675,14 +2707,17 @@ void M_QuakeVRSettings_Key(int k) quake::menu m{ "Weapon Configuration (2) - Hand, 2H", &M_Menu_QuakeVRDevTools_f}; - m.on_key([](int, quake::impl::menu_entry&) { - // TODO VR: (P2) hackish - VR_ModAllWeapons(); - }); + m.on_key( + [](int, quake::impl::menu_entry&) + { + // TODO VR: (P2) hackish + VR_ModAllWeapons(); + }); // ------------------------------------------------------------------------ - const auto o_wpncvar = [&](const char* title, const WpnCVar c) { + const auto o_wpncvar = [&](const char* title, const WpnCVar c) + { return m.add_cvar_getter_entry( // title, // [getIdx, c] { return &VR_GetWpnCVar(getIdx(), c); }, // @@ -2690,7 +2725,8 @@ void M_QuakeVRSettings_Key(int k) ); }; - const auto r_wpncvar = [&](const char* title, const WpnCVar c) { + const auto r_wpncvar = [&](const char* title, const WpnCVar c) + { return m.add_cvar_getter_entry( // title, // [getIdx, c] { return &VR_GetWpnCVar(getIdx(), c); }, // @@ -2698,15 +2734,18 @@ void M_QuakeVRSettings_Key(int k) ); }; - const auto b_wpncvar = [&](const char* title, const WpnCVar c) { + const auto b_wpncvar = [&](const char* title, const WpnCVar c) + { return m.add_cvar_getter_entry( // title, // [getIdx, c] { return &VR_GetWpnCVar(getIdx(), c); } // ); }; - const auto makeHoverFn = [&](int& implVar) { - return [&](const bool x) { + const auto makeHoverFn = [&](int& implVar) + { + return [&](const bool x) + { if(!x) { implVar = 0; @@ -2740,10 +2779,9 @@ void M_QuakeVRSettings_Key(int k) m.add_cvar_getter_entry( // "Hand Anchor Vertex", // - [getIdx] { - return &VR_GetWpnCVar(getIdx(), WpnCVar::HandAnchorVertex); - }, // - {1, 0, 4096} // + [getIdx] + { return &VR_GetWpnCVar(getIdx(), WpnCVar::HandAnchorVertex); }, // + {1, 0, 4096} // ) .hover(hoverHandAnchorVertex) .tooltip( @@ -2757,10 +2795,9 @@ void M_QuakeVRSettings_Key(int k) m.add_cvar_getter_enum_entry( // "2H Display Mode", // - [getIdx] { - return &VR_GetWpnCVar(getIdx(), WpnCVar::TwoHDisplayMode); - }, // - "Dynamic", "Fixed" // + [getIdx] + { return &VR_GetWpnCVar(getIdx(), WpnCVar::TwoHDisplayMode); }, // + "Dynamic", "Fixed" // ) .tooltip( "Display mode for the 2H aiming helping hand. When 'dynamic', the " @@ -2769,10 +2806,9 @@ void M_QuakeVRSettings_Key(int k) m.add_cvar_getter_entry( // "2H Hand Anchor Vertex", // - [getIdx] { - return &VR_GetWpnCVar(getIdx(), WpnCVar::TwoHHandAnchorVertex); - }, // - {1, 0, 4096} // + [getIdx] + { return &VR_GetWpnCVar(getIdx(), WpnCVar::TwoHHandAnchorVertex); }, // + {1, 0, 4096} // ) .hover(hover2HHandAnchorVertex) .tooltip( @@ -2872,7 +2908,8 @@ void M_QuakeVRSettings_Key(int k) { static bool wpnoff_offhand = false; - const auto getIdx = [] { + const auto getIdx = [] + { return wpnoff_offhand ? VR_GetOffHandWpnCvarEntry() : VR_GetMainHandWpnCvarEntry(); }; @@ -2888,14 +2925,17 @@ void M_QuakeVRSettings_Key(int k) quake::menu m{ "Weapon Configuration (3) - Weight", &M_Menu_QuakeVRDevTools_f}; - m.on_key([](int, quake::impl::menu_entry&) { - // TODO VR: (P2) hackish - VR_ModAllWeapons(); - }); + m.on_key( + [](int, quake::impl::menu_entry&) + { + // TODO VR: (P2) hackish + VR_ModAllWeapons(); + }); // ------------------------------------------------------------------------ - const auto w_wpncvar = [&](const char* title, const WpnCVar c) { + const auto w_wpncvar = [&](const char* title, const WpnCVar c) + { return m.add_cvar_getter_entry( // title, // [getIdx, c] { return &VR_GetWpnCVar(getIdx(), c); }, // @@ -2903,7 +2943,8 @@ void M_QuakeVRSettings_Key(int k) ); }; - const auto wm_wpncvar = [&](const char* title, const WpnCVar c) { + const auto wm_wpncvar = [&](const char* title, const WpnCVar c) + { return m.add_cvar_getter_entry( // title, // [getIdx, c] { return &VR_GetWpnCVar(getIdx(), c); }, // @@ -2970,7 +3011,8 @@ void M_QuakeVRSettings_Key(int k) { static bool wpnoff_offhand = false; - const auto getIdx = [] { + const auto getIdx = [] + { return wpnoff_offhand ? VR_GetOffHandWpnCvarEntry() : VR_GetMainHandWpnCvarEntry(); }; @@ -2990,14 +3032,17 @@ void M_QuakeVRSettings_Key(int k) quake::menu m{ "Weapon Configuration (4) - Button, Blend", &M_Menu_QuakeVRDevTools_f}; - m.on_key([](int, quake::impl::menu_entry&) { - // TODO VR: (P2) hackish - VR_ModAllWeapons(); - }); + m.on_key( + [](int, quake::impl::menu_entry&) + { + // TODO VR: (P2) hackish + VR_ModAllWeapons(); + }); // ------------------------------------------------------------------------ - const auto o_wpncvar = [&](const char* title, const WpnCVar c) { + const auto o_wpncvar = [&](const char* title, const WpnCVar c) + { return m.add_cvar_getter_entry( // title, // [getIdx, c] { return &VR_GetWpnCVar(getIdx(), c); }, // @@ -3005,7 +3050,8 @@ void M_QuakeVRSettings_Key(int k) ); }; - const auto r_wpncvar = [&](const char* title, const WpnCVar c) { + const auto r_wpncvar = [&](const char* title, const WpnCVar c) + { return m.add_cvar_getter_entry( // title, // [getIdx, c] { return &VR_GetWpnCVar(getIdx(), c); }, // @@ -3013,7 +3059,8 @@ void M_QuakeVRSettings_Key(int k) ); }; - const auto zb_wpncvar = [&](const char* title, const WpnCVar c) { + const auto zb_wpncvar = [&](const char* title, const WpnCVar c) + { return m.add_cvar_getter_entry( // title, // [getIdx, c] { return &VR_GetWpnCVar(getIdx(), c); }, // @@ -3021,8 +3068,10 @@ void M_QuakeVRSettings_Key(int k) ); }; - const auto makeHoverFn = [&](int& implVar) { - return [&](const bool x) { + const auto makeHoverFn = [&](int& implVar) + { + return [&](const bool x) + { if(!x) { implVar = 0; @@ -3046,10 +3095,9 @@ void M_QuakeVRSettings_Key(int k) m.add_cvar_getter_enum_entry( // "Button Mode", // - [getIdx] { - return &VR_GetWpnCVar(getIdx(), WpnCVar::WpnButtonMode); - }, // - "Disabled", "Ammo Type Change" // + [getIdx] + { return &VR_GetWpnCVar(getIdx(), WpnCVar::WpnButtonMode); }, // + "Disabled", "Ammo Type Change" // ) .tooltip("Type of button."); @@ -3117,7 +3165,8 @@ void M_QuakeVRSettings_Key(int k) { static bool wpnoff_offhand = false; - const auto getIdx = [] { + const auto getIdx = [] + { return wpnoff_offhand ? VR_GetOffHandWpnCvarEntry() : VR_GetMainHandWpnCvarEntry(); }; @@ -3136,14 +3185,17 @@ void M_QuakeVRSettings_Key(int k) quake::menu m{"Weapon Configuration (5) - Text", &M_Menu_QuakeVRDevTools_f}; - m.on_key([](int, quake::impl::menu_entry&) { - // TODO VR: (P2) hackish - VR_ModAllWeapons(); - }); + m.on_key( + [](int, quake::impl::menu_entry&) + { + // TODO VR: (P2) hackish + VR_ModAllWeapons(); + }); // ------------------------------------------------------------------------ - const auto o_wpncvar = [&](const char* title, const WpnCVar c) { + const auto o_wpncvar = [&](const char* title, const WpnCVar c) + { return m.add_cvar_getter_entry( // title, // [getIdx, c] { return &VR_GetWpnCVar(getIdx(), c); }, // @@ -3151,7 +3203,8 @@ void M_QuakeVRSettings_Key(int k) ); }; - const auto r_wpncvar = [&](const char* title, const WpnCVar c) { + const auto r_wpncvar = [&](const char* title, const WpnCVar c) + { return m.add_cvar_getter_entry( // title, // [getIdx, c] { return &VR_GetWpnCVar(getIdx(), c); }, // @@ -3159,7 +3212,8 @@ void M_QuakeVRSettings_Key(int k) ); }; - const auto zb_wpncvar = [&](const char* title, const WpnCVar c) { + const auto zb_wpncvar = [&](const char* title, const WpnCVar c) + { return m.add_cvar_getter_entry( // title, // [getIdx, c] { return &VR_GetWpnCVar(getIdx(), c); }, // @@ -3167,8 +3221,10 @@ void M_QuakeVRSettings_Key(int k) ); }; - const auto makeHoverFn = [&](int& implVar) { - return [&](const bool x) { + const auto makeHoverFn = [&](int& implVar) + { + return [&](const bool x) + { if(!x) { implVar = 0; @@ -3226,10 +3282,9 @@ void M_QuakeVRSettings_Key(int k) m.add_cvar_getter_entry( // "Text Anchor Vertex", // - [getIdx] { - return &VR_GetWpnCVar(getIdx(), WpnCVar::WpnTextAnchorVertex); - }, // - {1, 0, 4096} // + [getIdx] + { return &VR_GetWpnCVar(getIdx(), WpnCVar::WpnTextAnchorVertex); }, // + {1, 0, 4096} // ) .hover(hoverWpnTextAnchorVertex) .tooltip("Index of the mesh vertex where the text will be attached."); @@ -3303,8 +3358,10 @@ void M_QuakeVRSettings_Key(int k) [[nodiscard]] static quake::menu makeQVRDTDebugUtilitiesMenu() { - const auto runCmd = [](const char* cmd) { - return [cmd] { + const auto runCmd = [](const char* cmd) + { + return [cmd] + { quake::menu_util::playMenuSound("items/r_item2.wav", 0.5); Cmd_ExecuteString(cmd, cmd_source_t::src_command); }; @@ -3337,6 +3394,28 @@ void M_QuakeVRSettings_Key(int k) m.add_separator(); // ------------------------------------------------------------------------ + m.add_cvar_entry("Throw Avg Frames", vr_throw_avg_frames, {1, 1, 50}); + + m.add_cvar_entry( + "Throw AngVel Avg Frames", vr_throw_angvel_avg_frames, {1, 1, 50}); + + m.add_action_entry( + "Refresh Throw Avg Frames", [] { VR_ResetThrowAvgFrames(); }); + + // ------------------------------------------------------------------------ + m.add_separator(); + // ------------------------------------------------------------------------ + + m.add_cvar_getter_enum_entry( // + "Throw Algorithm", // + [] { return &vr_throw_algorithm; }, // + "Basic", "CrossAngVel" // + ); + + // ------------------------------------------------------------------------ + m.add_separator(); + // ------------------------------------------------------------------------ + m.add_cvar_entry("Autosave Period", vr_autosave_seconds, {5, 5, 2400}); m.add_cvar_entry( "Autosave On Changelevel", vr_autosave_on_changelevel); @@ -3435,7 +3514,8 @@ static void forQVRDTMenus(F&& f) { quake::menu m{"Quake VR - Dev Tools", &M_Menu_Main_f}; - const auto makeGotoMenu = [&](quake::menu& xm, m_state_e s) { + const auto makeGotoMenu = [&](quake::menu& xm, m_state_e s) + { m.add_action_entry( xm.title(), [&xm, s] { quake::menu_util::setMenuState(xm, s); }); }; @@ -3488,8 +3568,10 @@ template [[nodiscard]] static quake::menu makeQVRCMChangeMapMenuImpl( const std::string_view name, const Range& maps) { - const auto changeMap = [&maps](const int option) { - return [&maps, option] { + const auto changeMap = [&maps](const int option) + { + return [&maps, option] + { quake::menu_util::playMenuSound("items/r_item2.wav", 0.5); const char* cmd = @@ -3653,7 +3735,8 @@ static void forQVRCMMenus(F&& f) { quake::menu m{"Quake VR - Change Map", &M_Menu_Main_f}; - const auto makeGotoMenu = [&](quake::menu& xm, m_state_e s) { + const auto makeGotoMenu = [&](quake::menu& xm, m_state_e s) + { m.add_action_entry( xm.title(), [&xm, s] { quake::menu_util::setMenuState(xm, s); }); }; @@ -5027,7 +5110,8 @@ void M_DrawKeyboard() const float my = vr_menu_mouse_y; const bool click = vr_menu_mouse_click; - const auto doKey = [&](const int key) { + const auto doKey = [&](const int key) + { if(key_dest == key_menu) { M_Keydown(key, true /* fromVirtualKeyboard */); @@ -5046,8 +5130,8 @@ void M_DrawKeyboard() } }; - const auto actions = quake::util::make_overload_set( - [&](const char c) { Char_Event(mkb().caps_lock() ? c - 32 : c); }, + const auto actions = quake::util::make_overload_set([&](const char c) + { Char_Event(mkb().caps_lock() ? c - 32 : c); }, [&](menu_keyboard::ka_backspace) { doKey(K_BACKSPACE); }, // [&](menu_keyboard::ka_enter) { doKey(K_ENTER); }, // [&](menu_keyboard::ka_back) { doKey(K_ESCAPE); }, // @@ -5058,7 +5142,8 @@ void M_DrawKeyboard() [&](menu_keyboard::ka_space) { Char_Event(' '); }, // [&](menu_keyboard::ka_tab) { doKey(K_TAB); }, // [&](menu_keyboard::ka_capslock) { mkb().toggle_caps_lock(); }, //, - [&](menu_keyboard::ka_console) { + [&](menu_keyboard::ka_console) + { m_state = m_none; Con_ToggleConsole_f(); }); @@ -5105,30 +5190,36 @@ void M_Draw() // ----------------------------------------------------------------------- // VR: Process nested "Quake VR Settings" menus. - forQVRSMenus([&](quake::menu& xm, m_state_e s) { - if(m_state == s) + forQVRSMenus( + [&](quake::menu& xm, m_state_e s) { - xm.draw(); - } - }); + if(m_state == s) + { + xm.draw(); + } + }); // ----------------------------------------------------------------------- // VR: Process nested "Quake VR Dev Tools" menus. - forQVRDTMenus([&](quake::menu& xm, m_state_e s) { - if(m_state == s) + forQVRDTMenus( + [&](quake::menu& xm, m_state_e s) { - xm.draw(); - } - }); + if(m_state == s) + { + xm.draw(); + } + }); // ----------------------------------------------------------------------- // VR: Process nested "Quake VR Change mMap" menus. - forQVRCMMenus([&](quake::menu& xm, m_state_e s) { - if(m_state == s) + forQVRCMMenus( + [&](quake::menu& xm, m_state_e s) { - xm.draw(); - } - }); + if(m_state == s) + { + xm.draw(); + } + }); switch(m_state) { @@ -5198,13 +5289,15 @@ void M_Keydown(int key, const bool fromVirtualKeyboard) { bool processedAny = false; - forQVRSMenus([&](quake::menu& xm, m_state_e s) { - if(m_state == s) + forQVRSMenus( + [&](quake::menu& xm, m_state_e s) { - xm.key(key); - processedAny = true; - } - }); + if(m_state == s) + { + xm.key(key); + processedAny = true; + } + }); if(processedAny) { @@ -5217,13 +5310,15 @@ void M_Keydown(int key, const bool fromVirtualKeyboard) { bool processedAny = false; - forQVRDTMenus([&](quake::menu& xm, m_state_e s) { - if(m_state == s) + forQVRDTMenus( + [&](quake::menu& xm, m_state_e s) { - xm.key(key); - processedAny = true; - } - }); + if(m_state == s) + { + xm.key(key); + processedAny = true; + } + }); if(processedAny) { @@ -5236,13 +5331,15 @@ void M_Keydown(int key, const bool fromVirtualKeyboard) { bool processedAny = false; - forQVRCMMenus([&](quake::menu& xm, m_state_e s) { - if(m_state == s) + forQVRCMMenus( + [&](quake::menu& xm, m_state_e s) { - xm.key(key); - processedAny = true; - } - }); + if(m_state == s) + { + xm.key(key); + processedAny = true; + } + }); if(processedAny) { diff --git a/Quake/menu_keyboard.cpp b/Quake/menu_keyboard.cpp index 8786e238..6059a772 100644 --- a/Quake/menu_keyboard.cpp +++ b/Quake/menu_keyboard.cpp @@ -1,7 +1,9 @@ #include "menu_keyboard.hpp" +#include "common.hpp" #include "gl_util.hpp" #include "menu.hpp" +#include "variantutil.hpp" #include @@ -113,9 +115,8 @@ void menu_keyboard::draw_letters() quake::util::match( k._action, - [&](const char c) { - M_DrawCharacter(cp.x, cp.y, _caps_lock ? c - 32 : c); - }, + [&](const char c) + { M_DrawCharacter(cp.x, cp.y, _caps_lock ? c - 32 : c); }, [&](ka_backspace) { M_PrintWhite(cp.x, cp.y, "backspace"); }, // [&](ka_enter) { M_PrintWhite(cp.x, cp.y, "enter"); }, // [&](ka_back) { M_PrintWhite(cp.x, cp.y, "escape"); }, // @@ -217,8 +218,9 @@ zxcvbnm,.-)"sv; cx += distance; } - const auto add_special_key = [&](const int x, const int y, const int width, - auto action) { + const auto add_special_key = + [&](const int x, const int y, const int width, auto action) + { constexpr int off = 8; constexpr int height = 8; diff --git a/Quake/menu_keyboard.hpp b/Quake/menu_keyboard.hpp index 98222dad..4827edfc 100644 --- a/Quake/menu_keyboard.hpp +++ b/Quake/menu_keyboard.hpp @@ -1,6 +1,6 @@ #pragma once -#include "util.hpp" +#include "variantutil.hpp" #include "quakeglm_qvec2.hpp" #include diff --git a/Quake/menu_util.cpp b/Quake/menu_util.cpp index 7bde2055..ebb8cf5c 100644 --- a/Quake/menu_util.cpp +++ b/Quake/menu_util.cpp @@ -4,6 +4,7 @@ #include "client.hpp" #include "menu.hpp" #include "util.hpp" +#include "variantutil.hpp" #include "keys.hpp" #include "q_sound.hpp" #include "input.hpp" @@ -95,40 +96,43 @@ void menu::key_option(const int key, const int idx) impl::menu_entry& e = access(idx); - const auto match_entry = [&](auto& self, auto&& entry) -> void { + const auto match_entry = [&](auto& self, auto&& entry) -> void + { quake::util::match( std::forward(entry), // - [&](const impl::menu_entry_value& x) { + [&](const impl::menu_entry_value& x) + { bool& v = *(x._getter()); v = !v; }, - [&](const impl::menu_entry_cvar& x) { + [&](const impl::menu_entry_cvar& x) + { const auto& [inc, min, max] = x._bounds; adjustCVarF(*(x._cvar_getter()), inc, min, max); }, - [&](const impl::menu_entry_cvar& x) { + [&](const impl::menu_entry_cvar& x) + { const auto& [inc, min, max] = x._bounds; adjustCVarI(*(x._cvar_getter()), inc, min, max); }, - [&](const impl::menu_entry_cvar& x) { - adjustCVarI(*(x._cvar_getter()), 1, 0, 1); - }, - [&](const impl::menu_entry_value_labeled_cvar& x) { + [&](const impl::menu_entry_cvar& x) + { adjustCVarI(*(x._cvar_getter()), 1, 0, 1); }, + [&](const impl::menu_entry_value_labeled_cvar& x) + { const auto& [inc, min, max] = x._bounds; adjustCVarI(*(x._cvar_getter()), inc, min, max); }, - [&](const impl::menu_entry_value_labeled& x) { + [&](const impl::menu_entry_value_labeled& x) + { const auto& [inc, min, max] = x._bounds; adjustValueI(*(x._getter()), inc, min, max); }, [&](const impl::menu_entry_action& x) { x._action(); }, - [&](const impl::menu_entry_action_slider& x) { - x._action_slide(isLeft ? -1 : 1); - }, + [&](const impl::menu_entry_action_slider& x) + { x._action_slide(isLeft ? -1 : 1); }, [&](const impl::menu_entry_separator&) {}, - [&](const impl::menu_entry_ptr& ptr) { - self(self, ptr._ptr->_variant); - }); + [&](const impl::menu_entry_ptr& ptr) + { self(self, ptr._ptr->_variant); }); }; match_entry(match_entry, e._variant); @@ -377,7 +381,8 @@ void menu::draw(const int offset_x, const int offset_y) constexpr int char_size = 8; constexpr int label_padding = 26; - const auto get_label_x = [&, this](const std::string_view s) { + const auto get_label_x = [&, this](const std::string_view s) + { if(_two_columns) { return (x - 240) + 70 + (120 * (idx / items_per_column)); @@ -387,8 +392,8 @@ void menu::draw(const int offset_x, const int offset_y) ((label_padding - static_cast(s.size())) * char_size); }; - const auto print_label = [this, &get_label_x, &y, &buf]( - std::string_view s) { + const auto print_label = [this, &get_label_x, &y, &buf](std::string_view s) + { if(_two_columns && s.size() > 13) { s.remove_suffix(s.size() - 13); @@ -403,27 +408,32 @@ void menu::draw(const int offset_x, const int offset_y) M_Print(get_label_x(s), y, buf); }; - const auto print_as_float_str = [&buf, &x, &y](const float value) { + const auto print_as_float_str = [&buf, &x, &y](const float value) + { snprintf(buf, sizeof(buf), "%.4f", value); M_Print(x, y, buf); }; - const auto print_as_int_str = [&buf, &x, &y](const int value) { + const auto print_as_int_str = [&buf, &x, &y](const int value) + { snprintf(buf, sizeof(buf), "%d", value); M_Print(x, y, buf); }; - const auto print_as_bool_str = [&buf, &x, &y](const bool value) { + const auto print_as_bool_str = [&buf, &x, &y](const bool value) + { snprintf(buf, sizeof(buf), value ? "On" : "Off"); M_Print(x, y, buf); }; - const auto print_as_str = [&buf, &x, &y](const std::string_view value) { + const auto print_as_str = [&buf, &x, &y](const std::string_view value) + { snprintf(buf, sizeof(buf), "%s", value.data()); M_Print(x, y, buf); }; - const auto print_tooltip = [&buf](const std::string_view value) { + const auto print_tooltip = [&buf](const std::string_view value) + { snprintf(buf, sizeof(buf), "%s", value.data()); M_PrintWhiteByWrapping(28, 340, 50, buf); }; @@ -440,14 +450,17 @@ void menu::draw(const int offset_x, const int offset_y) { const std::string_view& e_label = e._common._label; - const auto match_entry = [&](auto& self, auto&& entry) -> void { + const auto match_entry = [&](auto& self, auto&& entry) -> void + { quake::util::match( std::forward(entry), // - [&](const impl::menu_entry_value& entry) { + [&](const impl::menu_entry_value& entry) + { print_label(e_label); print_as_bool_str(*(entry._getter())); }, - [&](const impl::menu_entry_cvar& entry) { + [&](const impl::menu_entry_cvar& entry) + { print_label(e_label); const float value = entry._cvar_getter()->value; @@ -461,7 +474,8 @@ void menu::draw(const int offset_x, const int offset_y) M_Print(x, y, buf); } }, - [&](const impl::menu_entry_cvar& entry) { + [&](const impl::menu_entry_cvar& entry) + { print_label(e_label); const int value = entry._cvar_getter()->value; @@ -475,21 +489,25 @@ void menu::draw(const int offset_x, const int offset_y) M_Print(x, y, buf); } }, - [&](const impl::menu_entry_cvar& entry) { + [&](const impl::menu_entry_cvar& entry) + { print_label(e_label); print_as_bool_str(entry._cvar_getter()->value); }, - [&](const impl::menu_entry_value_labeled_cvar& entry) { + [&](const impl::menu_entry_value_labeled_cvar& entry) + { print_label(e_label); print_as_str(entry._value_label_fn( static_cast(entry._cvar_getter()->value))); }, - [&](const impl::menu_entry_value_labeled& entry) { + [&](const impl::menu_entry_value_labeled& entry) + { print_label(e_label); print_as_str(entry._value_label_fn( static_cast(*entry._getter()))); }, - [&](const impl::menu_entry_action&) { + [&](const impl::menu_entry_action&) + { print_label(e_label); if(!_two_columns) @@ -497,14 +515,14 @@ void menu::draw(const int offset_x, const int offset_y) print_as_str("(X)"); } }, - [&](const impl::menu_entry_action_slider& entry) { + [&](const impl::menu_entry_action_slider& entry) + { print_label(e_label); M_DrawSlider(x + 10, y, entry._range()); }, [&](const impl::menu_entry_separator&) {}, - [&](const impl::menu_entry_ptr& ptr) { - self(self, ptr._ptr->_variant); - }); + [&](const impl::menu_entry_ptr& ptr) + { self(self, ptr._ptr->_variant); }); }; match_entry(match_entry, e._variant); diff --git a/Quake/menu_util.hpp b/Quake/menu_util.hpp index 9e2db25d..82c33633 100644 --- a/Quake/menu_util.hpp +++ b/Quake/menu_util.hpp @@ -233,16 +233,22 @@ class menu [[nodiscard]] bool entry_is_selectable_at(const int idx); + std::size_t emplace_and_get_handle_impl( + const impl::menu_entry_common& common, + impl::menu_entry_variant&& entry_variant) noexcept + { + const auto index = _entries.size(); + _entries.emplace_back(common, std::move(entry_variant)); + return index; + } + template entry_handle emplace_and_get_handle( const impl::menu_entry_common& common, Args&&... args) noexcept { - const auto index = _entries.size(); - - _entries.emplace_back( - common, impl::menu_entry_variant{T{std::forward(args)...}}); - - return entry_handle{*this, index}; + return entry_handle{*this, + emplace_and_get_handle_impl(common, + impl::menu_entry_variant{T{std::forward(args)...}})}; } void update_hover( @@ -283,8 +289,8 @@ class menu auto add_cvar_getter_enum_entry(const std::string_view label, CvarGetter&& cvar_getter, const EnumLabels... enum_labels) { - const auto enum_labels_fn = [enum_labels...]( - int x) -> std::string_view { + const auto enum_labels_fn = [enum_labels...](int x) -> std::string_view + { static std::array strs{ enum_labels...}; return strs[static_cast(x)]; @@ -301,8 +307,8 @@ class menu auto add_getter_enum_entry(const std::string_view label, Getter&& getter, const EnumLabels... enum_labels) { - const auto enum_labels_fn = [enum_labels...]( - int x) -> std::string_view { + const auto enum_labels_fn = [enum_labels...](int x) -> std::string_view + { static std::array strs{ enum_labels...}; return strs[static_cast(x)]; diff --git a/Quake/net_wins.cpp b/Quake/net_wins.cpp index 1f67840c..1ecad9bc 100644 --- a/Quake/net_wins.cpp +++ b/Quake/net_wins.cpp @@ -608,7 +608,7 @@ int WINS_GetSocketAddr(sys_socket_t socketid, struct qsockaddr* addr) #ifdef IPPROTO_IPV6 if(addr->qsa_family == AF_INET6) { - static const in_addr6_t in6addr_any; // = IN6ADDR_ANY_INIT; + static const in_addr6_t in6addr_any = IN6ADDR_ANY_INIT; if(!memcmp(&((struct sockaddr_in6*)addr)->sin6_addr, &in6addr_any, sizeof(in_addr6_t))) memcpy(&((struct sockaddr_in6*)addr)->sin6_addr, &myAddrv6, @@ -897,9 +897,9 @@ sys_socket_t WINIPv6_Init() if(COM_CheckParm("-noudp") || COM_CheckParm("-noudp6")) return -1; qgetaddrinfo = - (void*)GetProcAddress(GetModuleHandle("ws2_32.dll"), "getaddrinfo"); + (decltype(qgetaddrinfo))GetProcAddress(GetModuleHandle("ws2_32.dll"), "getaddrinfo"); qfreeaddrinfo = - (void*)GetProcAddress(GetModuleHandle("ws2_32.dll"), "freeaddrinfo"); + (decltype(qfreeaddrinfo))GetProcAddress(GetModuleHandle("ws2_32.dll"), "freeaddrinfo"); if(!qgetaddrinfo || !qfreeaddrinfo) { qgetaddrinfo = nullptr; diff --git a/Quake/openvr.hpp b/Quake/openvr.hpp index 402b553d..12b35b09 100644 --- a/Quake/openvr.hpp +++ b/Quake/openvr.hpp @@ -898,7 +898,7 @@ enum EVREventType VREvent_ScreenshotTaken = 521, // Sent by compositor to the application // that the screenshot has been taken VREvent_ScreenshotFailed = 522, // Sent by compositor to the application - // that the screenshot failed to be taken + // that the screenshot failed to be taken VREvent_SubmitScreenshotToDashboard = 523, // Sent by compositor to the dashboard that a completed // screenshot was submitted @@ -1964,11 +1964,11 @@ enum EVRTrackedCameraFrameType { VRTrackedCameraFrameType_Distorted = 0, // This is the camera video frame // size in pixels, still distorted. - VRTrackedCameraFrameType_Undistorted, // In pixels, an undistorted - // inscribed rectangle region - // without invalid regions. This - // size is subject to changes - // shortly. + VRTrackedCameraFrameType_Undistorted, // In pixels, an undistorted + // inscribed rectangle region + // without invalid regions. This + // size is subject to changes + // shortly. VRTrackedCameraFrameType_MaximumUndistorted, // In pixels, maximum // undistorted with invalid // regions. Non zero alpha diff --git a/Quake/pch.hpp b/Quake/pch.hpp new file mode 100644 index 00000000..8addd23c --- /dev/null +++ b/Quake/pch.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "quakeglm_macros.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include +#endif + +#include "quakeglm_qvec3.hpp" + +#include diff --git a/Quake/pl_win.cpp b/Quake/pl_win.cpp index 14df5854..321370bb 100644 --- a/Quake/pl_win.cpp +++ b/Quake/pl_win.cpp @@ -24,6 +24,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.hpp" +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + #include #include "platform.hpp" diff --git a/Quake/pr_cmds.cpp b/Quake/pr_cmds.cpp index 39e19d12..427e2260 100644 --- a/Quake/pr_cmds.cpp +++ b/Quake/pr_cmds.cpp @@ -1215,9 +1215,8 @@ static void PF_worldtext_hsettext() sv.getWorldText(wth)._text = text; - forAllActiveOrSpawnedClients([&](client_t& client) { - sv.SendMsg_WorldTextHSetText(client, wth, text); - }); + forAllActiveOrSpawnedClients([&](client_t& client) + { sv.SendMsg_WorldTextHSetText(client, wth, text); }); } static void PF_worldtext_hsetpos() @@ -1233,9 +1232,8 @@ static void PF_worldtext_hsetpos() sv.getWorldText(wth)._pos = pos; - forAllActiveOrSpawnedClients([&](client_t& client) { - sv.SendMsg_WorldTextHSetPos(client, wth, pos); - }); + forAllActiveOrSpawnedClients([&](client_t& client) + { sv.SendMsg_WorldTextHSetPos(client, wth, pos); }); } static void PF_worldtext_hsetangles() @@ -1251,9 +1249,8 @@ static void PF_worldtext_hsetangles() sv.getWorldText(wth)._angles = angles; - forAllActiveOrSpawnedClients([&](client_t& client) { - sv.SendMsg_WorldTextHSetAngles(client, wth, angles); - }); + forAllActiveOrSpawnedClients([&](client_t& client) + { sv.SendMsg_WorldTextHSetAngles(client, wth, angles); }); } static void PF_worldtext_hsethalign() @@ -1271,9 +1268,8 @@ static void PF_worldtext_hsethalign() sv.getWorldText(wth)._hAlign = hAlign; - forAllActiveOrSpawnedClients([&](client_t& client) { - sv.SendMsg_WorldTextHSetHAlign(client, wth, hAlign); - }); + forAllActiveOrSpawnedClients([&](client_t& client) + { sv.SendMsg_WorldTextHSetHAlign(client, wth, hAlign); }); } static void PF_strlen() @@ -1309,7 +1305,8 @@ static void PF_substr() static void PF_calcthrowangle() { // TODO VR: (P2): repetition with `SV_AddGravityImpl` - const auto getGravity = [&](const float entGravity) { + const auto getGravity = [&](const float entGravity) + { extern cvar_t sv_gravity; return (double)entGravity * (double)sv_gravity.value * host_frametime; }; @@ -1782,7 +1779,8 @@ static void PF_droptofloor() qfloat highestZ = std::numeric_limits::lowest(); edict_t* groundEnt = nullptr; - const auto processHit = [&](const qvec3& xyOffset) { + const auto processHit = [&](const qvec3& xyOffset) + { const qvec3 corner = ent.v.origin + xyOffset + qvec3{0, 0, ent.v.mins[2]}; diff --git a/Quake/pr_edict.cpp b/Quake/pr_edict.cpp index 34fa28af..3a9b4cbe 100644 --- a/Quake/pr_edict.cpp +++ b/Quake/pr_edict.cpp @@ -594,13 +594,15 @@ void ED_PrintEdicts() return; } - QCVMGuard qg{&sv.qcvm}; + PR_SwitchQCVM(&sv.qcvm); Con_Printf("%i entities\n", qcvm->num_edicts); for(i = 0; i < qcvm->num_edicts; i++) { ED_PrintNum(i); } + + PR_SwitchQCVM(nullptr); } /* @@ -621,7 +623,7 @@ static void ED_PrintEdict_f() i = Q_atoi(Cmd_Argv(1)); - QCVMGuard qg{&sv.qcvm}; + PR_SwitchQCVM(&sv.qcvm); if(i < 0 || i >= qcvm->num_edicts) { @@ -652,6 +654,8 @@ static void ED_PrintEdict_f() } } } + + PR_SwitchQCVM(nullptr); } /* @@ -675,7 +679,7 @@ static void ED_Count() return; } - QCVMGuard qg{&sv.qcvm}; + PR_SwitchQCVM(&sv.qcvm); active = models = solid = step = 0; for(i = 0; i < qcvm->num_edicts; i++) @@ -705,6 +709,8 @@ static void ED_Count() Con_Printf("view :%3i\n", models); Con_Printf("touch :%3i\n", solid); Con_Printf("step :%3i\n", step); + + PR_SwitchQCVM(nullptr); } @@ -1250,12 +1256,15 @@ globalvars_t* pr_global_struct; void PR_ClearProgs(qcvm_t* vm) { + qcvm_t* oldvm = qcvm; + if(!vm->progs) { return; // wasn't loaded. } - QCVMGuardForce qgf{vm}; + qcvm = nullptr; + PR_SwitchQCVM(vm); PR_ShutdownExtensions(); @@ -1265,6 +1274,9 @@ void PR_ClearProgs(qcvm_t* vm) } free(qcvm->edicts); // ericw -- sv.edicts switched to use malloc() memset(qcvm, 0, sizeof(*qcvm)); + + qcvm = nullptr; + PR_SwitchQCVM(oldvm); } /* diff --git a/Quake/pr_exec.cpp b/Quake/pr_exec.cpp index 3d7193cd..c58ee5ae 100644 --- a/Quake/pr_exec.cpp +++ b/Quake/pr_exec.cpp @@ -178,7 +178,7 @@ void PR_Profile_f() return; } - QCVMGuard qg{&sv.qcvm}; + PR_SwitchQCVM(&sv.qcvm); num = 0; do @@ -205,6 +205,8 @@ void PR_Profile_f() best->profile = 0; } } while(best); + + PR_SwitchQCVM(nullptr); } diff --git a/Quake/pr_ext.cpp b/Quake/pr_ext.cpp index c3ad1fb0..717859a5 100644 --- a/Quake/pr_ext.cpp +++ b/Quake/pr_ext.cpp @@ -8312,7 +8312,7 @@ void PR_AutoCvarChanged(cvar_t* var) if(sv.active) { - QCVMGuard qg{&sv.qcvm}; + PR_SwitchQCVM(&sv.qcvm); n = va("autocvar_%s", var->name); glob = ED_FindGlobal(n); @@ -8323,14 +8323,14 @@ void PR_AutoCvarChanged(cvar_t* var) Con_Warning("EXT: Unable to configure %s\n", n); } } + + PR_SwitchQCVM(nullptr); } if(cl.qcvm.globals) { PR_SwitchQCVM(nullptr); - - QCVMGuard qg{&cl.qcvm}; - + PR_SwitchQCVM(&cl.qcvm); n = va("autocvar_%s", var->name); glob = ED_FindGlobal(n); if(glob) @@ -8340,6 +8340,7 @@ void PR_AutoCvarChanged(cvar_t* var) Con_Warning("EXT: Unable to configure %s\n", n); } } + PR_SwitchQCVM(nullptr); } PR_SwitchQCVM(oldqcvm); diff --git a/Quake/progdefs_generated.hpp b/Quake/progdefs_generated.hpp index f28eeadd..2ddb9656 100644 --- a/Quake/progdefs_generated.hpp +++ b/Quake/progdefs_generated.hpp @@ -1,252 +1,254 @@ -/* File generated by FTEQCC, relevent for engine modding only, the generated crc must be the same as your engine expects. */ +/* File generated by FTEQCC, relevent for engine modding only, the generated crc + * must be the same as your engine expects. */ typedef struct globalvars_s -{ int pad; - int ofs_return[3]; - int ofs_parm0[3]; - int ofs_parm1[3]; - int ofs_parm2[3]; - int ofs_parm3[3]; - int ofs_parm4[3]; - int ofs_parm5[3]; - int ofs_parm6[3]; - int ofs_parm7[3]; - int self; - int other; - int world; - float time; - float frametime; - float force_retouch; - string_t mapname; - float deathmatch; - float coop; - float teamplay; - float serverflags; - float total_secrets; - float total_monsters; - float found_secrets; - float killed_monsters; - float spawnServerFromSaveFile; - float parm1; - float parm2; - float parm3; - float parm4; - float parm5; - float parm6; - float parm7; - float parm8; - float parm9; - float parm10; - float parm11; - float parm12; - float parm13; - float parm14; - float parm15; - float parm16; - float parm17; - float parm18; - float parm19; - float parm20; - float parm21; - float parm22; - float parm23; - float parm24; - float parm25; - float parm26; - float parm27; - float parm28; - float parm29; - float parm30; - float parm31; - float parm32; - float parm33; - float parm34; - float parm35; - float parm36; - float parm37; - float parm38; - float parm39; - float parm40; - vec3_t v_forward; - vec3_t v_up; - vec3_t v_right; - float trace_allsolid; - float trace_startsolid; - float trace_fraction; - vec3_t trace_endpos; - vec3_t trace_plane_normal; - float trace_plane_dist; - int trace_ent; - float trace_inopen; - float trace_inwater; - int msg_entity; - func_t main; - func_t StartFrame; - func_t PlayerPreThink; - func_t PlayerPostThink; - func_t ClientKill; - func_t ClientConnect; - func_t PutClientInServer; - func_t ClientDisconnect; - func_t SetNewParms; - func_t SetChangeParms; - func_t OnSpawnServerBeforeLoad; - func_t OnSpawnServerAfterLoad; - func_t OnLoadGame; +{ + int pad; + int ofs_return[3]; + int ofs_parm0[3]; + int ofs_parm1[3]; + int ofs_parm2[3]; + int ofs_parm3[3]; + int ofs_parm4[3]; + int ofs_parm5[3]; + int ofs_parm6[3]; + int ofs_parm7[3]; + int self; + int other; + int world; + float time; + float frametime; + float force_retouch; + string_t mapname; + float deathmatch; + float coop; + float teamplay; + float serverflags; + float total_secrets; + float total_monsters; + float found_secrets; + float killed_monsters; + float spawnServerFromSaveFile; + float parm1; + float parm2; + float parm3; + float parm4; + float parm5; + float parm6; + float parm7; + float parm8; + float parm9; + float parm10; + float parm11; + float parm12; + float parm13; + float parm14; + float parm15; + float parm16; + float parm17; + float parm18; + float parm19; + float parm20; + float parm21; + float parm22; + float parm23; + float parm24; + float parm25; + float parm26; + float parm27; + float parm28; + float parm29; + float parm30; + float parm31; + float parm32; + float parm33; + float parm34; + float parm35; + float parm36; + float parm37; + float parm38; + float parm39; + float parm40; + vec3_t v_forward; + vec3_t v_up; + vec3_t v_right; + float trace_allsolid; + float trace_startsolid; + float trace_fraction; + vec3_t trace_endpos; + vec3_t trace_plane_normal; + float trace_plane_dist; + int trace_ent; + float trace_inopen; + float trace_inwater; + int msg_entity; + func_t main; + func_t StartFrame; + func_t PlayerPreThink; + func_t PlayerPostThink; + func_t ClientKill; + func_t ClientConnect; + func_t PutClientInServer; + func_t ClientDisconnect; + func_t SetNewParms; + func_t SetChangeParms; + func_t OnSpawnServerBeforeLoad; + func_t OnSpawnServerAfterLoad; + func_t OnLoadGame; } globalvars_t; typedef struct entvars_s { - float modelindex; - vec3_t absmin; - vec3_t absmax; - float ltime; - float movetype; - float solid; - vec3_t origin; - vec3_t oldorigin; - vec3_t velocity; - vec3_t angles; - vec3_t avelocity; - vec3_t punchangle; - string_t classname; - string_t model; - float frame; - float skin; - float effects; - vec3_t mins; - vec3_t maxs; - vec3_t size; - func_t touch; - func_t use; - func_t think; - func_t blocked; - float nextthink; - int groundentity; - float health; - float frags; - float weapon; - string_t weaponmodel; - float weaponframe; - float currentammo; - float ammocounter; - float ammo_shells; - float ammo_nails; - float ammo_rockets; - float ammo_cells; - float items; - float takedamage; - int chain; - float deadflag; - vec3_t view_ofs; - float button0; - float button1; - float button2; - float impulse; - float fixangle; - vec3_t v_angle; - float idealpitch; - string_t netname; - int enemy; - float flags; - float colormap; - float team; - float max_health; - float teleport_time; - float armortype; - float armorvalue; - float waterlevel; - float watertype; - float lastwatertime; - float ideal_yaw; - float yaw_speed; - int aiment; - int goalentity; - float spawnflags; - string_t target; - string_t targetname; - float dmg_take; - float dmg_save; - int dmg_inflictor; - int owner; - vec3_t movedir; - string_t message; - float sounds; - string_t noise; - string_t noise1; - string_t noise2; - string_t noise3; - vec3_t v_viewangle; - vec3_t model_scale; - vec3_t model_scale_origin; - vec3_t model_offset; - float vr_itemId; - func_t handtouch; - func_t vr_wpntouch; - func_t think2; - float nextthink2; - float weaponflags; - float weapon2; - string_t weaponmodel2; - float weaponframe2; - float weaponflags2; - float weaponclip; - float weaponclip2; - float holsterweaponclip0; - float holsterweaponclip1; - float holsterweaponclip2; - float holsterweaponclip3; - float holsterweaponclip4; - float holsterweaponclip5; - float weaponclipsize; - float weaponclipsize2; - float holsterweapon0; - float holsterweapon1; - float holsterweapon2; - float holsterweapon3; - float holsterweapon4; - float holsterweapon5; - string_t holsterweaponmodel0; - string_t holsterweaponmodel1; - string_t holsterweaponmodel2; - string_t holsterweaponmodel3; - string_t holsterweaponmodel4; - string_t holsterweaponmodel5; - float holsterweaponflags0; - float holsterweaponflags1; - float holsterweaponflags2; - float holsterweaponflags3; - float holsterweaponflags4; - float holsterweaponflags5; - float offhand_hotspot; - float mainhand_hotspot; - float currentammo2; - float ammocounter2; - float button3; - float vryaw; - vec3_t handpos; - vec3_t handrot; - vec3_t handvel; - vec3_t handthrowvel; - float handvelmag; - vec3_t handavel; - vec3_t offhandpos; - vec3_t offhandrot; - vec3_t offhandvel; - vec3_t offhandthrowvel; - float offhandvelmag; - vec3_t offhandavel; - vec3_t headvel; - vec3_t muzzlepos; - vec3_t offmuzzlepos; - float vrbits0; - vec3_t teleport_target; - vec3_t roomscalemove; - float touchinghand; - float handtouch_hand; - int handtouch_ent; - float ishuman; + float modelindex; + vec3_t absmin; + vec3_t absmax; + float ltime; + float movetype; + float solid; + vec3_t origin; + vec3_t oldorigin; + vec3_t velocity; + vec3_t angles; + vec3_t avelocity; + vec3_t punchangle; + string_t classname; + string_t model; + float frame; + float skin; + float effects; + vec3_t mins; + vec3_t maxs; + vec3_t size; + func_t touch; + func_t use; + func_t think; + func_t blocked; + float nextthink; + int groundentity; + float health; + float frags; + float weapon; + string_t weaponmodel; + float weaponframe; + float currentammo; + float ammocounter; + float ammo_shells; + float ammo_nails; + float ammo_rockets; + float ammo_cells; + float items; + float takedamage; + int chain; + float deadflag; + vec3_t view_ofs; + float button0; + float button1; + float button2; + float impulse; + float fixangle; + vec3_t v_angle; + float idealpitch; + string_t netname; + int enemy; + float flags; + float colormap; + float team; + float max_health; + float teleport_time; + float armortype; + float armorvalue; + float waterlevel; + float watertype; + float lastwatertime; + float ideal_yaw; + float yaw_speed; + int aiment; + int goalentity; + float spawnflags; + string_t target; + string_t targetname; + float dmg_take; + float dmg_save; + int dmg_inflictor; + int owner; + vec3_t movedir; + string_t message; + float sounds; + string_t noise; + string_t noise1; + string_t noise2; + string_t noise3; + vec3_t v_viewangle; + vec3_t model_scale; + vec3_t model_scale_origin; + vec3_t model_offset; + float vr_itemId; + func_t handtouch; + func_t vr_wpntouch; + func_t think2; + float nextthink2; + float weaponflags; + float weapon2; + string_t weaponmodel2; + float weaponframe2; + float weaponflags2; + float weaponclip; + float weaponclip2; + float holsterweaponclip0; + float holsterweaponclip1; + float holsterweaponclip2; + float holsterweaponclip3; + float holsterweaponclip4; + float holsterweaponclip5; + float weaponclipsize; + float weaponclipsize2; + float holsterweapon0; + float holsterweapon1; + float holsterweapon2; + float holsterweapon3; + float holsterweapon4; + float holsterweapon5; + string_t holsterweaponmodel0; + string_t holsterweaponmodel1; + string_t holsterweaponmodel2; + string_t holsterweaponmodel3; + string_t holsterweaponmodel4; + string_t holsterweaponmodel5; + float holsterweaponflags0; + float holsterweaponflags1; + float holsterweaponflags2; + float holsterweaponflags3; + float holsterweaponflags4; + float holsterweaponflags5; + float offhand_hotspot; + float mainhand_hotspot; + float currentammo2; + float ammocounter2; + float button3; + float vryaw; + vec3_t handpos; + vec3_t handrot; + vec3_t handvel; + vec3_t handthrowvel; + float handvelmag; + vec3_t handavel; + vec3_t offhandpos; + vec3_t offhandrot; + vec3_t offhandvel; + vec3_t offhandthrowvel; + float offhandvelmag; + vec3_t offhandavel; + vec3_t headvel; + vec3_t muzzlepos; + vec3_t offmuzzlepos; + float vrbits0; + vec3_t teleport_target; + vec3_t roomscalemove; + float touchinghand; + float handtouch_hand; + int handtouch_ent; + float ishuman; } entvars_t; #define PROGHEADER_CRC 52440 diff --git a/Quake/protocol.hpp b/Quake/protocol.hpp index ac2acd7a..05e3ccbb 100644 --- a/Quake/protocol.hpp +++ b/Quake/protocol.hpp @@ -87,7 +87,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define PEXT2_PRYDONCURSOR 0x00000001 // a mouse cursor exposed to ssqc #define PEXT2_VOICECHAT \ 0x00000002 //+voip or cl_voip_send 1; requires opus dll, and others to also - //have that same dll. + // have that same dll. #define PEXT2_SETANGLEDELTA 0x00000004 // less annoying when teleporting. #define PEXT2_REPLACEMENTDELTAS \ 0x00000008 // more compact entity deltas (can also be split across multiple @@ -520,8 +520,8 @@ struct entity_state_t unsigned short modelindex; // johnfitz -- was int unsigned short frame; // johnfitz -- was int unsigned int effects; - unsigned char colormap; // johnfitz -- was int - unsigned char skin; // johnfitz -- was int + unsigned char colormap; // johnfitz -- was int + unsigned char skin; // johnfitz -- was int unsigned char scale; // spike -- *16 unsigned char pmovetype; // spike unsigned short diff --git a/Quake/q_stdinc.hpp b/Quake/q_stdinc.hpp index bb650b7b..0f6cac5f 100644 --- a/Quake/q_stdinc.hpp +++ b/Quake/q_stdinc.hpp @@ -29,14 +29,14 @@ #pragma once #include -#include -#include +#include +#include #ifndef _WIN32 /* others we support without sys/param.h? */ #include #endif -#include +#include /* NOTES on TYPE SIZES: Quake/Hexen II engine relied on 32 bit int type size @@ -58,13 +58,13 @@ * version 2010. Even in VS2010, there is no inttypes.h.. */ #include "msinttypes/stdint.hpp" #else -#include +#include #endif -#include -#include +#include +#include #include -#include +#include /*==========================================================================*/ @@ -81,11 +81,11 @@ /* Make sure the types really have the right * sizes: These macros are from SDL headers. */ -static_assert(sizeof(char) == 1, ""); -static_assert(sizeof(float) == 4, ""); -static_assert(sizeof(long) >= 4, ""); -static_assert(sizeof(int) == 4, ""); -static_assert(sizeof(short) == 2, ""); +static_assert(sizeof(char) == 1); +static_assert(sizeof(float) == 4); +static_assert(sizeof(long) >= 4); +static_assert(sizeof(int) == 4); +static_assert(sizeof(short) == 2); /* make sure enums are the size of ints for structure packing */ typedef enum diff --git a/Quake/qcvm.cpp b/Quake/qcvm.cpp index 5bec060b..4dab689a 100644 --- a/Quake/qcvm.cpp +++ b/Quake/qcvm.cpp @@ -24,25 +24,3 @@ void PR_SwitchQCVM(qcvm_t* nvm) pr_global_struct = nullptr; } } - -QCVMGuard::QCVMGuard(qcvm_t* newQcvm) : d_oldQcvm(qcvm) -{ - PR_SwitchQCVM(newQcvm); -} - -QCVMGuard::~QCVMGuard() -{ - PR_SwitchQCVM(d_oldQcvm); -} - -QCVMGuardForce::QCVMGuardForce(qcvm_t* newQcvm) : d_oldQcvm(qcvm) -{ - PR_SwitchQCVM(nullptr); - PR_SwitchQCVM(newQcvm); -} - -QCVMGuardForce::~QCVMGuardForce() -{ - PR_SwitchQCVM(nullptr); - PR_SwitchQCVM(d_oldQcvm); -} diff --git a/Quake/qcvm.hpp b/Quake/qcvm.hpp index e19a6b64..13850aad 100644 --- a/Quake/qcvm.hpp +++ b/Quake/qcvm.hpp @@ -69,25 +69,3 @@ struct qcvm_t extern qcvm_t* qcvm; void PR_SwitchQCVM(qcvm_t* nvm); - -struct QCVMGuard -{ - qcvm_t* d_oldQcvm; - - [[nodiscard]] explicit QCVMGuard(qcvm_t* newQcvm); - ~QCVMGuard(); - - QCVMGuard(const QCVMGuard&) = delete; - QCVMGuard(QCVMGuard&&) = delete; -}; - -struct QCVMGuardForce -{ - qcvm_t* d_oldQcvm; - - [[nodiscard]] explicit QCVMGuardForce(qcvm_t* newQcvm); - ~QCVMGuardForce(); - - QCVMGuardForce(const QCVMGuardForce&) = delete; - QCVMGuardForce(QCVMGuard&&) = delete; -}; diff --git a/Quake/quakedef_macros.hpp b/Quake/quakedef_macros.hpp index 82e1fe9a..e23c803d 100644 --- a/Quake/quakedef_macros.hpp +++ b/Quake/quakedef_macros.hpp @@ -36,7 +36,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define FITZQUAKE_VERSION 0.85 // johnfitz #define QUAKESPASM_VERSION 0.93 -#define QUAKEVR_VERSION "0.0.6" +#define QUAKEVR_VERSION "0.0.7" #define QUAKESPASM_VER_PATCH 2 // helper to print a string like 0.93.2 #ifndef QUAKESPASM_VER_SUFFIX #define QUAKESPASM_VER_SUFFIX // optional version suffix string literal like @@ -296,16 +296,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Quake VR - vrbits0 bits // clang-format off -#define QVR_VRBITS0_TELEPORTING VRUTIL_POWER_OF_TWO(0) -#define QVR_VRBITS0_OFFHAND_GRABBING VRUTIL_POWER_OF_TWO(1) -#define QVR_VRBITS0_OFFHAND_PREVGRABBING VRUTIL_POWER_OF_TWO(2) -#define QVR_VRBITS0_MAINHAND_GRABBING VRUTIL_POWER_OF_TWO(3) -#define QVR_VRBITS0_MAINHAND_PREVGRABBING VRUTIL_POWER_OF_TWO(4) -#define QVR_VRBITS0_2H_AIMING VRUTIL_POWER_OF_TWO(5) -#define QVR_VRBITS0_OFFHAND_RELOADING VRUTIL_POWER_OF_TWO(6) -#define QVR_VRBITS0_OFFHAND_PREVRELOADING VRUTIL_POWER_OF_TWO(7) -#define QVR_VRBITS0_MAINHAND_RELOADING VRUTIL_POWER_OF_TWO(8) -#define QVR_VRBITS0_MAINHAND_PREVRELOADING VRUTIL_POWER_OF_TWO(9) +#define QVR_VRBITS0_TELEPORTING VRUTIL_POWER_OF_TWO(0) +#define QVR_VRBITS0_OFFHAND_GRABBING VRUTIL_POWER_OF_TWO(1) +#define QVR_VRBITS0_OFFHAND_PREVGRABBING VRUTIL_POWER_OF_TWO(2) +#define QVR_VRBITS0_MAINHAND_GRABBING VRUTIL_POWER_OF_TWO(3) +#define QVR_VRBITS0_MAINHAND_PREVGRABBING VRUTIL_POWER_OF_TWO(4) +#define QVR_VRBITS0_2H_AIMING VRUTIL_POWER_OF_TWO(5) +#define QVR_VRBITS0_OFFHAND_RELOADING VRUTIL_POWER_OF_TWO(6) +#define QVR_VRBITS0_OFFHAND_PREVRELOADING VRUTIL_POWER_OF_TWO(7) +#define QVR_VRBITS0_MAINHAND_RELOADING VRUTIL_POWER_OF_TWO(8) +#define QVR_VRBITS0_MAINHAND_PREVRELOADING VRUTIL_POWER_OF_TWO(9) +#define QVR_VRBITS0_OFFHAND_RELOADFLICKING VRUTIL_POWER_OF_TWO(10) +#define QVR_VRBITS0_OFFHAND_PREVRELOADFLICKING VRUTIL_POWER_OF_TWO(11) +#define QVR_VRBITS0_MAINHAND_RELOADFLICKING VRUTIL_POWER_OF_TWO(12) +#define QVR_VRBITS0_MAINHAND_PREVRELOADFLICKING VRUTIL_POWER_OF_TWO(13) + // clang-format on #define MAX_SCOREBOARD 255 diff --git a/Quake/quakeglm.hpp b/Quake/quakeglm.hpp index a7a81d89..bdb406cc 100644 --- a/Quake/quakeglm.hpp +++ b/Quake/quakeglm.hpp @@ -1,5 +1,6 @@ #pragma once +#include #ifdef __GNUC__ #pragma GCC diagnostic push diff --git a/Quake/quakeglm_qvec3.cpp b/Quake/quakeglm_qvec3.cpp new file mode 100644 index 00000000..2749f3bc --- /dev/null +++ b/Quake/quakeglm_qvec3.cpp @@ -0,0 +1 @@ +#include "quakeglm_qvec3.hpp" diff --git a/Quake/r_part.cpp b/Quake/r_part.cpp index 218ce162..70add374 100644 --- a/Quake/r_part.cpp +++ b/Quake/r_part.cpp @@ -224,7 +224,8 @@ class ParticleBufferSOA _aliveCount = 0; _maxParticles = maxParticles; - const auto alloc = [&](auto& field, const char* name) { + const auto alloc = [&](auto& field, const char* name) + { using Type = std::remove_pointer_t>; field = Hunk_AllocName(_maxParticles, name); }; @@ -243,12 +244,14 @@ class ParticleBufferSOA { _aliveCount = index_remove_if( 0, _aliveCount, - [&](const std::size_t i) { + [&](const std::size_t i) + { return _pSOA._colors[i].a <= 0.f // || _pSOA._scales[i] <= 0.f // || cl.time >= _pSOA._datas[i]._die; }, - [&](const std::size_t targetIdx, const std::size_t srcIdx) { + [&](const std::size_t targetIdx, const std::size_t srcIdx) + { _pSOA._orgs[targetIdx] = std::move(_pSOA._orgs[srcIdx]); _pSOA._vels[targetIdx] = std::move(_pSOA._vels[srcIdx]); _pSOA._accs[targetIdx] = std::move(_pSOA._accs[srcIdx]); @@ -316,7 +319,8 @@ ImageData stitchImageData(const ImageData& a, const ImageData& b) const auto numBytes = numPixels * 4; const auto idx = [](const int width, const int height, const int depth, - const int x, const int y, const int z) { + const int x, const int y, const int z) + { return (width * y + x) * 4 + z; return x + height * (y + width * z); return x + width * (y + depth * z); @@ -324,7 +328,8 @@ ImageData stitchImageData(const ImageData& a, const ImageData& b) byte* data = Hunk_Alloc(numBytes); - const auto doPic = [&](const int xOffset, const auto& pic) { + const auto doPic = [&](const int xOffset, const auto& pic) + { for(int x = 0; x < pic.width; ++x) { for(int y = 0; y < pic.height; ++y) @@ -359,13 +364,14 @@ template const auto numBytes = numPixels * 4; const auto idx = [](const int width, const int depth, const int x, - const int y, - const int z) { return (width * y + x) * depth + z; }; + const int y, const int z) + { return (width * y + x) * depth + z; }; byte* data = Hunk_Alloc(numBytes); std::vector imageInfo; - const auto blit = [&](const int xOffset, const auto& pic) { + const auto blit = [&](const int xOffset, const auto& pic) + { imageInfo.emplace_back(xOffset); imageInfo.emplace_back(0); imageInfo.emplace_back(pic.width); @@ -700,17 +706,20 @@ void R_InitParticleTextures() static byte particle2_data[2 * 2 * 4]; static byte particle3_data[64 * 64 * 4]; - const auto circleImageData = [&] { + const auto circleImageData = [&] + { buildCircleTexture(particle1_data); return ImageData{particle1_data, 64, 64}; }(); - const auto squareImageData = [&] { + const auto squareImageData = [&] + { buildSquareTexture(particle2_data); return ImageData{particle2_data, 2, 2}; }(); - const auto blobImageData = [&] { + const auto blobImageData = [&] + { buildBlobTexture(particle3_data); return ImageData{particle3_data, 64, 64}; }(); @@ -807,24 +816,26 @@ void R_EntityParticles(entity_t* ent) forward[1] = cp * sy; forward[2] = -sp; - makeNParticles(ptxAtlas, 1, [&](PHandle p) { - p.atlasIdx() = aiCircle; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(255); - p.die() = cl.time + 0.01; - p.setColor(0x6f); - p.type() = pt_explode; - p.scale() = 1.f; - setAccGrav(p); + makeNParticles(ptxAtlas, 1, + [&](PHandle p) + { + p.atlasIdx() = aiCircle; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(255); + p.die() = cl.time + 0.01; + p.setColor(0x6f); + p.type() = pt_explode; + p.scale() = 1.f; + setAccGrav(p); - constexpr float dist = 64; - p.org()[0] = ent->origin[0] + r_avertexnormals[i][0] * dist + - forward[0] * beamlength; - p.org()[1] = ent->origin[1] + r_avertexnormals[i][1] * dist + - forward[1] * beamlength; - p.org()[2] = ent->origin[2] + r_avertexnormals[i][2] * dist + - forward[2] * beamlength; - }); + constexpr float dist = 64; + p.org()[0] = ent->origin[0] + r_avertexnormals[i][0] * dist + + forward[0] * beamlength; + p.org()[1] = ent->origin[1] + r_avertexnormals[i][1] * dist + + forward[1] * beamlength; + p.org()[2] = ent->origin[2] + r_avertexnormals[i][2] * dist + + forward[2] * beamlength; + }); } } @@ -876,19 +887,21 @@ void R_ReadPointFile_f() c++; - makeNParticles(ptxAtlas, 1, [&](PHandle p) { - p.atlasIdx() = aiCircle; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(255); - p.die() = 99999; - p.setColor((-c) & 15); - p.type() = pt_static; - p.scale() = 1.f; - setAccGrav(p); + makeNParticles(ptxAtlas, 1, + [&](PHandle p) + { + p.atlasIdx() = aiCircle; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(255); + p.die() = 99999; + p.setColor((-c) & 15); + p.type() = pt_static; + p.scale() = 1.f; + setAccGrav(p); - p.vel() = vec3_zero; - p.org() = org; - }); + p.vel() = vec3_zero; + p.org() = org; + }); } fclose(f); @@ -948,97 +961,107 @@ R_ParticleExplosion */ void R_ParticleExplosion(const qvec3& org) { - makeNParticlesI(ptxAtlas, 256, [&](const int i, PHandle p) { - p.atlasIdx() = aiCircle; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(255); - p.die() = cl.time + 1.5; - p.setColor(ramp1[0]); - p.ramp() = rand() & 3; - p.scale() = rnd(0.6f, 1.2f); - setAccGrav(p); - p.type() = i & 1 ? pt_explode : pt_explode2; - - for(int j = 0; j < 3; j++) + makeNParticlesI(ptxAtlas, 256, + [&](const int i, PHandle p) { - p.org()[j] = org[j] + rnd(-16, 16); - p.vel()[j] = rnd(-256, 256); - } - }); - - makeNParticlesI(ptxAtlas, 64, [&](const int, PHandle p) { - p.atlasIdx() = aiSpark; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(255); - p.die() = cl.time + 1.5; - p.setColor(ramp1[0]); - p.ramp() = rand() & 3; - p.scale() = rnd(1.9f, 2.9f) * 0.55f; - setAccGrav(p); - p.type() = pt_rock; - p.param0() = rndi(0, 2); // rotation direction - - for(int j = 0; j < 3; j++) + p.atlasIdx() = aiCircle; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(255); + p.die() = cl.time + 1.5; + p.setColor(ramp1[0]); + p.ramp() = rand() & 3; + p.scale() = rnd(0.6f, 1.2f); + setAccGrav(p); + p.type() = i & 1 ? pt_explode : pt_explode2; + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + rnd(-16, 16); + p.vel()[j] = rnd(-256, 256); + } + }); + + makeNParticlesI(ptxAtlas, 64, + [&](const int, PHandle p) { - p.org()[j] = org[j] + rnd(-16, 16); - p.vel()[j] = rnd(-256, 256); - } - }); - - makeNParticlesI(ptxAtlas, 48, [&](const int, PHandle p) { - p.atlasIdx() = aiRock; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(255); - p.die() = cl.time + 1.5; - p.setColor(167 + (rand() & 7)); - p.ramp() = rand() & 3; - p.scale() = rnd(0.9f, 1.9f); - setAccGrav(p); - p.type() = pt_rock; - p.param0() = rndi(0, 2); // rotation direction - - for(int j = 0; j < 3; j++) + p.atlasIdx() = aiSpark; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(255); + p.die() = cl.time + 1.5; + p.setColor(ramp1[0]); + p.ramp() = rand() & 3; + p.scale() = rnd(1.9f, 2.9f) * 0.55f; + setAccGrav(p); + p.type() = pt_rock; + p.param0() = rndi(0, 2); // rotation direction + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + rnd(-16, 16); + p.vel()[j] = rnd(-256, 256); + } + }); + + makeNParticlesI(ptxAtlas, 48, + [&](const int, PHandle p) { - p.org()[j] = org[j] + rnd(-16, 16); - p.vel()[j] = rnd(-256, 256); - } - }); - - makeNParticles(ptxAtlas, 1, [&](PHandle p) { - p.atlasIdx() = aiExplosion; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(255); - p.die() = cl.time + 1.5; - p.setColor(ramp1[0]); - p.ramp() = rand() & 3; - p.scale() = rnd(0.5f, 2.1f) * 2.f; - setAccGrav(p, 0.05f); - p.type() = pt_txexplode; - p.param0() = rndi(0, 2); // rotation direction - - for(int j = 0; j < 3; j++) + p.atlasIdx() = aiRock; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(255); + p.die() = cl.time + 1.5; + p.setColor(167 + (rand() & 7)); + p.ramp() = rand() & 3; + p.scale() = rnd(0.9f, 1.9f); + setAccGrav(p); + p.type() = pt_rock; + p.param0() = rndi(0, 2); // rotation direction + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + rnd(-16, 16); + p.vel()[j] = rnd(-256, 256); + } + }); + + makeNParticles(ptxAtlas, 1, + [&](PHandle p) { - p.org()[j] = org[j] + rnd(-11, 11); - p.vel()[j] = rnd(-8, 8); - } - }); - - makeNParticles(ptxAtlas, 3, [&](PHandle p) { - p.atlasIdx() = aiSmoke; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(225); - p.die() = cl.time + 3.5; - p.setColor(rand() & 7); - p.scale() = rnd(1.2f, 1.5f); - p.type() = pt_txsmoke; - setAccGrav(p, -0.09f); - - for(int j = 0; j < 3; j++) + p.atlasIdx() = aiExplosion; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(255); + p.die() = cl.time + 1.5; + p.setColor(ramp1[0]); + p.ramp() = rand() & 3; + p.scale() = rnd(0.5f, 2.1f) * 2.f; + setAccGrav(p, 0.05f); + p.type() = pt_txexplode; + p.param0() = rndi(0, 2); // rotation direction + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + rnd(-11, 11); + p.vel()[j] = rnd(-8, 8); + } + }); + + makeNParticles(ptxAtlas, 3, + [&](PHandle p) { - p.org()[j] = org[j] + ((rand() & 7) - 4); - p.vel()[j] = rnd(-24, 24); - } - }); + p.atlasIdx() = aiSmoke; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(225); + p.die() = cl.time + 3.5; + p.setColor(rand() & 7); + p.scale() = rnd(1.2f, 1.5f); + p.type() = pt_txsmoke; + setAccGrav(p, -0.09f); + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + ((rand() & 7) - 4); + p.vel()[j] = rnd(-24, 24); + } + }); } /* @@ -1050,97 +1073,107 @@ void R_ParticleExplosion2(const qvec3& org, int colorStart, int colorLength) { int colorMod = 0; - makeNParticlesI(ptxAtlas, 256, [&](const int, PHandle p) { - p.atlasIdx() = aiCircle; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(255); - p.die() = cl.time + 1.5; - p.setColor(colorStart + (colorMod % colorLength)); - p.scale() = rnd(1.6f, 3.5f); - colorMod++; - setAccGrav(p); - p.type() = pt_blob; - - for(int j = 0; j < 3; j++) + makeNParticlesI(ptxAtlas, 256, + [&](const int, PHandle p) { - p.org()[j] = org[j] + rnd(-16, 16); - p.vel()[j] = rnd(-256, 256); - } - }); - - makeNParticlesI(ptxAtlas, 64, [&](const int, PHandle p) { - p.atlasIdx() = aiSpark; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(255); - p.die() = cl.time + 1.5; - p.setColor(ramp1[0]); - p.ramp() = rand() & 3; - p.scale() = rnd(1.9f, 2.9f) * 0.55f; - setAccGrav(p); - p.type() = pt_rock; - p.param0() = rndi(0, 2); // rotation direction - - for(int j = 0; j < 3; j++) + p.atlasIdx() = aiCircle; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(255); + p.die() = cl.time + 1.5; + p.setColor(colorStart + (colorMod % colorLength)); + p.scale() = rnd(1.6f, 3.5f); + colorMod++; + setAccGrav(p); + p.type() = pt_blob; + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + rnd(-16, 16); + p.vel()[j] = rnd(-256, 256); + } + }); + + makeNParticlesI(ptxAtlas, 64, + [&](const int, PHandle p) { - p.org()[j] = org[j] + rnd(-16, 16); - p.vel()[j] = rnd(-256, 256); - } - }); - - makeNParticlesI(ptxAtlas, 48, [&](const int, PHandle p) { - p.atlasIdx() = aiRock; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(255); - p.die() = cl.time + 1.5; - p.setColor(167 + (rand() & 7)); - p.ramp() = rand() & 3; - p.scale() = rnd(0.9f, 1.9f); - setAccGrav(p); - p.type() = pt_rock; - p.param0() = rndi(0, 2); // rotation direction - - for(int j = 0; j < 3; j++) + p.atlasIdx() = aiSpark; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(255); + p.die() = cl.time + 1.5; + p.setColor(ramp1[0]); + p.ramp() = rand() & 3; + p.scale() = rnd(1.9f, 2.9f) * 0.55f; + setAccGrav(p); + p.type() = pt_rock; + p.param0() = rndi(0, 2); // rotation direction + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + rnd(-16, 16); + p.vel()[j] = rnd(-256, 256); + } + }); + + makeNParticlesI(ptxAtlas, 48, + [&](const int, PHandle p) { - p.org()[j] = org[j] + rnd(-16, 16); - p.vel()[j] = rnd(-256, 256); - } - }); - - makeNParticles(ptxAtlas, 1, [&](PHandle p) { - p.atlasIdx() = aiExplosion; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(255); - p.die() = cl.time + 1.5; - p.setColor(colorStart + (colorMod % colorLength)); - p.ramp() = rand() & 3; - p.scale() = rnd(0.5f, 2.1f) * 2.f; - setAccGrav(p, 0.05f); - p.type() = pt_txexplode; - p.param0() = rndi(0, 2); // rotation direction - - for(int j = 0; j < 3; j++) + p.atlasIdx() = aiRock; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(255); + p.die() = cl.time + 1.5; + p.setColor(167 + (rand() & 7)); + p.ramp() = rand() & 3; + p.scale() = rnd(0.9f, 1.9f); + setAccGrav(p); + p.type() = pt_rock; + p.param0() = rndi(0, 2); // rotation direction + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + rnd(-16, 16); + p.vel()[j] = rnd(-256, 256); + } + }); + + makeNParticles(ptxAtlas, 1, + [&](PHandle p) { - p.org()[j] = org[j] + rnd(-11, 11); - p.vel()[j] = rnd(-8, 8); - } - }); - - makeNParticles(ptxAtlas, 3, [&](PHandle p) { - p.atlasIdx() = aiSmoke; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(225); - p.die() = cl.time + 3.5; - p.setColor(rand() & 7); - p.scale() = rnd(1.2f, 1.5f); - p.type() = pt_txsmoke; - setAccGrav(p, -0.09f); - - for(int j = 0; j < 3; j++) + p.atlasIdx() = aiExplosion; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(255); + p.die() = cl.time + 1.5; + p.setColor(colorStart + (colorMod % colorLength)); + p.ramp() = rand() & 3; + p.scale() = rnd(0.5f, 2.1f) * 2.f; + setAccGrav(p, 0.05f); + p.type() = pt_txexplode; + p.param0() = rndi(0, 2); // rotation direction + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + rnd(-11, 11); + p.vel()[j] = rnd(-8, 8); + } + }); + + makeNParticles(ptxAtlas, 3, + [&](PHandle p) { - p.org()[j] = org[j] + ((rand() & 7) - 4); - p.vel()[j] = rnd(-24, 24); - } - }); + p.atlasIdx() = aiSmoke; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(225); + p.die() = cl.time + 3.5; + p.setColor(rand() & 7); + p.scale() = rnd(1.2f, 1.5f); + p.type() = pt_txsmoke; + setAccGrav(p, -0.09f); + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + ((rand() & 7) - 4); + p.vel()[j] = rnd(-24, 24); + } + }); } void R_RunParticleEffect_BulletPuff( @@ -1150,78 +1183,86 @@ void R_RunParticleEffect_BulletPuff( const auto dustCount = count * 0.7f; const auto sparkCount = count * 0.4f; - makeNParticles(ptxAtlas, debrisCount, [&](PHandle p) { - p.atlasIdx() = aiRock; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(255); - p.die() = cl.time + 0.7 * (rand() % 5); - p.setColor((color & ~7) + (rand() & 7)); - p.scale() = rnd(0.5f, 0.9f); - p.type() = pt_rock; - p.param0() = rndi(0, 2); // rotation direction - setAccGrav(p, 0.26f); - - for(int j = 0; j < 3; j++) + makeNParticles(ptxAtlas, debrisCount, + [&](PHandle p) { - p.org()[j] = org[j] + ((rand() & 7) - 4); - p.vel()[j] = (dir[j] + 0.3f) * rnd(-75, 75); - } - }); - - makeNParticles(ptxAtlas, 1, [&](PHandle p) { - p.atlasIdx() = aiSmoke; - p.setAlpha(45); - p.die() = cl.time + 1.25 * (rand() % 5); - p.setColor(rand() & 7); - p.scale() = rnd(0.3f, 0.5f); - p.type() = pt_txsmoke; - setAccGrav(p, -0.09f); - - for(int j = 0; j < 3; j++) + p.atlasIdx() = aiRock; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(255); + p.die() = cl.time + 0.7 * (rand() % 5); + p.setColor((color & ~7) + (rand() & 7)); + p.scale() = rnd(0.5f, 0.9f); + p.type() = pt_rock; + p.param0() = rndi(0, 2); // rotation direction + setAccGrav(p, 0.26f); + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + ((rand() & 7) - 4); + p.vel()[j] = (dir[j] + 0.3f) * rnd(-75, 75); + } + }); + + makeNParticles(ptxAtlas, 1, + [&](PHandle p) { - p.org()[j] = org[j] + ((rand() & 4) - 2); - p.vel()[j] = rnd(-12, 12); - } - }); - - makeNParticles(ptxAtlas, dustCount, [&](PHandle p) { - p.atlasIdx() = aiCircle; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(255); - p.die() = cl.time + 0.75 * (rand() % 5); - p.setColor((color & ~7) + (rand() & 7)); - p.scale() = rnd(0.05f, 0.3f); - p.type() = pt_static; - setAccGrav(p, 0.08f); - - for(int j = 0; j < 3; j++) + p.atlasIdx() = aiSmoke; + p.setAlpha(45); + p.die() = cl.time + 1.25 * (rand() % 5); + p.setColor(rand() & 7); + p.scale() = rnd(0.3f, 0.5f); + p.type() = pt_txsmoke; + setAccGrav(p, -0.09f); + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + ((rand() & 4) - 2); + p.vel()[j] = rnd(-12, 12); + } + }); + + makeNParticles(ptxAtlas, dustCount, + [&](PHandle p) { - p.org()[j] = org[j] + ((rand() & 7) - 4); - p.vel()[j] = rnd(-24, 24); - } + p.atlasIdx() = aiCircle; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(255); + p.die() = cl.time + 0.75 * (rand() % 5); + p.setColor((color & ~7) + (rand() & 7)); + p.scale() = rnd(0.05f, 0.3f); + p.type() = pt_static; + setAccGrav(p, 0.08f); - p.vel()[2] += rnd(10, 40); - }); - - makeNParticles(ptxAtlas, sparkCount, [&](PHandle p) { - p.atlasIdx() = aiSpark; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(255); - p.die() = cl.time + 1.25 * (rand() % 5); - p.setColor(ramp3[0] + (rand() & 7)); - p.scale() = rnd(1.95f, 2.87f) * 0.35f; - p.type() = pt_rock; - p.param0() = rndi(0, 2); // rotation direction - setAccGrav(p, 1.f); - - for(int j = 0; j < 3; j++) + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + ((rand() & 7) - 4); + p.vel()[j] = rnd(-24, 24); + } + + p.vel()[2] += rnd(10, 40); + }); + + makeNParticles(ptxAtlas, sparkCount, + [&](PHandle p) { - p.org()[j] = org[j] + ((rand() & 7) - 4); - p.vel()[j] = rnd(-48, 48); - } + p.atlasIdx() = aiSpark; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(255); + p.die() = cl.time + 1.25 * (rand() % 5); + p.setColor(ramp3[0] + (rand() & 7)); + p.scale() = rnd(1.95f, 2.87f) * 0.35f; + p.type() = pt_rock; + p.param0() = rndi(0, 2); // rotation direction + setAccGrav(p, 1.f); + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + ((rand() & 7) - 4); + p.vel()[j] = rnd(-48, 48); + } - p.vel()[2] = rnd(60, 360); - }); + p.vel()[2] = rnd(60, 360); + }); } void R_RunParticleEffect_Blood(const qvec3& org, const qvec3& dir, int count) @@ -1229,62 +1270,68 @@ void R_RunParticleEffect_Blood(const qvec3& org, const qvec3& dir, int count) constexpr int bloodColors[]{247, 248, 249, 250, 251}; const auto pickBloodColor = [&] { return bloodColors[rndi(0, 5)]; }; - makeNParticles(ptxAtlas, count * 2, [&](PHandle p) { - p.atlasIdx() = aiBlood; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(100); - p.die() = cl.time + 0.7 * (rand() % 3); - p.setColor(pickBloodColor()); - p.scale() = rnd(0.35f, 0.6f) * 6.5f; - p.type() = pt_static; - setAccGrav(p, 0.29f); - - for(int j = 0; j < 3; j++) + makeNParticles(ptxAtlas, count * 2, + [&](PHandle p) { - p.org()[j] = org[j] + rnd(-2, 2); - p.vel()[j] = (dir[j] + 0.3f) * rnd(-10, 10); - } + p.atlasIdx() = aiBlood; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(100); + p.die() = cl.time + 0.7 * (rand() % 3); + p.setColor(pickBloodColor()); + p.scale() = rnd(0.35f, 0.6f) * 6.5f; + p.type() = pt_static; + setAccGrav(p, 0.29f); - p.vel()[2] += rnd(0, 40); - }); + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + rnd(-2, 2); + p.vel()[j] = (dir[j] + 0.3f) * rnd(-10, 10); + } - makeNParticles(ptxAtlas, count * 24, [&](PHandle p) { - p.atlasIdx() = aiCircle; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(175); - p.die() = cl.time + 0.4 * (rand() % 3); - p.setColor(pickBloodColor()); - p.scale() = rnd(0.12f, 0.2f); - p.type() = pt_static; - setAccGrav(p, 0.45f); + p.vel()[2] += rnd(0, 40); + }); - for(int j = 0; j < 3; j++) + makeNParticles(ptxAtlas, count * 24, + [&](PHandle p) { - p.org()[j] = org[j] + rnd(-2, 2); - p.vel()[j] = (dir[j] + 0.3f) * rnd(-3, 3); - p.vel()[j] *= 13.f; - } + p.atlasIdx() = aiCircle; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(175); + p.die() = cl.time + 0.4 * (rand() % 3); + p.setColor(pickBloodColor()); + p.scale() = rnd(0.12f, 0.2f); + p.type() = pt_static; + setAccGrav(p, 0.45f); + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + rnd(-2, 2); + p.vel()[j] = (dir[j] + 0.3f) * rnd(-3, 3); + p.vel()[j] *= 13.f; + } - p.vel()[2] += rnd(20, 60); - }); - - makeNParticles(ptxAtlas, 1, [&](PHandle p) { - p.atlasIdx() = aiBloodMist; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(38); - p.die() = cl.time + 2.0; - p.setColor(225); - p.ramp() = rand() & 3; - p.scale() = rnd(1.1f, 2.4f) * 15.f; - setAccGrav(p, -0.03f); - p.type() = pt_txsmoke; - - for(int j = 0; j < 3; j++) + p.vel()[2] += rnd(20, 60); + }); + + makeNParticles(ptxAtlas, 1, + [&](PHandle p) { - p.org()[j] = org[j] + rnd(-8, 8); - p.vel()[j] = rnd(-4, -4); - } - }); + p.atlasIdx() = aiBloodMist; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(38); + p.die() = cl.time + 2.0; + p.setColor(225); + p.ramp() = rand() & 3; + p.scale() = rnd(1.1f, 2.4f) * 15.f; + setAccGrav(p, -0.03f); + p.type() = pt_txsmoke; + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + rnd(-8, 8); + p.vel()[j] = rnd(-4, -4); + } + }); } void R_RunParticleEffect_Lightning( @@ -1292,140 +1339,152 @@ void R_RunParticleEffect_Lightning( { (void)dir; - makeNParticles(ptxAtlas, count, [&](PHandle p) { - p.atlasIdx() = aiLightning; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(rnd(180, 220)); - p.die() = cl.time + 1.2 * (rand() % 3); - p.setColor(254); - p.scale() = rnd(0.35f, 0.6f) * 6.2f; - p.type() = pt_lightning; - setAccGrav(p, 0.f); - - for(int j = 0; j < 3; j++) + makeNParticles(ptxAtlas, count, + [&](PHandle p) { - p.org()[j] = org[j] + rnd(-3, 3); - p.vel()[j] = rnd(-185, 185); - } - }); + p.atlasIdx() = aiLightning; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(rnd(180, 220)); + p.die() = cl.time + 1.2 * (rand() % 3); + p.setColor(254); + p.scale() = rnd(0.35f, 0.6f) * 6.2f; + p.type() = pt_lightning; + setAccGrav(p, 0.f); + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + rnd(-3, 3); + p.vel()[j] = rnd(-185, 185); + } + }); } void R_RunParticleEffect_Smoke(const qvec3& org, const qvec3& dir, int count) { (void)dir; - makeNParticles(ptxAtlas, count, [&](PHandle p) { - p.atlasIdx() = aiSmoke; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(125); - p.die() = cl.time + 2.5 * (rand() % 5); - p.setColor(rand() & 7); - p.scale() = rnd(1.2f, 1.5f) * 0.8f; - p.type() = pt_txsmoke; - setAccGrav(p, -0.09f); - - for(int j = 0; j < 3; j++) + makeNParticles(ptxAtlas, count, + [&](PHandle p) { - p.org()[j] = org[j] + ((rand() & 7) - 4); - p.vel()[j] = rnd(-24, 24); - } - }); + p.atlasIdx() = aiSmoke; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(125); + p.die() = cl.time + 2.5 * (rand() % 5); + p.setColor(rand() & 7); + p.scale() = rnd(1.2f, 1.5f) * 0.8f; + p.type() = pt_txsmoke; + setAccGrav(p, -0.09f); + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + ((rand() & 7) - 4); + p.vel()[j] = rnd(-24, 24); + } + }); } void R_RunParticleEffect_BigSmoke(const qvec3& org, const qvec3& dir, int count) { (void)dir; - makeNParticles(ptxAtlas, count, [&](PHandle p) { - p.atlasIdx() = aiSmoke; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(255); - p.die() = cl.time + 2.5 * (rand() % 5); - p.setColor(rand() & 7); - p.scale() = rnd(1.2f, 1.7f) * 2.8f; - p.type() = pt_txbigsmoke; - setAccGrav(p, -0.09f); - - for(int j = 0; j < 3; j++) + makeNParticles(ptxAtlas, count, + [&](PHandle p) { - p.org()[j] = org[j] + ((rand() & 9) - 4); - p.vel()[j] = rnd(-24, 24); - } - }); + p.atlasIdx() = aiSmoke; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(255); + p.die() = cl.time + 2.5 * (rand() % 5); + p.setColor(rand() & 7); + p.scale() = rnd(1.2f, 1.7f) * 2.8f; + p.type() = pt_txbigsmoke; + setAccGrav(p, -0.09f); + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + ((rand() & 9) - 4); + p.vel()[j] = rnd(-24, 24); + } + }); } void R_RunParticleEffect_Sparks(const qvec3& org, const qvec3& dir, int count) { (void)dir; - makeNParticles(ptxAtlas, count, [&](PHandle p) { - p.atlasIdx() = aiSpark; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(255); - p.die() = cl.time + 2.0 * (rand() % 5); - p.setColor(rndi(102, 112)); - p.scale() = rnd(1.55f, 2.87f) * 0.45f; - p.type() = pt_rock; - p.param0() = rndi(0, 2); // rotation direction - setAccGrav(p, 1.f); - - for(int j = 0; j < 3; j++) + makeNParticles(ptxAtlas, count, + [&](PHandle p) { - p.org()[j] = org[j] + ((rand() & 7) - 4); - p.vel()[j] = rnd(-48, 48); - } + p.atlasIdx() = aiSpark; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(255); + p.die() = cl.time + 2.0 * (rand() % 5); + p.setColor(rndi(102, 112)); + p.scale() = rnd(1.55f, 2.87f) * 0.45f; + p.type() = pt_rock; + p.param0() = rndi(0, 2); // rotation direction + setAccGrav(p, 1.f); + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + ((rand() & 7) - 4); + p.vel()[j] = rnd(-48, 48); + } - p.vel()[2] = rnd(60, 360); - }); + p.vel()[2] = rnd(60, 360); + }); } void R_RunParticleEffect_GunSmoke(const qvec3& org, const qvec3& dir, int count) { (void)dir; - makeNParticles(ptxAtlas, count, [&](PHandle p) { - p.atlasIdx() = aiGunSmoke; - p.angle() = rndToRad(-10.f, 10.f) + (90 * M_PI_DIV_180); - p.setAlpha(rnd(85, 125)); - p.die() = cl.time + 3.5; - p.setColor(rndi(10, 16)); - p.scale() = rnd(0.9f, 1.5f) * 0.1f; - p.type() = pt_gunsmoke; - setAccGrav(p, -0.09f); - - for(int j = 0; j < 3; j++) + makeNParticles(ptxAtlas, count, + [&](PHandle p) { - p.org()[j] = org[j]; - p.vel()[j] = rnd(-3, 3); - } + p.atlasIdx() = aiGunSmoke; + p.angle() = rndToRad(-10.f, 10.f) + (90 * M_PI_DIV_180); + p.setAlpha(rnd(85, 125)); + p.die() = cl.time + 3.5; + p.setColor(rndi(10, 16)); + p.scale() = rnd(0.9f, 1.5f) * 0.1f; + p.type() = pt_gunsmoke; + setAccGrav(p, -0.09f); + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j]; + p.vel()[j] = rnd(-3, 3); + } - p.org()[2] += 3.f; - }); + p.org()[2] += 3.f; + }); } void R_RunParticleEffect_Teleport(const qvec3& org, const qvec3& dir, int count) { (void)dir; - makeNParticles(ptxAtlas, count, [&](PHandle p) { - p.atlasIdx() = aiSpark; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(255); - p.die() = cl.time + 0.6; - p.setColor(rndi(208, 220)); - p.scale() = rnd(1.55f, 2.87f) * 0.65f; - p.type() = pt_rock; - p.param0() = rndi(0, 2); // rotation direction - setAccGrav(p, 1.f); - - for(int j = 0; j < 3; j++) + makeNParticles(ptxAtlas, count, + [&](PHandle p) { - p.org()[j] = org[j] + ((rand() & 7) - 4); - p.vel()[j] = rnd(-48, 48); - } + p.atlasIdx() = aiSpark; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(255); + p.die() = cl.time + 0.6; + p.setColor(rndi(208, 220)); + p.scale() = rnd(1.55f, 2.87f) * 0.65f; + p.type() = pt_rock; + p.param0() = rndi(0, 2); // rotation direction + setAccGrav(p, 1.f); + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + ((rand() & 7) - 4); + p.vel()[j] = rnd(-48, 48); + } - p.vel()[2] = rnd(60, 360); - }); + p.vel()[2] = rnd(60, 360); + }); } void R_RunParticleEffect_GunPickup( @@ -1433,24 +1492,26 @@ void R_RunParticleEffect_GunPickup( { (void)dir; - makeNParticles(ptxAtlas, count, [&](PHandle p) { - p.atlasIdx() = aiSpark; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(rnd(150, 200)); - p.die() = cl.time + 0.5; - p.setColor(rndi(12, 16)); - p.scale() = rnd(1.55f, 2.87f) * 0.35f; - p.type() = pt_gunpickup; - setAccGrav(p, -0.2f); - - for(int j = 0; j < 3; j++) + makeNParticles(ptxAtlas, count, + [&](PHandle p) { - p.org()[j] = org[j] + ((rand() & 3) - 2); - p.vel()[j] = rnd(-16, 16); - } + p.atlasIdx() = aiSpark; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(rnd(150, 200)); + p.die() = cl.time + 0.5; + p.setColor(rndi(12, 16)); + p.scale() = rnd(1.55f, 2.87f) * 0.35f; + p.type() = pt_gunpickup; + setAccGrav(p, -0.2f); + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + ((rand() & 3) - 2); + p.vel()[j] = rnd(-16, 16); + } - p.vel()[2] = rnd(-10, 30); - }); + p.vel()[2] = rnd(-10, 30); + }); } void R_RunParticleEffect_GunForceGrab( @@ -1458,24 +1519,26 @@ void R_RunParticleEffect_GunForceGrab( { (void)dir; - makeNParticles(ptxAtlas, count, [&](PHandle p) { - p.atlasIdx() = aiSpark; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(rnd(180, 225)); - p.die() = cl.time + 0.6; - p.setColor(rndi(106, 111)); - p.scale() = rnd(1.55f, 2.87f) * 0.35f; - p.type() = pt_gunpickup; - setAccGrav(p, -0.3f); - - for(int j = 0; j < 3; j++) + makeNParticles(ptxAtlas, count, + [&](PHandle p) { - p.org()[j] = org[j] + ((rand() & 4) - 2); - p.vel()[j] = rnd(-24, 24); - } + p.atlasIdx() = aiSpark; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(rnd(180, 225)); + p.die() = cl.time + 0.6; + p.setColor(rndi(106, 111)); + p.scale() = rnd(1.55f, 2.87f) * 0.35f; + p.type() = pt_gunpickup; + setAccGrav(p, -0.3f); + + for(int j = 0; j < 3; j++) + { + p.org()[j] = org[j] + ((rand() & 4) - 2); + p.vel()[j] = rnd(-24, 24); + } - p.vel()[2] = rnd(0, 40); - }); + p.vel()[2] = rnd(0, 40); + }); } void R_RunParticleEffect_LavaSpike( @@ -1483,22 +1546,25 @@ void R_RunParticleEffect_LavaSpike( { (void)dir; - makeNParticles(ptxAtlas, count, [&](PHandle p) { - p.atlasIdx() = aiSpark; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(rnd(180, 225)); - p.die() = cl.time + 0.5; - p.setColor(rndi(247, 254)); - p.scale() = rnd(1.55f, 2.87f) * 0.17f; - p.type() = pt_gunpickup; - setAccGrav(p, 0.17f); - - for(int j = 0; j < 3; j++) + makeNParticles(ptxAtlas, count, + [&](PHandle p) { - p.org()[j] = org[j] + static_cast(((rand() & 2) - 1)) * 0.3f; - p.vel()[j] = rnd(-2, 2); - } - }); + p.atlasIdx() = aiSpark; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(rnd(180, 225)); + p.die() = cl.time + 0.5; + p.setColor(rndi(247, 254)); + p.scale() = rnd(1.55f, 2.87f) * 0.17f; + p.type() = pt_gunpickup; + setAccGrav(p, 0.17f); + + for(int j = 0; j < 3; j++) + { + p.org()[j] = + org[j] + static_cast(((rand() & 2) - 1)) * 0.3f; + p.vel()[j] = rnd(-2, 2); + } + }); } /* @@ -1606,28 +1672,30 @@ void R_LavaSplash(const qvec3& org) { for(int j = -16; j < 16; j++) { - makeNParticles(ptxAtlas, 1, [&](PHandle p) { - p.atlasIdx() = aiCircle; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(255); - p.scale() = 1.f; - p.die() = cl.time + 2 + (rand() & 31) * 0.02; - p.setColor(224 + (rand() & 7)); - p.type() = pt_static; - setAccGrav(p); - - const qvec3 dir{ // - j * 8 + (rand() & 7), // - i * 8 + (rand() & 7), // - 256}; - - p.org()[0] = org[0] + dir[0]; - p.org()[1] = org[1] + dir[1]; - p.org()[2] = org[2] + (rand() & 63); + makeNParticles(ptxAtlas, 1, + [&](PHandle p) + { + p.atlasIdx() = aiCircle; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(255); + p.scale() = 1.f; + p.die() = cl.time + 2 + (rand() & 31) * 0.02; + p.setColor(224 + (rand() & 7)); + p.type() = pt_static; + setAccGrav(p); + + const qvec3 dir{ // + j * 8 + (rand() & 7), // + i * 8 + (rand() & 7), // + 256}; + + p.org()[0] = org[0] + dir[0]; + p.org()[1] = org[1] + dir[1]; + p.org()[2] = org[2] + (rand() & 63); - const qfloat vel = 50 + (rand() & 63); - p.vel() = safeNormalize(dir) * vel; - }); + const qfloat vel = 50 + (rand() & 63); + p.vel() = safeNormalize(dir) * vel; + }); } } } @@ -1645,29 +1713,31 @@ void R_TeleportSplash(const qvec3& org) { for(int k = -24; k < 32; k += 4) { - makeNParticles(ptxAtlas, 1, [&](PHandle p) { - p.atlasIdx() = aiCircle; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(rnd(150, 255)); - p.scale() = rnd(0.6f, 1.f); - p.die() = cl.time + 1.2 + (rand() & 7) * 0.2; - p.setColor(7 + (rand() & 7)); - p.type() = pt_teleport; - setAccGrav(p, 0.2f); - - const qvec3 dir{ - j * 8, // - i * 8, // - k * 8 // - }; - - p.org()[0] = org[0] + i + (rand() & 3); - p.org()[1] = org[1] + j + (rand() & 3); - p.org()[2] = org[2] + k + (rand() & 3); - - const qfloat vel = 50 + (rand() & 63); - p.vel() = safeNormalize(dir) * vel; - }); + makeNParticles(ptxAtlas, 1, + [&](PHandle p) + { + p.atlasIdx() = aiCircle; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(rnd(150, 255)); + p.scale() = rnd(0.6f, 1.f); + p.die() = cl.time + 1.2 + (rand() & 7) * 0.2; + p.setColor(7 + (rand() & 7)); + p.type() = pt_teleport; + setAccGrav(p, 0.2f); + + const qvec3 dir{ + j * 8, // + i * 8, // + k * 8 // + }; + + p.org()[0] = org[0] + i + (rand() & 3); + p.org()[1] = org[1] + j + (rand() & 3); + p.org()[2] = org[2] + k + (rand() & 3); + + const qfloat vel = 50 + (rand() & 63); + p.vel() = safeNormalize(dir) * vel; + }); } } } @@ -1804,78 +1874,88 @@ void R_RocketTrail(qvec3 start, const qvec3& end, int type) { case 0: // rocket trail { - makeNParticles(ptxAtlas, 6, [&](PHandle p) { - p.atlasIdx() = aiCircle; - R_SetRTCommon(p); - R_SetRTRocketTrail(start, p); - }); - - makeNParticles(ptxAtlas, 1, [&](PHandle p) { - p.atlasIdx() = aiSmoke; - p.setAlpha(65); - p.die() = cl.time + 1.5 * (rand() % 5); - p.setColor(rand() & 7); - p.scale() = rnd(0.3f, 0.5f); - p.type() = pt_txsmoke; - setAccGrav(p, -0.09f); + makeNParticles(ptxAtlas, 6, + [&](PHandle p) + { + p.atlasIdx() = aiCircle; + R_SetRTCommon(p); + R_SetRTRocketTrail(start, p); + }); - for(int j = 0; j < 3; j++) + makeNParticles(ptxAtlas, 1, + [&](PHandle p) { - p.org()[j] = start[j] + ((rand() & 6) - 3); - p.vel()[j] = rnd(-18, 18); - } - }); + p.atlasIdx() = aiSmoke; + p.setAlpha(65); + p.die() = cl.time + 1.5 * (rand() % 5); + p.setColor(rand() & 7); + p.scale() = rnd(0.3f, 0.5f); + p.type() = pt_txsmoke; + setAccGrav(p, -0.09f); + + for(int j = 0; j < 3; j++) + { + p.org()[j] = start[j] + ((rand() & 6) - 3); + p.vel()[j] = rnd(-18, 18); + } + }); break; } case 1: // smoke smoke { - makeNParticles(ptxAtlas, 1, [&](PHandle p) { - p.atlasIdx() = aiSmoke; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(65); - p.die() = cl.time + 1.5 * (rand() % 5); - p.setColor(rand() & 7); - p.scale() = rnd(0.3f, 0.5f); - p.type() = pt_txsmoke; - setAccGrav(p, -0.09f); - - for(int j = 0; j < 3; j++) + makeNParticles(ptxAtlas, 1, + [&](PHandle p) { - p.org()[j] = start[j] + ((rand() & 6) - 3); - p.vel()[j] = rnd(-18, 18); - } - }); + p.atlasIdx() = aiSmoke; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(65); + p.die() = cl.time + 1.5 * (rand() % 5); + p.setColor(rand() & 7); + p.scale() = rnd(0.3f, 0.5f); + p.type() = pt_txsmoke; + setAccGrav(p, -0.09f); + + for(int j = 0; j < 3; j++) + { + p.org()[j] = start[j] + ((rand() & 6) - 3); + p.vel()[j] = rnd(-18, 18); + } + }); break; } case 2: // blood { - makeNParticles(ptxAtlas, 6, [&](PHandle p) { - p.atlasIdx() = aiCircle; - R_SetRTCommon(p); - R_SetRTBlood(start, p); - }); + makeNParticles(ptxAtlas, 6, + [&](PHandle p) + { + p.atlasIdx() = aiCircle; + R_SetRTCommon(p); + R_SetRTBlood(start, p); + }); - makeNParticles(ptxAtlas, 1, [&](PHandle p) { - p.atlasIdx() = aiBloodMist; - p.angle() = rndToRad(0.f, 360.f); - p.setAlpha(32); - p.die() = cl.time + 3.2; - p.setColor(225); - p.ramp() = rand() & 3; - p.scale() = rnd(1.1f, 2.4f) * 15.f; - setAccGrav(p, -0.03f); - p.type() = pt_txsmoke; - - for(int j = 0; j < 3; j++) + makeNParticles(ptxAtlas, 1, + [&](PHandle p) { - p.org()[j] = start[j] + rnd(-8, 8); - p.vel()[j] = rnd(-4, -4); - } - }); + p.atlasIdx() = aiBloodMist; + p.angle() = rndToRad(0.f, 360.f); + p.setAlpha(32); + p.die() = cl.time + 3.2; + p.setColor(225); + p.ramp() = rand() & 3; + p.scale() = rnd(1.1f, 2.4f) * 15.f; + setAccGrav(p, -0.03f); + p.type() = pt_txsmoke; + + for(int j = 0; j < 3; j++) + { + p.org()[j] = start[j] + rnd(-8, 8); + p.vel()[j] = rnd(-4, -4); + } + }); break; } @@ -1883,61 +1963,71 @@ void R_RocketTrail(qvec3 start, const qvec3& end, int type) case 3: [[fallthrough]]; case 5: // tracer { - makeNParticles(ptxAtlas, 6, [&](PHandle p) { - p.atlasIdx() = aiCircle; - R_SetRTCommon(p); - R_SetRTTracer(start, end, p, type); - }); + makeNParticles(ptxAtlas, 6, + [&](PHandle p) + { + p.atlasIdx() = aiCircle; + R_SetRTCommon(p); + R_SetRTTracer(start, end, p, type); + }); break; } case 4: // slight blood { - makeNParticles(ptxAtlas, 6, [&](PHandle p) { - p.atlasIdx() = aiCircle; - R_SetRTCommon(p); - R_SetRTSlightBlood(start, p); - len -= 3; - }); + makeNParticles(ptxAtlas, 6, + [&](PHandle p) + { + p.atlasIdx() = aiCircle; + R_SetRTCommon(p); + R_SetRTSlightBlood(start, p); + len -= 3; + }); break; } case 6: // voor trail { - makeNParticles(ptxAtlas, 6, [&](PHandle p) { - p.atlasIdx() = aiCircle; - R_SetRTCommon(p); - R_SetRTVoorTrail(start, p); - }); + makeNParticles(ptxAtlas, 6, + [&](PHandle p) + { + p.atlasIdx() = aiCircle; + R_SetRTCommon(p); + R_SetRTVoorTrail(start, p); + }); break; } case 7: // mini rocket trail { - makeNParticles(ptxAtlas, 2, [&](PHandle p) { - p.atlasIdx() = aiCircle; - R_SetRTCommon(p); - R_SetRTRocketTrail(start, p); - }); - - makeNParticles(ptxAtlas, 1, [&](PHandle p) { - p.atlasIdx() = aiSmoke; - p.setAlpha(55); - p.die() = cl.time + 1.2 * (rand() % 5); - p.setColor(rand() & 7); - p.scale() = rnd(0.05f, 0.23f); - p.type() = pt_txsmoke; - setAccGrav(p, -0.09f); + makeNParticles(ptxAtlas, 2, + [&](PHandle p) + { + p.atlasIdx() = aiCircle; + R_SetRTCommon(p); + R_SetRTRocketTrail(start, p); + }); - for(int j = 0; j < 3; j++) + makeNParticles(ptxAtlas, 1, + [&](PHandle p) { - p.org()[j] = start[j] + ((rand() & 4) - 2); - p.vel()[j] = rnd(-18, 18); - } - }); + p.atlasIdx() = aiSmoke; + p.setAlpha(55); + p.die() = cl.time + 1.2 * (rand() % 5); + p.setColor(rand() & 7); + p.scale() = rnd(0.05f, 0.23f); + p.type() = pt_txsmoke; + setAccGrav(p, -0.09f); + + for(int j = 0; j < 3; j++) + { + p.org()[j] = start[j] + ((rand() & 4) - 2); + p.vel()[j] = rnd(-18, 18); + } + }); break; } @@ -1969,170 +2059,176 @@ void CL_RunParticles() pMgr.cleanup(); - pMgr.forBuffers([&](gltexture_t*, const ImageData&, PBuffer& pBuffer) { - ParticleSOA& soa = pBuffer.soa(); - const auto pCount = pBuffer.aliveCount(); - - for(std::size_t i = 0; i < pCount; ++i) + pMgr.forBuffers( + [&](gltexture_t*, const ImageData&, PBuffer& pBuffer) { - soa._vels[i] += soa._accs[i] * frametime; - soa._orgs[i] += soa._vels[i] * frametime; - } - }); + ParticleSOA& soa = pBuffer.soa(); + const auto pCount = pBuffer.aliveCount(); - forActiveParticles([&](PHandle p) { - switch(p.type()) - { - case pt_static: + for(std::size_t i = 0; i < pCount; ++i) { - break; + soa._vels[i] += soa._accs[i] * frametime; + soa._orgs[i] += soa._vels[i] * frametime; } + }); - case pt_fire: + forActiveParticles( + [&](PHandle p) + { + switch(p.type()) { - p.ramp() += time1; - if(p.ramp() >= 6) - { - p.die() = -1; - } - else + case pt_static: { - p.setColor(ramp3[(int)p.ramp()]); + break; } - break; - } - - case pt_explode: - { - p.ramp() += time2; - - if(p.ramp() >= 8) + case pt_fire: { - p.die() = -1; - } - else - { - p.setColor(ramp1[(int)p.ramp()]); + p.ramp() += time1; + if(p.ramp() >= 6) + { + p.die() = -1; + } + else + { + p.setColor(ramp3[(int)p.ramp()]); + } + + break; } - for(int i = 0; i < 3; i++) + case pt_explode: { - p.vel()[i] += p.vel()[i] * dvel; - } + p.ramp() += time2; - break; - } + if(p.ramp() >= 8) + { + p.die() = -1; + } + else + { + p.setColor(ramp1[(int)p.ramp()]); + } - case pt_explode2: - { - p.ramp() += time3; + for(int i = 0; i < 3; i++) + { + p.vel()[i] += p.vel()[i] * dvel; + } - if(p.ramp() >= 8) - { - p.die() = -1; - } - else - { - p.setColor(ramp2[(int)p.ramp()]); + break; } - for(int i = 0; i < 3; i++) + case pt_explode2: { - p.vel()[i] -= p.vel()[i] * frametime; - } + p.ramp() += time3; - break; - } + if(p.ramp() >= 8) + { + p.die() = -1; + } + else + { + p.setColor(ramp2[(int)p.ramp()]); + } - case pt_blob: - { - p.vel() += p.vel() * dvel; + for(int i = 0; i < 3; i++) + { + p.vel()[i] -= p.vel()[i] * frametime; + } - break; - } + break; + } - case pt_blob2: - { - for(int i = 0; i < 2; i++) + case pt_blob: { - p.vel()[i] -= p.vel()[i] * dvel; + p.vel() += p.vel() * dvel; + + break; } - break; - } + case pt_blob2: + { + for(int i = 0; i < 2; i++) + { + p.vel()[i] -= p.vel()[i] * dvel; + } - case pt_txexplode: - { - p.addAlpha(-345.f, frametime); - p.scale() += 135.f * frametime; - p.angle() += 0.75f * frametime * (p.param0() == 0 ? 1.f : -1.f); + break; + } - break; - } + case pt_txexplode: + { + p.addAlpha(-345.f, frametime); + p.scale() += 135.f * frametime; + p.angle() += + 0.75f * frametime * (p.param0() == 0 ? 1.f : -1.f); - case pt_txsmoke: - { - p.addAlpha(-70.f, frametime); - p.scale() += 47.f * frametime; + break; + } - break; - } + case pt_txsmoke: + { + p.addAlpha(-70.f, frametime); + p.scale() += 47.f * frametime; - case pt_txbigsmoke: - { - p.addAlpha(-35.f, frametime); - p.scale() += 37.f * frametime; + break; + } - break; - } + case pt_txbigsmoke: + { + p.addAlpha(-35.f, frametime); + p.scale() += 37.f * frametime; - case pt_lightning: - { - p.addAlpha(-84.f, frametime); - p.scale() -= 32.f * frametime; + break; + } - break; - } + case pt_lightning: + { + p.addAlpha(-84.f, frametime); + p.scale() -= 32.f * frametime; - case pt_teleport: - { - p.addAlpha(-85.f, frametime); - p.scale() -= 0.1f * frametime; + break; + } - break; - } + case pt_teleport: + { + p.addAlpha(-85.f, frametime); + p.scale() -= 0.1f * frametime; - case pt_rock: - { - p.angle() += 25.f * frametime * (p.param0() == 0 ? 1.f : -1.f); + break; + } - break; - } + case pt_rock: + { + p.angle() += + 25.f * frametime * (p.param0() == 0 ? 1.f : -1.f); - case pt_gunsmoke: - { - p.addAlpha(-110.f, frametime); - p.scale() += 69.f * frametime; - p.org()[2] += 18.f * frametime; + break; + } - break; - } + case pt_gunsmoke: + { + p.addAlpha(-110.f, frametime); + p.scale() += 69.f * frametime; + p.org()[2] += 18.f * frametime; - case pt_gunpickup: - { - p.addAlpha(-120.f, frametime); - p.scale() -= 0.2f * frametime; + break; + } - break; - } + case pt_gunpickup: + { + p.addAlpha(-120.f, frametime); + p.scale() -= 0.2f * frametime; - default: - { - break; + break; + } + + default: + { + break; + } } - } - }); + }); } static GLuint makeParticleShaders() @@ -2396,84 +2492,85 @@ void R_DrawParticles() glBindVertexArray(vaoId); - pMgr.forBuffers([&](gltexture_t* texture, const ImageData& imageData, - PBuffer& pBuffer) { - (void)texture; - (void)imageData; - - const auto pCount = pBuffer.aliveCount(); - ParticleSOA& soa = pBuffer.soa(); - - GL_Bind(texture); - - // - // - // Setup - - glBindBuffer(GL_ARRAY_BUFFER, pOrgVboId); - glBufferData( - GL_ARRAY_BUFFER, sizeof(qvec3) * pCount, soa._orgs, GL_STATIC_DRAW); - glVertexAttribPointer( // - pOrgLocation, // location - 3, // number of components (vec3 = 3) - GL_FLOAT, // type of each component - GL_FALSE, // normalized - 0, // stride - (void*)0 // array buffer offset - ); - - glBindBuffer(GL_ARRAY_BUFFER, pAngleVboId); - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * pCount, soa._angles, - GL_STATIC_DRAW); - glVertexAttribPointer( // - pAngleLocation, // location - 1, // number of components - GL_FLOAT, // type of each component - GL_FALSE, // normalized - 0, // stride - (void*)0 // array buffer offset - ); - - glBindBuffer(GL_ARRAY_BUFFER, pScaleVboId); - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * pCount, soa._scales, - GL_STATIC_DRAW); - glVertexAttribPointer( // - pScaleLocation, // location - 1, // number of components - GL_FLOAT, // type of each component - GL_FALSE, // normalized - 0, // stride - (void*)0 // array buffer offset - ); - - glBindBuffer(GL_ARRAY_BUFFER, pColorVboId); - glBufferData(GL_ARRAY_BUFFER, sizeof(qvec4) * pCount, soa._colors, - GL_STATIC_DRAW); - glVertexAttribPointer( // - pColorLocation, // location - 4, // number of components - GL_FLOAT, // type of each component - GL_FALSE, // normalized - 0, // stride - (void*)0 // array buffer offset - ); - - glBindBuffer(GL_ARRAY_BUFFER, pAtlasIdxVboId); - glBufferData(GL_ARRAY_BUFFER, sizeof(int) * pCount, soa._atlasIdxs, - GL_STATIC_DRAW); - glVertexAttribIPointer( // - pAtlasIdxLocation, // location - 1, // number of components - GL_INT, // type of each component - 0, // stride - (void*)0 // array buffer offset - ); - - // - // - // Draw - glDrawArrays(GL_POINTS, 0, pBuffer.aliveCount()); - }); + pMgr.forBuffers( + [&](gltexture_t* texture, const ImageData& imageData, PBuffer& pBuffer) + { + (void)texture; + (void)imageData; + + const auto pCount = pBuffer.aliveCount(); + ParticleSOA& soa = pBuffer.soa(); + + GL_Bind(texture); + + // + // + // Setup + + glBindBuffer(GL_ARRAY_BUFFER, pOrgVboId); + glBufferData(GL_ARRAY_BUFFER, sizeof(qvec3) * pCount, soa._orgs, + GL_STATIC_DRAW); + glVertexAttribPointer( // + pOrgLocation, // location + 3, // number of components (vec3 = 3) + GL_FLOAT, // type of each component + GL_FALSE, // normalized + 0, // stride + (void*)0 // array buffer offset + ); + + glBindBuffer(GL_ARRAY_BUFFER, pAngleVboId); + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * pCount, soa._angles, + GL_STATIC_DRAW); + glVertexAttribPointer( // + pAngleLocation, // location + 1, // number of components + GL_FLOAT, // type of each component + GL_FALSE, // normalized + 0, // stride + (void*)0 // array buffer offset + ); + + glBindBuffer(GL_ARRAY_BUFFER, pScaleVboId); + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * pCount, soa._scales, + GL_STATIC_DRAW); + glVertexAttribPointer( // + pScaleLocation, // location + 1, // number of components + GL_FLOAT, // type of each component + GL_FALSE, // normalized + 0, // stride + (void*)0 // array buffer offset + ); + + glBindBuffer(GL_ARRAY_BUFFER, pColorVboId); + glBufferData(GL_ARRAY_BUFFER, sizeof(qvec4) * pCount, soa._colors, + GL_STATIC_DRAW); + glVertexAttribPointer( // + pColorLocation, // location + 4, // number of components + GL_FLOAT, // type of each component + GL_FALSE, // normalized + 0, // stride + (void*)0 // array buffer offset + ); + + glBindBuffer(GL_ARRAY_BUFFER, pAtlasIdxVboId); + glBufferData(GL_ARRAY_BUFFER, sizeof(int) * pCount, soa._atlasIdxs, + GL_STATIC_DRAW); + glVertexAttribIPointer( // + pAtlasIdxLocation, // location + 1, // number of components + GL_INT, // type of each component + 0, // stride + (void*)0 // array buffer offset + ); + + // + // + // Draw + glDrawArrays(GL_POINTS, 0, pBuffer.aliveCount()); + }); glDepthMask(GL_TRUE); glDisable(GL_BLEND); @@ -2510,23 +2607,25 @@ void R_DrawParticles_ShowTris() // const auto right = vright * 1.5f; glBegin(GL_TRIANGLES); - forActiveParticles([&](PHandle p) { - (void)p; + forActiveParticles( + [&](PHandle p) + { + (void)p; - // TODO VR: (P2) rewrite - /* - const float scale = p.scale; + // TODO VR: (P2) rewrite + /* + const float scale = p.scale; - glVertex3fv(toGlVec(p.org)); + glVertex3fv(toGlVec(p.org)); - qvec3 p_up; - VectorMA(p.org, scale, up, p_up); - glVertex3fv(toGlVec(p_up)); + qvec3 p_up; + VectorMA(p.org, scale, up, p_up); + glVertex3fv(toGlVec(p_up)); - qvec3 p_right; - VectorMA(p.org, scale, right, p_right); - glVertex3fv(toGlVec(p_right)); - */ - }); + qvec3 p_right; + VectorMA(p.org, scale, right, p_right); + glVertex3fv(toGlVec(p_right)); + */ + }); glEnd(); } diff --git a/Quake/saveutil.cpp b/Quake/saveutil.cpp index dc515740..1047b6e2 100644 --- a/Quake/saveutil.cpp +++ b/Quake/saveutil.cpp @@ -9,6 +9,8 @@ #include #include +#include +#include namespace quake::saveutil { @@ -17,7 +19,7 @@ namespace quake::saveutil static char data[MAX_SAVEGAMES][SAVEGAME_COMMENT_LENGTH + 1]{}; return data; } -// namespace quake::saveutil + [[nodiscard]] auto& autosaveFilenames() noexcept { static char data[MAX_AUTOSAVES][SAVEGAME_COMMENT_LENGTH + 1]{}; @@ -89,8 +91,8 @@ void scanSaves() { const auto doScan = [&](auto& filenamesArray, auto& loadableArray, const int max, const char* naming, - const char* unusedSlot, - std::time_t* timestampArray) { + const char* unusedSlot, std::time_t* timestampArray) + { for(int i = 0; i < max; i++) { strcpy(filenamesArray[i], unusedSlot); @@ -115,7 +117,14 @@ void scanSaves() tm.tm_year -= 1900; timestampArray[i] = std::mktime(&tm); - assert(timestampArray[i] != -1); + if(timestampArray[i] == -1) + { + std::cerr << "Error loading timestamp for save '" << name << "'\n"; + + loadableArray[i] = false; + fclose(f); + continue; + } } int version; @@ -133,7 +142,6 @@ void scanSaves() } loadableArray[i] = true; - fclose(f); } }; @@ -171,7 +179,8 @@ void scanSaves() const auto it = std::min_element(std::begin(autosaveTimestamps()), std::end(autosaveTimestamps()), - [](const std::time_t& a, const std::time_t& b) { + [](const std::time_t& a, const std::time_t& b) + { return std::difftime(a, std::time_t(nullptr)) < std::difftime(b, std::time_t(nullptr)); }); diff --git a/Quake/sbar.cpp b/Quake/sbar.cpp index 12bd210a..9f666da0 100644 --- a/Quake/sbar.cpp +++ b/Quake/sbar.cpp @@ -1343,7 +1343,8 @@ void Sbar_Draw() } else { - const auto drawAmmoIcon = [&](const int x, const int stat) { + const auto drawAmmoIcon = [&](const int x, const int stat) + { const int aid = static_cast(cl.stats[stat]); if(aid >= AID_SHELLS && aid <= AID_CELLS) @@ -1361,8 +1362,9 @@ void Sbar_Draw() drawAmmoIcon(ammo2Pos - 24, STAT_AMMO2); } - const auto drawAmmoCounter = [&](const int x, const int ammoStat, - const int ammoCounterStat) { + const auto drawAmmoCounter = + [&](const int x, const int ammoStat, const int ammoCounterStat) + { const int aid = static_cast(cl.stats[ammoStat]); if(aid == AID_NONE) { @@ -1379,30 +1381,30 @@ void Sbar_Draw() { const auto drawClipAmmoCounter = [&](const int x, const int clipStat, const int clipSizeStat, - const int ammoStat, const int ammoCounterStat) { - const int aid = static_cast(cl.stats[ammoStat]); - if(aid == AID_NONE) - { - return; - } + const int ammoStat, const int ammoCounterStat) + { + const int aid = static_cast(cl.stats[ammoStat]); + if(aid == AID_NONE) + { + return; + } - if(cl.stats[clipSizeStat] == 0) - { - // Weapon does not support reloading. - drawAmmoCounter(x, ammoStat, ammoCounterStat); - return; - } + if(cl.stats[clipSizeStat] == 0) + { + // Weapon does not support reloading. + drawAmmoCounter(x, ammoStat, ammoCounterStat); + return; + } - const int nextX = - Sbar_DrawNum(x, 0, cl.stats[clipStat], 3, 0); + const int nextX = Sbar_DrawNum(x, 0, cl.stats[clipStat], 3, 0); - char buf[32]; - sprintf(buf, "/%d", cl.stats[clipSizeStat]); - Sbar_DrawString(nextX + 4, 2, buf); + char buf[32]; + sprintf(buf, "/%d", cl.stats[clipSizeStat]); + Sbar_DrawString(nextX + 4, 2, buf); - sprintf(buf, "%d", cl.stats[ammoCounterStat]); - Sbar_DrawString(nextX + 4, 10, buf, 1.4f); - }; + sprintf(buf, "%d", cl.stats[ammoCounterStat]); + Sbar_DrawString(nextX + 4, 10, buf, 1.4f); + }; drawClipAmmoCounter(ammoPos, STAT_WEAPONCLIP, STAT_WEAPONCLIPSIZE, STAT_AMMO, STAT_AMMOCOUNTER); diff --git a/Quake/server.hpp b/Quake/server.hpp index 44c7693d..f1671e97 100644 --- a/Quake/server.hpp +++ b/Quake/server.hpp @@ -33,6 +33,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "snd_voip.hpp" #include "qcvm.hpp" #include "modeleffects.hpp" +#include "serverdefines.hpp" #include @@ -268,68 +269,6 @@ struct client_t bool knowntoqc; // putclientinserver was called }; - -//============================================================================= - -// edict->movetype values -#define MOVETYPE_NONE 0 // never moves -#define MOVETYPE_ANGLENOCLIP 1 -#define MOVETYPE_ANGLECLIP 2 -#define MOVETYPE_WALK 3 // gravity -#define MOVETYPE_STEP 4 // gravity, special edge handling -#define MOVETYPE_FLY 5 -#define MOVETYPE_TOSS 6 // gravity -#define MOVETYPE_PUSH 7 // no clip to world, push and crush -#define MOVETYPE_NOCLIP 8 -#define MOVETYPE_FLYMISSILE 9 // extra size to monsters -#define MOVETYPE_BOUNCE 10 -//#define MOVETYPE_EXT_BOUNCEMISSILE 11 -#define MOVETYPE_EXT_FOLLOW 12 - -// edict->solid values -#define SOLID_NOT 0 // no interaction with other objects -#define SOLID_TRIGGER 1 // touch on edge, but not blocking -#define SOLID_BBOX 2 // touch on edge, block -#define SOLID_SLIDEBOX 3 // touch on edge, but not an onground -#define SOLID_BSP 4 // bsp clip, touch on edge, block -#define SOLID_NOT_BUT_TOUCHABLE 5 // not solid, but can be [hand]touched -#define SOLID_EXT_CORPSE \ - 6 // passes through slidebox+other corpses, but not bsp/bbox/triggers - -// edict->deadflag values -#define DEAD_NO 0 -#define DEAD_DYING 1 -#define DEAD_DEAD 2 - -#define DAMAGE_NO 0 -#define DAMAGE_YES 1 -#define DAMAGE_AIM 2 - -// edict->flags -// clang-format off -#define FL_FLY VRUTIL_POWER_OF_TWO(0) -#define FL_SWIM VRUTIL_POWER_OF_TWO(1) -#define FL_CONVEYOR VRUTIL_POWER_OF_TWO(2) -#define FL_CLIENT VRUTIL_POWER_OF_TWO(3) -#define FL_INWATER VRUTIL_POWER_OF_TWO(4) -#define FL_MONSTER VRUTIL_POWER_OF_TWO(5) -#define FL_GODMODE VRUTIL_POWER_OF_TWO(6) -#define FL_NOTARGET VRUTIL_POWER_OF_TWO(7) -#define FL_ITEM VRUTIL_POWER_OF_TWO(8) -#define FL_ONGROUND VRUTIL_POWER_OF_TWO(9) -#define FL_PARTIALGROUND VRUTIL_POWER_OF_TWO(10) // not all corners are valid -#define FL_WATERJUMP VRUTIL_POWER_OF_TWO(11) // player jumping out of water -#define FL_JUMPRELEASED VRUTIL_POWER_OF_TWO(12) // for jump debouncing -#define FL_EASYHANDTOUCH VRUTIL_POWER_OF_TWO(13) // adds bonus to boundaries for handtouch -#define FL_SPECIFICDAMAGE VRUTIL_POWER_OF_TWO(14) // HONEY. -#define FL_FORCEGRABBABLE VRUTIL_POWER_OF_TWO(15) // VR. -// clang-format on - -#define SPAWNFLAG_NOT_EASY 256 -#define SPAWNFLAG_NOT_MEDIUM 512 -#define SPAWNFLAG_NOT_HARD 1024 -#define SPAWNFLAG_NOT_DEATHMATCH 2048 - //============================================================================ extern cvar_t teamplay; diff --git a/Quake/serverdefines.hpp b/Quake/serverdefines.hpp new file mode 100644 index 00000000..7146c4be --- /dev/null +++ b/Quake/serverdefines.hpp @@ -0,0 +1,62 @@ +#pragma once + +#include "vr_macros.hpp" + +// edict->movetype values +#define MOVETYPE_NONE 0 // never moves +#define MOVETYPE_ANGLENOCLIP 1 +#define MOVETYPE_ANGLECLIP 2 +#define MOVETYPE_WALK 3 // gravity +#define MOVETYPE_STEP 4 // gravity, special edge handling +#define MOVETYPE_FLY 5 +#define MOVETYPE_TOSS 6 // gravity +#define MOVETYPE_PUSH 7 // no clip to world, push and crush +#define MOVETYPE_NOCLIP 8 +#define MOVETYPE_FLYMISSILE 9 // extra size to monsters +#define MOVETYPE_BOUNCE 10 +//#define MOVETYPE_EXT_BOUNCEMISSILE 11 +#define MOVETYPE_EXT_FOLLOW 12 + +// edict->solid values +#define SOLID_NOT 0 // no interaction with other objects +#define SOLID_TRIGGER 1 // touch on edge, but not blocking +#define SOLID_BBOX 2 // touch on edge, block +#define SOLID_SLIDEBOX 3 // touch on edge, but not an onground +#define SOLID_BSP 4 // bsp clip, touch on edge, block +#define SOLID_NOT_BUT_TOUCHABLE 5 // not solid, but can be [hand]touched +#define SOLID_EXT_CORPSE \ + 6 // passes through slidebox+other corpses, but not bsp/bbox/triggers + +// edict->deadflag values +#define DEAD_NO 0 +#define DEAD_DYING 1 +#define DEAD_DEAD 2 + +#define DAMAGE_NO 0 +#define DAMAGE_YES 1 +#define DAMAGE_AIM 2 + +// edict->flags +// clang-format off +#define FL_FLY VRUTIL_POWER_OF_TWO(0) +#define FL_SWIM VRUTIL_POWER_OF_TWO(1) +#define FL_CONVEYOR VRUTIL_POWER_OF_TWO(2) +#define FL_CLIENT VRUTIL_POWER_OF_TWO(3) +#define FL_INWATER VRUTIL_POWER_OF_TWO(4) +#define FL_MONSTER VRUTIL_POWER_OF_TWO(5) +#define FL_GODMODE VRUTIL_POWER_OF_TWO(6) +#define FL_NOTARGET VRUTIL_POWER_OF_TWO(7) +#define FL_ITEM VRUTIL_POWER_OF_TWO(8) +#define FL_ONGROUND VRUTIL_POWER_OF_TWO(9) +#define FL_PARTIALGROUND VRUTIL_POWER_OF_TWO(10) // not all corners are valid +#define FL_WATERJUMP VRUTIL_POWER_OF_TWO(11) // player jumping out of water +#define FL_JUMPRELEASED VRUTIL_POWER_OF_TWO(12) // for jump debouncing +#define FL_EASYHANDTOUCH VRUTIL_POWER_OF_TWO(13) // adds bonus to boundaries for handtouch +#define FL_SPECIFICDAMAGE VRUTIL_POWER_OF_TWO(14) // HONEY. +#define FL_FORCEGRABBABLE VRUTIL_POWER_OF_TWO(15) // VR. +// clang-format on + +#define SPAWNFLAG_NOT_EASY 256 +#define SPAWNFLAG_NOT_MEDIUM 512 +#define SPAWNFLAG_NOT_HARD 1024 +#define SPAWNFLAG_NOT_DEATHMATCH 2048 diff --git a/Quake/shader.cpp b/Quake/shader.cpp index dda7fd3b..d008320b 100644 --- a/Quake/shader.cpp +++ b/Quake/shader.cpp @@ -3,7 +3,6 @@ #include #include -#include #include #include #include diff --git a/Quake/shader.hpp b/Quake/shader.hpp index 15c7cc4d..5d10a93b 100644 --- a/Quake/shader.hpp +++ b/Quake/shader.hpp @@ -1,18 +1,10 @@ #pragma once -#include - -#include -#include - // TODO VR: (P2) pimpl #include #include -#include -#include #include -#include namespace quake { diff --git a/Quake/snd_voip.cpp b/Quake/snd_voip.cpp index 82997bfb..6fee538b 100644 --- a/Quake/snd_voip.cpp +++ b/Quake/snd_voip.cpp @@ -78,6 +78,10 @@ void Sys_CloseLibrary(dllhandle_t* lib); #include "arch_def.hpp" #ifdef _WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + #include void Sys_CloseLibrary(dllhandle_t* lib) { @@ -106,7 +110,7 @@ dllhandle_t* Sys_LoadLibrary(const char* name, dllfunction_t* funcs) { for(i = 0; funcs[i].name; i++) { - *funcs[i].funcptr = GetProcAddress(lib, funcs[i].name); + *funcs[i].funcptr = reinterpret_cast(GetProcAddress(lib, funcs[i].name)); if(!*funcs[i].funcptr) { break; diff --git a/Quake/stb_image.hpp b/Quake/stb_image.hpp index 10a07941..ce1b29ea 100644 --- a/Quake/stb_image.hpp +++ b/Quake/stb_image.hpp @@ -1153,9 +1153,9 @@ static stbi_uc* stbi__convert_16_to_8( if(reduced == nullptr) return stbi__errpuc("outofmem", "Out of memory"); for(i = 0; i < img_len; ++i) - reduced[i] = (stbi_uc)( - (orig[i] >> 8) & 0xFF); // top half of each byte is sufficient - // approx of 16->8 bit scaling + reduced[i] = (stbi_uc)((orig[i] >> 8) & + 0xFF); // top half of each byte is sufficient + // approx of 16->8 bit scaling STBI_FREE(orig); return reduced; @@ -1173,9 +1173,9 @@ static stbi__uint16* stbi__convert_8_to_16( return (stbi__uint16*)stbi__errpuc("outofmem", "Out of memory"); for(i = 0; i < img_len; ++i) - enlarged[i] = (stbi__uint16)( - (orig[i] << 8) + - orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff + enlarged[i] = (stbi__uint16)((orig[i] << 8) + + orig[i]); // replicate to high and low + // byte, maps 0->0, 255->0xffff STBI_FREE(orig); return enlarged; @@ -4651,8 +4651,7 @@ static int stbi__parse_huffman_block(stbi__zbuf* a) stbi_uc v = *p; if(len) { - do - *zout++ = v; + do *zout++ = v; while(--len); } } @@ -4660,8 +4659,7 @@ static int stbi__parse_huffman_block(stbi__zbuf* a) { if(len) { - do - *zout++ = *p++; + do *zout++ = *p++; while(--len); } } @@ -6267,7 +6265,7 @@ static void* stbi__bmp_load(stbi__context* s, int* x, int* y, int* comp, if(flip_vertically) { stbi_uc t; - for(j = 0; j<(int)s->img_y> > 1; ++j) + for(j = 0; j < (int)s->img_y >> 1; ++j) { stbi_uc* p1 = out + j * s->img_x * target; stbi_uc* p2 = out + (s->img_y - 1 - j) * s->img_x * target; diff --git a/Quake/stb_image_write.hpp b/Quake/stb_image_write.hpp index e8ada298..dd040bfb 100644 --- a/Quake/stb_image_write.hpp +++ b/Quake/stb_image_write.hpp @@ -617,11 +617,13 @@ static int stbi_write_jpg_core(stbi__write_context* s, int width, int height, for(i = 0; i < 64; ++i) { int uvti, yti = (YQT[i] * quality + 50) / 100; - YTable[stbiw__jpg_ZigZag[i]] = - (unsigned char)(yti < 1 ? 1 : yti > 255 ? 255 : yti); + YTable[stbiw__jpg_ZigZag[i]] = (unsigned char)(yti < 1 ? 1 + : yti > 255 ? 255 + : yti); uvti = (UVQT[i] * quality + 50) / 100; - UVTable[stbiw__jpg_ZigZag[i]] = - (unsigned char)(uvti < 1 ? 1 : uvti > 255 ? 255 : uvti); + UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char)(uvti < 1 ? 1 + : uvti > 255 ? 255 + : uvti); } for(row = 0, k = 0; row < 8; ++row) diff --git a/Quake/stringcat.hpp b/Quake/stringcat.hpp new file mode 100644 index 00000000..1ef2533d --- /dev/null +++ b/Quake/stringcat.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include + +namespace quake::util +{ + +template +[[nodiscard]] std::string stringCat(const Ts&... xs) +{ + std::ostringstream oss; + (oss << ... << xs); + return oss.str(); +} + +template +[[nodiscard]] std::string stringCatSeparated( + const std::string_view separator, const T& x, const Ts&... xs) +{ + std::ostringstream oss; + oss << x; + ((oss << separator << xs), ...); + return oss.str(); +} + + +} // namespace quake::util diff --git a/Quake/sv_phys.cpp b/Quake/sv_phys.cpp index f409dc7e..8d1f82c8 100644 --- a/Quake/sv_phys.cpp +++ b/Quake/sv_phys.cpp @@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "console.hpp" #include #include "quakedef.hpp" +#include "server.hpp" #include "vr.hpp" #include "vr_cvars.hpp" #include "world.hpp" @@ -633,7 +634,8 @@ void SV_PushMove(edict_t* pusher, float movetime) check->v.groundentity = EDICT_TO_PROG(pusher); } - const auto checkBlock = [&](edict_t* ent, qvec3 adjUpMove) { + const auto checkBlock = [&](edict_t* ent, qvec3 adjUpMove) + { if(adjUpMove[2] < 0) { adjUpMove[2] *= -1.f; @@ -1078,7 +1080,8 @@ void SV_Handtouch(edict_t* ent) // Figure out tracing boundaries // (Largest possible volume containing the hands and the player) - const auto [origin, mins, maxs] = [&] { + const auto [origin, mins, maxs] = [&] + { const auto& playerOrigin = ent->v.origin; const auto& playerMins = ent->v.mins; const auto& playerMaxs = ent->v.maxs; @@ -1108,14 +1111,16 @@ void SV_Handtouch(edict_t* ent) return std::tuple{origin, -halfSize, +halfSize}; }(); - const auto traceCheck = [&](const trace_t& trace) { + const auto traceCheck = [&](const trace_t& trace) + { if(!trace.ent) { return; } - const auto handCollisionCheck = [&](const int hand, - const qvec3& handPos) { + const auto handCollisionCheck = + [&](const int hand, const qvec3& handPos) + { const float bonus = (quake::util::hasFlag(trace.ent, FL_EASYHANDTOUCH)) ? VR_GetEasyHandTouchBonus() @@ -1141,7 +1146,8 @@ void SV_Handtouch(edict_t* ent) handCollisionCheck(cVR_MainHand, ent->v.handpos); }; - const auto endHandPos = [&](const qvec3& handPos, const qvec3& handRot) { + const auto endHandPos = [&](const qvec3& handPos, const qvec3& handRot) + { const auto fwd = quake::util::getFwdVecFromPitchYawRoll(handRot); return handPos + fwd * 1._qf; }; @@ -1156,7 +1162,8 @@ void SV_Handtouch(edict_t* ent) ent->v.origin, ent->v.mins, ent->v.maxs, offHandEnd, MOVE_NORMAL, ent)); traceCheck(SV_Move(origin, mins, maxs, offHandEnd, MOVE_NORMAL, ent)); - const auto traceForHand = [&](const qvec3& handPos, const qvec3& handRot) { + const auto traceForHand = [&](const qvec3& handPos, const qvec3& handRot) + { const auto fwd = quake::util::getFwdVecFromPitchYawRoll(handRot); const auto end = handPos + fwd * 1._qf; @@ -1172,7 +1179,8 @@ void SV_VRWpntouch(edict_t* ent) { // TODO VR: (P2) code repetition with vr.cpp setHandPos - const auto doHand = [&](const HandIdx handIndex) { + const auto doHand = [&](const HandIdx handIndex) + { const auto& playerOrigin = ent->v.origin; const auto worldHandPos = VR_GetWorldHandPos(handIndex, playerOrigin); diff --git a/Quake/sv_user.cpp b/Quake/sv_user.cpp index 1dec7f27..fcef77a2 100644 --- a/Quake/sv_user.cpp +++ b/Quake/sv_user.cpp @@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // sv_user.c -- server code for moving users #include "quakedef.hpp" +#include "server.hpp" #include "vr.hpp" #include "world.hpp" #include "util.hpp" @@ -598,7 +599,7 @@ void SV_ReadClientMove(usercmd_t* move) int sequence; eval_t* val; - if(host_client->protocol_pext2 & PEXT2_PREDINFO) + if(host_client->protocol_pext2 & PEXT2_PREDINFO) { i = (unsigned short)MSG_ReadShort(); sequence = (host_client->lastmovemessage & 0xffff0000) | (i & 0xffff); @@ -626,7 +627,8 @@ void SV_ReadClientMove(usercmd_t* move) qcvm->time - MSG_ReadFloat(); host_client->num_pings++; - const auto readAngles = [&](auto& target) { + const auto readAngles = [&](auto& target) + { // read current angles for(int i = 0; i < 3; i++) { diff --git a/Quake/sys_sdl_win.cpp b/Quake/sys_sdl_win.cpp index 21dd9df5..db87fae0 100644 --- a/Quake/sys_sdl_win.cpp +++ b/Quake/sys_sdl_win.cpp @@ -49,8 +49,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include +#ifndef __MINGW32__ #pragma comment(lib, "dbgeng.lib") #define BOOST_STACKTRACE_USE_WINDBG +#endif + #include #include @@ -238,10 +241,13 @@ static void Sys_SetDPIAware() hShcore = LoadLibraryA("Shcore.dll"); hUser32 = LoadLibraryA("user32.dll"); - setDPIAwareness = (SetProcessDPIAwarenessFunc)( - hShcore ? GetProcAddress(hShcore, "SetProcessDpiAwareness") : nullptr); - setDPIAware = (SetProcessDPIAwareFunc)( - hUser32 ? GetProcAddress(hUser32, "SetProcessDPIAware") : nullptr); + setDPIAwareness = + (SetProcessDPIAwarenessFunc)(hShcore ? GetProcAddress(hShcore, + "SetProcessDpiAwareness") + : nullptr); + setDPIAware = (SetProcessDPIAwareFunc)(hUser32 ? GetProcAddress(hUser32, + "SetProcessDPIAware") + : nullptr); if(setDPIAwareness) { /* Windows 8.1+ */ diff --git a/Quake/util.cpp b/Quake/util.cpp new file mode 100644 index 00000000..536600df --- /dev/null +++ b/Quake/util.cpp @@ -0,0 +1,15 @@ +#include "util.hpp" + +#include + +namespace quake::util +{ + +[[nodiscard]] int getMaxMSAALevel() noexcept +{ + int res; + glGetIntegerv(GL_MAX_SAMPLES, &res); + return res; +} + +} // namespace quake::util diff --git a/Quake/util.hpp b/Quake/util.hpp index e2a7ce92..8ce50500 100644 --- a/Quake/util.hpp +++ b/Quake/util.hpp @@ -1,13 +1,5 @@ #pragma once -#ifdef WIN32 -#include -#include "debugapi.h" - -#undef min -#undef max -#endif - #include "q_stdinc.hpp" #include "cvar.hpp" #include "mathlib.hpp" @@ -15,19 +7,11 @@ #include "macros.hpp" #include "progs.hpp" #include "world.hpp" -#include "server.hpp" - -#include +#include "serverdefines.hpp" -#include -#include #include #include -#include #include -#include -#include -#include // TODO VR: (P2) ugly declaration float VR_GetMenuMult() noexcept; @@ -35,6 +19,12 @@ float VR_GetMenuMult() noexcept; namespace quake::util { +template +constexpr const T& qclamp(const T& v, const T& lo, const T& hi) +{ + return (v < lo) ? lo : (hi < v) ? hi : v; +} + template [[nodiscard]] QUAKE_FORCEINLINE_CONSTFN constexpr T mapRange(const T input, const T inputMin, const T inputMax, const T outputMin, @@ -51,41 +41,6 @@ template return static_cast(static_cast(x.value)); } -template -[[nodiscard]] std::string stringCat(const Ts&... xs) -{ - std::ostringstream oss; - (oss << ... << xs); - return oss.str(); -} - -template -[[nodiscard]] std::string stringCatSeparated( - const std::string_view separator, const T& x, const Ts&... xs) -{ - std::ostringstream oss; - oss << x; - ((oss << separator << xs), ...); - return oss.str(); -} - -template -void debugPrint([[maybe_unused]] const Ts&... xs) -{ -#ifdef WIN32 - OutputDebugStringA(stringCat(xs...).data()); -#endif -} - -template -void debugPrintSeparated([[maybe_unused]] const std::string_view separator, - [[maybe_unused]] const Ts&... xs) -{ -#ifdef WIN32 - OutputDebugStringA(stringCatSeparated(separator, xs...).data()); -#endif -} - template [[nodiscard]] QUAKE_FORCEINLINE_PUREFN constexpr bool boxIntersection( @@ -200,7 +155,7 @@ getAngledVectors(const qvec3& v) noexcept (cr * sp * sy + -sr * cy), // cr * cp}; - return std::tuple{forward, right, up}; + return {forward, right, up}; } [[nodiscard]] QUAKE_FORCEINLINE qvec3 getDirectionVectorFromPitchYawRoll( @@ -219,31 +174,32 @@ getAngledVectors(const qvec3& v) noexcept template [[nodiscard]] auto makeMenuCVarAdjuster(const bool isLeft) { - return - [isLeft](const cvar_t& cvar, const T incr, const T min, const T max) { - const float factor = VR_GetMenuMult() >= 3 ? 6.f : VR_GetMenuMult(); + return [isLeft](const cvar_t& cvar, const T incr, const T min, const T max) + { + const float factor = VR_GetMenuMult() >= 3 ? 6.f : VR_GetMenuMult(); - const T adjIncr = incr * static_cast(factor); + const T adjIncr = incr * static_cast(factor); - const auto newVal = static_cast( - isLeft ? cvar.value - adjIncr : cvar.value + adjIncr); - const auto res = static_cast(std::clamp(newVal, min, max)); + const auto newVal = static_cast( + isLeft ? cvar.value - adjIncr : cvar.value + adjIncr); + const auto res = static_cast(qclamp(newVal, min, max)); - Cvar_SetValue(cvar.name, res); - }; + Cvar_SetValue(cvar.name, res); + }; } template [[nodiscard]] auto makeMenuValueAdjuster(const bool isLeft) { - return [isLeft](T& value, const T incr, const T min, const T max) { + return [isLeft](T& value, const T incr, const T min, const T max) + { const float factor = VR_GetMenuMult() >= 3 ? 6.f : VR_GetMenuMult(); const T adjIncr = incr * static_cast(factor); const auto newVal = static_cast(isLeft ? value - adjIncr : value + adjIncr); - const auto res = static_cast(std::clamp(newVal, min, max)); + const auto res = static_cast(qclamp(newVal, min, max)); value = res; }; @@ -256,33 +212,6 @@ template return trace.fraction < 1.f; } -template -struct overload_set : Fs... -{ - template - constexpr overload_set(FFwds&&... fFwds) : Fs{std::forward(fFwds)}... - { - } - - using Fs::operator()...; -}; - -template -overload_set(Fs...) -> overload_set; - -template -constexpr auto make_overload_set(Fs&&... fs) -{ - return overload_set...>{std::forward(fs)...}; -} - -template -constexpr decltype(auto) match(Variant&& v, Fs&&... fs) -{ - return std::visit( - make_overload_set(std::forward(fs)...), std::forward(v)); -} - // TODO VR: (P2) reuse throughout project [[nodiscard]] QUAKE_FORCEINLINE qvec3 redirectVector( const qvec3& input, const qvec3& examplar) noexcept @@ -297,12 +226,7 @@ template return trace.plane.normal[2] > 0.7; } -[[nodiscard]] inline int getMaxMSAALevel() noexcept -{ - int res; - glGetIntegerv(GL_MAX_SAMPLES, &res); - return res; -} +[[nodiscard]] int getMaxMSAALevel() noexcept; [[nodiscard]] QUAKE_FORCEINLINE_CONSTFN constexpr bool hasFlag( const float flags, const int x) noexcept @@ -400,7 +324,8 @@ bool anyXYCorner(const edict_t& ent, F&& f) (void)xBias; // TODO VR: (P2) unused (void)yBias; // TODO VR: (P2) unused - const auto checkCorner = [&](const qvec3& pos) { + const auto checkCorner = [&](const qvec3& pos) + { const qvec3 end = pos + move; traceBuffer = SV_MoveTrace(pos, end, moveType, ent); @@ -416,10 +341,12 @@ bool anyXYCorner(const edict_t& ent, F&& f) return checkCorner(bottomOrigin); } - return anyXYCorner(*ent, [&](const qvec3& offset) { - offsetBuffer = offset; - return checkCorner(bottomOrigin + offsetBuffer); - }); + return anyXYCorner(*ent, + [&](const qvec3& offset) + { + offsetBuffer = offset; + return checkCorner(bottomOrigin + offsetBuffer); + }); } } // namespace quake::util diff --git a/Quake/variantutil.hpp b/Quake/variantutil.hpp new file mode 100644 index 00000000..dc43907b --- /dev/null +++ b/Quake/variantutil.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include + +namespace quake::util +{ + +template +struct overload_set : Fs... +{ + template + constexpr overload_set(FFwds&&... fFwds) : Fs{std::forward(fFwds)}... + { + } + + using Fs::operator()...; +}; + +template +overload_set(Fs...) -> overload_set; + +template +constexpr auto make_overload_set(Fs&&... fs) +{ + return overload_set...>{std::forward(fs)...}; +} + +template +constexpr decltype(auto) match(Variant&& v, Fs&&... fs) +{ + return std::visit( + make_overload_set(std::forward(fs)...), std::forward(v)); +} + +} // namespace quake::util diff --git a/Quake/view.cpp b/Quake/view.cpp index a1f98b17..da06baa4 100644 --- a/Quake/view.cpp +++ b/Quake/view.cpp @@ -698,22 +698,30 @@ CalcGunAngle ================== */ void CalcGunAngle(const int wpnCvarEntry, entity_t* viewent, - const qvec3& handrot, bool horizFlip) + const qvec3& handrot, const qvec3& visual_handrot, bool horizFlip) { // Skip everything if we're doing VR Controller aiming. if(vr_enabled.value && vr_aimmode.value == VrAimMode::e_CONTROLLER) { auto [oPitch, oYaw, oRoll] = VR_GetWpnAngleOffsets(wpnCvarEntry); + auto [vhrPitch, vhrYaw, vhrRoll] = visual_handrot; if(horizFlip) { oYaw *= -1.f; oRoll *= -1.f; + + vhrYaw *= -1.f; + vhrRoll *= -1.f; } - viewent->angles[PITCH] = -(handrot[PITCH]) + oPitch; - viewent->angles[YAW] = handrot[YAW] + oYaw; - viewent->angles[ROLL] = handrot[ROLL] + oRoll; + // viewent->angles[PITCH] = -(handrot[PITCH]) + oPitch + vhrPitch; + // viewent->angles[YAW] = handrot[YAW] + oYaw + vhrYaw; + // viewent->angles[ROLL] = handrot[ROLL] + oRoll + vhrRoll; + + viewent->angles[PITCH] = -(visual_handrot[PITCH]) + oPitch; + viewent->angles[YAW] = visual_handrot[YAW] + oYaw; + viewent->angles[ROLL] = visual_handrot[ROLL] + oRoll; return; } @@ -1043,7 +1051,8 @@ void V_CalcRefdef( // set up gun position view->angles = cl.viewangles; - CalcGunAngle(cvarEntry, view, cl.handrot[cVR_MainHand], false); + CalcGunAngle(cvarEntry, view, cl.handrot[cVR_MainHand], + cl.visual_handrot[cVR_MainHand], false); // VR controller aiming configuration if(vr_enabled.value && vr_aimmode.value == VrAimMode::e_CONTROLLER) @@ -1090,7 +1099,8 @@ void V_CalcRefdef( view->model = cl.model_precache[cl.stats[STAT_WEAPON]]; // TODO VR: (P2) hack - const auto isHandMdl = [](const char* mdlname) { + const auto isHandMdl = [](const char* mdlname) + { return (strcmp(mdlname, "progs/hand.mdl") == 0) || (strcmp(mdlname, "progs/hand_base.mdl") == 0) || (strcmp(mdlname, "progs/finger_thumb.mdl") == 0) || @@ -1161,7 +1171,8 @@ void V_SetupOffHandWpnViewEnt( entity_t& view = cl.offhand_viewent; // set up gun position - CalcGunAngle(cvarEntry, &view, cl.handrot[cVR_OffHand], true); + CalcGunAngle(cvarEntry, &view, cl.handrot[cVR_OffHand], + cl.visual_handrot[cVR_OffHand], true); // VR controller aiming configuration if(vr_enabled.value && vr_aimmode.value == VrAimMode::e_CONTROLLER) @@ -1176,7 +1187,8 @@ void V_SetupOffHandWpnViewEnt( view.model = cl.model_precache[cl.stats[STAT_WEAPONMODEL2]]; // TODO VR: (P2) hack - const auto isHandMdl = [](const char* mdlname) { + const auto isHandMdl = [](const char* mdlname) + { return (strcmp(mdlname, "progs/hand.mdl") == 0) || (strcmp(mdlname, "progs/hand_base.mdl") == 0) || (strcmp(mdlname, "progs/finger_thumb.mdl") == 0) || @@ -1215,7 +1227,8 @@ void V_SetupVRTorsoViewEnt() const auto [vFwd, vRight, vUp] = quake::util::getAngledVectors(playerYawOnly); - const auto heightRatio = std::clamp(VR_GetCrouchRatio(), 0._qf, 0.8_qf); + const auto heightRatio = + quake::util::qclamp(VR_GetCrouchRatio(), 0._qf, 0.8_qf); view.angles[PITCH] = 0.f + vr_vrtorso_pitch.value - (heightRatio * 35._qf); view.angles[YAW] = VR_GetBodyYawAngle() + vr_vrtorso_yaw.value; @@ -1297,7 +1310,8 @@ void V_SetupHolsterViewEnt(const int hotspot, const int modelId, view->model = cl.model_precache[modelId]; // TODO VR: (P2) hack - const auto isHandMdl = [](const char* mdlname) { + const auto isHandMdl = [](const char* mdlname) + { return (strcmp(mdlname, "progs/hand.mdl") == 0) || (strcmp(mdlname, "progs/hand_base.mdl") == 0) || (strcmp(mdlname, "progs/finger_thumb.mdl") == 0) || @@ -1691,11 +1705,11 @@ static void V_RenderView_HolsterModels() static void V_RenderView_HandModels() { - const auto doHand = [&](const FingerIdx fingerIdx, entity_t* wpnEnt, - const int wpnCvar, entity_t* otherWpnEnt, - entity_t* handEnt, const int hand, - const qvec3& extraOffset, const bool horizFlip, - const bool ghost) { + const auto doHand = + [&](const FingerIdx fingerIdx, entity_t* wpnEnt, const int wpnCvar, + entity_t* otherWpnEnt, entity_t* handEnt, const int hand, + const qvec3& extraOffset, const bool horizFlip, const bool ghost) + { if(otherWpnEnt->model != nullptr) { const int otherWpnCvar = VR_GetWpnCVarFromModel(otherWpnEnt->model); @@ -1734,7 +1748,8 @@ static void V_RenderView_HandModels() const auto doHandEntities = [&](auto& handEntities, entity_t& wpnEnt, const int handIdx, const qvec3& extraOffset, - const bool horizFlip, const bool ghost) { + const bool horizFlip, const bool ghost) + { if(wpnEnt.model == nullptr) { return; @@ -1745,8 +1760,9 @@ static void V_RenderView_HandModels() entity_t& otherWpnEnt = &wpnEnt == &cl.viewent ? cl.offhand_viewent : cl.viewent; - const auto doHandImpl = [&](const FingerIdx fingerIdx, - entity_t& handEnt) { + const auto doHandImpl = + [&](const FingerIdx fingerIdx, entity_t& handEnt) + { doHand(fingerIdx, &wpnEnt, wpnCvar, &otherWpnEnt, &handEnt, handIdx, extraOffset, horizFlip, ghost); }; @@ -1798,7 +1814,8 @@ static void V_RenderView_WeaponButtonModels() // VR: Setup weapon buttons. const auto doWpnButton = [&](entity_t* wpnEnt, entity_t* buttonEnt, const int hand, const qvec3& extraOffset, - const bool horizFlip) { + const bool horizFlip) + { if(wpnEnt->model == nullptr) { return; @@ -1822,7 +1839,8 @@ static void V_RenderView_WeaponText() // VR: Setup weapon text. const auto doWpnText = [&](entity_t* wpnEnt, textentity_t* textEnt, const int hand, const qvec3& extraOffset, - const bool horizFlip) { + const bool horizFlip) + { if(wpnEnt->model == nullptr) { return; diff --git a/Quake/vr.cpp b/Quake/vr.cpp index e1a66f41..74779167 100644 --- a/Quake/vr.cpp +++ b/Quake/vr.cpp @@ -1,6 +1,9 @@ #include "console.hpp" #include "cvar.hpp" +#include "mathlib.hpp" #include "quakedef.hpp" +#include "quakedef_macros.hpp" +#include "server.hpp" #include "vr.hpp" #include "vr_cvars.hpp" #include "util.hpp" @@ -20,14 +23,18 @@ #include "draw.hpp" #include "gl_util.hpp" #include "cmd.hpp" +#include "debugprint.hpp" #include #include #include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include #include @@ -84,7 +91,7 @@ class VecHistory public: explicit VecHistory(const std::size_t bufCapacity) noexcept - : _bufCapacity{5} + : _bufCapacity{bufCapacity} { } @@ -100,14 +107,14 @@ class VecHistory [[nodiscard]] qvec3 average() const noexcept { - if(_data.size() == 0) + if(_data.empty()) { return vec3_zero; } qvec3 res{}; - for(const auto& v : _data) + for(const qvec3& v : _data) { res += v; } @@ -128,7 +135,7 @@ struct vr_controller vr::HmdQuaternion_t raworientation; bool active{false}; - VecHistory velocityHistory{5}; + VecHistory velocityHistory{15}; VecHistory angularVelocityHistory{5}; }; @@ -218,6 +225,13 @@ bool vr_left_reloading{false}; bool vr_left_prevreloading{false}; bool vr_right_reloading{false}; bool vr_right_prevreloading{false}; +bool vr_left_reloadflicking{false}; +bool vr_left_prevreloadflicking{false}; +bool vr_right_reloadflicking{false}; +bool vr_right_prevreloadflicking{false}; + +float flickreload_effect[2]{}; +qvec3 flicktargetfwd[2]{}; vr::VRSkeletalSummaryData_t vr_ss_lefthand; vr::VRSkeletalSummaryData_t vr_ss_righthand; @@ -642,6 +656,17 @@ void VR_ApplyModelMod( return vr_right_grabbing; } +[[nodiscard]] bool VR_IsHandReloadFlicking(const int hand) noexcept +{ + if(hand == cVR_OffHand) + { + return vr_left_reloadflicking; + } + + assert(hand == cVR_MainHand); + return vr_right_reloadflicking; +} + void ApplyMod_Weapon(const int cvarEntry, aliashdr_t* const hdr) { const auto ofs = VR_GetWpnOffsets(cvarEntry); @@ -905,10 +930,9 @@ int InitWeaponCVars(int i, const char* id, const char* offsetX, (void)offHandOffsetY; (void)offHandOffsetZ; - const auto init = [&](const WpnCVar wpnCVar, const char* name, - const char* defaultVal) { - InitWeaponCVar(VR_GetWpnCVar(i, wpnCVar), name, i, defaultVal); - }; + const auto init = + [&](const WpnCVar wpnCVar, const char* name, const char* defaultVal) + { InitWeaponCVar(VR_GetWpnCVar(i, wpnCVar), name, i, defaultVal); }; // clang-format off init(WpnCVar::OffsetX, "vr_wofs_x_nn", offsetX); @@ -1249,7 +1273,8 @@ static void VR_InitActionHandles() // ----------------------------------------------------------------------- // VR: Read all action handles. - const auto readHandle = [](const char* name, vr::VRActionHandle_t& handle) { + const auto readHandle = [](const char* name, vr::VRActionHandle_t& handle) + { const auto rc = vr::VRInput()->GetActionHandle(name, &handle); if(rc != vr::EVRInputError::VRInputError_None) @@ -1317,8 +1342,9 @@ static void VR_InitActionHandles() // ----------------------------------------------------------------------- // VR: Get handles to the controllers. - const auto readInputSourceHandle = [](const char* name, - vr::VRInputValueHandle_t& handle) { + const auto readInputSourceHandle = + [](const char* name, vr::VRInputValueHandle_t& handle) + { const auto rc = vr::VRInput()->GetInputSourceHandle(name, &handle); if(rc != vr::EVRInputError::VRInputError_None) @@ -1387,6 +1413,11 @@ static void VR_InitActionHandles() bool VR_Enable() { + if(COM_CheckParm("-fakevr")) + { + Cvar_SetValueQuick(&vr_fakevr, 1); + } + if(COM_CheckParm("-novr")) { Cvar_SetValueQuick(&vr_fakevr, 1); @@ -1889,8 +1920,9 @@ void SetHandPos(int index, entity_t& player) VR_CalcWeaponWeightFTAdjusted(index) * VR_GetWpnCVarValue(wpnCvarEntry, WpnCVar::WeightPosMult); - const auto rotate_point = [](const qvec2& center, const qfloat angle, - qvec2 p) { + const auto rotate_point = + [](const qvec2& center, const qfloat angle, qvec2 p) + { // translate point back to origin: p -= center; @@ -1949,20 +1981,35 @@ void SetHandPos(int index, entity_t& player) cl.handavel[index] = controllers[index].a_velocity; // handthrowvel + if((int)vr_throw_algorithm.value == (int)VrThrowAlgorithm::Basic) + { + cl.handthrowvel[index] = openVRCoordsToQuakeCoords( + controllers[index].velocityHistory.average()); + + cl.handthrowvel[index] = + redirectVectorByYaw(cl.handthrowvel[index], VR_GetTurnYawAngle()); + } + else if((int)vr_throw_algorithm.value == (int)VrThrowAlgorithm::CrossAngVel) { - cl.handthrowvel[index] = controllers[index].velocityHistory.average(); + cl.handthrowvel[index] = {}; // TODO VR: (P1) throwing an item up with a small flick feels too strong - const auto up = - std::get<2>(getAngledVectors(controllers[index].orientation)); + const auto [fwd, right, up] = getAngledVectors(cl.handrot[index]); + + const qvec3 objOffset = + safeNormalize(up) * vr_throw_up_center_of_mass.value; + + const qvec3 angvel = openVRCoordsToQuakeCoords( + controllers[index].angularVelocityHistory.average()); + + const auto rav = redirectVector(angvel, cl.handrot[index]); - cl.handthrowvel[index] += - glm::cross(controllers[index].angularVelocityHistory.average(), - up * vr_throw_up_center_of_mass.value); + cl.handthrowvel[index] += glm::cross(rav, objOffset); - cl.handthrowvel[index] = redirectVectorByYaw( - openVRCoordsToQuakeCoords(cl.handthrowvel[index]), - VR_GetTurnYawAngle()); + const auto x = openVRCoordsToQuakeCoords( + controllers[index].velocityHistory.average()); + + cl.handthrowvel[index] += redirectVectorByYaw(x, VR_GetTurnYawAngle()); } // When positional weight is enabled, scale the hand velocity and throw @@ -2374,9 +2421,8 @@ void SetHandPos(int index, entity_t& player) const auto [eyePitch, eyeYaw, eyeRoll] = VR_GetEyesOrientation(); const auto [headFwd, headRight, headUp] = VR_GetHeadDirs(); - const auto isBetween = [](const auto x, const auto min, const auto max) { - return x >= min && x <= max; - }; + const auto isBetween = [](const auto x, const auto min, const auto max) + { return x >= min && x <= max; }; if(isBetween(eyePitch, -50.f, 50.f)) { @@ -2418,7 +2464,8 @@ void SetHandPos(int index, entity_t& player) const qvec3& adjPlayerOriginLeft, const qvec3& adjPlayerOriginRight) noexcept { - const auto fixZ = [&](qvec3 v) { + const auto fixZ = [&](qvec3 v) + { v[2] = adjPlayerOriginLeft[2]; return v; }; @@ -2558,10 +2605,9 @@ static void VR_DoTeleportation() const trace_t trace = SV_Move( adjPlayerOrigin, mins, maxs, target, MOVE_NORMAL, getPlayerEdict()); - const auto between = [](const float value, const float min, - const float max) { - return value >= min && value <= max; - }; + const auto between = + [](const float value, const float min, const float max) + { return value >= min && value <= max; }; // Allow slopes, but not walls or ceilings. const bool goodNormal = between(trace.plane.normal[2], 0.75f, 1.f); @@ -2764,9 +2810,8 @@ static void VR_DoWeaponDirSlerp() const auto slerpFwd = glm::slerp(nOldFwd, nNewFwd, ftw); const auto slerpUp = glm::slerp(nOldUp, nNewUp, ftw); - const auto anyNan = [](const qvec3& v) { - return std::isnan(v[0]) || std::isnan(v[1]) || std::isnan(v[2]); - }; + const auto anyNan = [](const qvec3& v) + { return std::isnan(v[0]) || std::isnan(v[1]) || std::isnan(v[2]); }; const auto mixFwd = anyNan(slerpFwd) ? nNewFwd : slerpFwd; const auto mixUp = anyNan(slerpUp) ? nNewUp : slerpUp; @@ -2912,8 +2957,9 @@ static void VR_Do2HAimingImpl(Vr2HMode vr2HMode, const qvec3 (&originalRots)[2], const auto frametime = cl.time - cl.oldtime; - const auto transitionVar = [&frametime](float& var, const bool predicate, - const float speed) { + const auto transitionVar = + [&frametime](float& var, const bool predicate, const float speed) + { var += frametime * (predicate ? speed : -speed); var = std::clamp(var, 0.f, 1.f); }; @@ -2934,7 +2980,8 @@ static void VR_Do2HAimingImpl(Vr2HMode vr2HMode, const qvec3 (&originalRots)[2], const bool helpingHandIsFist = cl.stats[helpingHandStatIdx] == WID_FIST; - const bool beforeMuzzle = [&] { + const bool beforeMuzzle = [&] + { const auto muzzlePos = VR_CalcFinalWpnMuzzlePos(holdingHand); const auto gunLength = glm::distance(holdingHandPos, muzzlePos); @@ -3032,13 +3079,15 @@ static void VR_FakeVRControllerAiming() cl.handrot[cVR_MainHand] = cl.viewangles; cl.handrot[cVR_OffHand] = cl.viewangles; + cl.handrot[cVR_MainHand][ROLL] = vr_fakevr_handroll.value; + cl.handrot[cVR_OffHand][ROLL] = vr_fakevr_handroll.value; } static void VR_DoWpnButton() { - const auto doWpnButton = [](const int handIdx, - const entity_t& wpnButtonEntity, - const char key) { + const auto doWpnButton = + [](const int handIdx, const entity_t& wpnButtonEntity, const char key) + { const bool hasWpnButton = !wpnButtonEntity.hidden; WpnButtonState& state = vr_wpnbutton_state[handIdx]; @@ -3106,7 +3155,8 @@ static void VR_ControllerAiming(const qvec3& orientation) // TODO VR: (P1) this is weird, the weapon model name is being used as a // key. Should switch to the WID instead - const auto setHeldWeaponCVar = [](int& cvarEntry, entity_t& viewEntity) { + const auto setHeldWeaponCVar = [](int& cvarEntry, entity_t& viewEntity) + { if(viewEntity.model) { cvarEntry = VR_GetWpnCVarFromModel(viewEntity.model); @@ -3141,6 +3191,61 @@ static void VR_ControllerAiming(const qvec3& orientation) VR_DoUpdatePrevAnglesAndPlayerYaw(); VR_DoTeleportation(); VR_DoWpnButton(); + + // flick reload + const auto doFlickReload = [](const int handIdx) + { + const bool isMainHand = handIdx == cVR_MainHand; + + bool& prev = isMainHand ? vr_right_prevreloadflicking + : vr_left_prevreloadflicking; + + bool& curr = + isMainHand ? vr_right_reloadflicking : vr_left_reloadflicking; + + const int clipStat = isMainHand ? STAT_WEAPONCLIP : STAT_WEAPONCLIP2; + + const int clipSizeStat = + isMainHand ? STAT_WEAPONCLIPSIZE : STAT_WEAPONCLIPSIZE2; + + const int wpnStat = isMainHand ? STAT_MAINHAND_WID : STAT_OFFHAND_WID; + + const bool clipFull = cl.stats[clipStat] == cl.stats[clipSizeStat]; + + if(cl.stats[wpnStat] != WID_SUPER_SHOTGUN || clipFull || + !controllers[handIdx].active) + { + prev = curr = false; + return; + } + + const qvec3 rawAngVel = openVRCoordsToQuakeCoords( + controllers[handIdx].angularVelocityHistory.average()); + + if(glm::length(rawAngVel) < 1.5f) + { + flicktargetfwd[handIdx] = + std::get<2>(getAngledVectors(cl.handrot[handIdx])); + } + + const bool aVelThresholdReached = + glm::length(rawAngVel) >= vr_spinreload_x_angular_threshold.value; + + const bool goodDot = + glm::dot(getFwdVecFromPitchYawRoll(cl.handrot[handIdx]), + flicktargetfwd[handIdx]) > 0.6f; + + prev = curr; + curr = aVelThresholdReached && goodDot; + + if(flickreload_effect[handIdx] == 0.f && !prev && curr) + { + flickreload_effect[handIdx] = 360.f; + } + }; + + doFlickReload(cVR_MainHand); + doFlickReload(cVR_OffHand); } static void VR_ResetGlobals() @@ -3174,13 +3279,11 @@ void VR_OnClientClearState() // Automatically close thumb if most other fingers are curled. if(fingerIdx == FingerIdx::Thumb && vr_finger_auto_close_thumb.value) { - const auto avg = [](const auto... xs) { - return (xs + ...) / sizeof...(xs); - }; + const auto avg = [](const auto... xs) + { return (xs + ...) / sizeof...(xs); }; - const auto avgCurl = [&](const auto... xs) { - return avg(ss.flFingerCurl[(int)xs]...); - }; + const auto avgCurl = [&](const auto... xs) + { return avg(ss.flFingerCurl[(int)xs]...); }; if(avgCurl(FingerIdx::Index, FingerIdx::Middle, FingerIdx::Ring, FingerIdx::Pinky) > 0.5) @@ -3250,6 +3353,34 @@ void VR_UpdateFingerTracking() } } +void VR_UpdateFlick() +{ + for(int i = 0; i < 2; ++i) + { + int handIdx = i; + + if(flickreload_effect[handIdx] <= 0.f) + { + flickreload_effect[handIdx] = 0.f; + cl.visual_handrot[handIdx] = cl.handrot[handIdx]; + continue; + } + + if(flickreload_effect[handIdx] > 0.f) + { + const auto frametime = cl.time - cl.oldtime; + + flickreload_effect[handIdx] -= + static_cast(frametime) * vr_spinreload_pitch_speed.value; + } + + const auto [fwd, right, up] = getAngledVectors(cl.handrot[handIdx]); + + cl.visual_handrot[handIdx] = VectorAngles( + TurnVector(fwd, up, 360.f - flickreload_effect[handIdx]), up); + } +} + void VR_UpdateScreenContent() { // Last chance to enable VR Mode - we get here when the game already @@ -3280,9 +3411,17 @@ void VR_UpdateScreenContent() switch((int)vr_aimmode.value) { - // 1: (Default) Head Aiming; View YAW is mouse+head, PITCH is - // head + default: + // 7: (Default) Controller Aiming; + case VrAimMode::e_CONTROLLER: + { + VR_ControllerAiming(orientation); + break; + } + + // 1:Head Aiming; View YAW is mouse+head, PITCH is + // head case VrAimMode::e_HEAD_MYAW: cl.viewangles[PITCH] = cl.aimangles[PITCH] = orientation[PITCH]; cl.aimangles[YAW] = cl.viewangles[YAW] = @@ -3340,13 +3479,6 @@ void VR_UpdateScreenContent() break; } - - // 7: Controller Aiming; - case VrAimMode::e_CONTROLLER: - { - VR_ControllerAiming(orientation); - break; - } } if(vr_fakevr.value == 0) @@ -3476,7 +3608,8 @@ void VR_Draw2D() // interferring with one another glEnable(GL_BLEND); - const VrMenuMode menuMode = [&] { + const VrMenuMode menuMode = [&] + { const auto v = static_cast(static_cast(vr_menumode.value)); @@ -3739,7 +3872,8 @@ struct VRAxisResult const bool bMoveForward, const bool bMoveBackward, const bool bMoveLeft, const bool bMoveRight, const bool bTurnLeft, const bool bTurnRight) { - const auto getAxis = [](const bool left, const bool right) { + const auto getAxis = [](const bool left, const bool right) + { if(left) { return -1.f; @@ -3801,7 +3935,8 @@ static void VR_DoInput_UpdateVRMouse() return; } - const auto updateWith = [&](const HandIdx handIdx) { + const auto updateWith = [&](const HandIdx handIdx) + { const auto& orig = cl.handpos[handIdx]; const auto dir = getFwdVecFromPitchYawRoll(cl.handrot[handIdx]); @@ -3823,7 +3958,8 @@ static void VR_DoInput_UpdateVRMouse() const float scale_hud = vr_menu_scale.value; - const auto sign = [](const float x) { + const auto sign = [](const float x) + { if(x >= 0) { return 1.f; @@ -3840,8 +3976,9 @@ static void VR_DoInput_UpdateVRMouse() vr_menu_mouse_y = glm::length(yProj) * ySign / scale_hud + 240 / 2; }; - const auto doControllersInOrder = [&](const HandIdx first, - const HandIdx second) { + const auto doControllersInOrder = + [&](const HandIdx first, const HandIdx second) + { if(controllers[first].active) { updateWith(first); @@ -3886,6 +4023,21 @@ static void VR_DoInput_UpdateVRMouse() vr_left_reloading = in_reloadleft.state & 1; vr_right_reloading = in_reloadright.state & 1; + vr_left_prevreloadflicking = vr_left_reloadflicking; + vr_right_prevreloadflicking = vr_right_reloadflicking; + vr_left_reloadflicking = in_flickreloadleft.state & 1; + vr_right_reloadflicking = in_flickreloadright.state & 1; + + if(vr_left_reloadflicking) + { + flickreload_effect[cVR_OffHand] = 360.f; + } + + if(vr_right_reloadflicking) + { + flickreload_effect[cVR_MainHand] = 360.f; + } + VR_DoInput_UpdateFakeMouse(); return {0.f, 0.f, 0.f}; @@ -3902,7 +4054,8 @@ static void VR_DoInput_UpdateVRMouse() } } - const auto readAnalogAction = [](const vr::VRActionHandle_t& actionHandle) { + const auto readAnalogAction = [](const vr::VRActionHandle_t& actionHandle) + { vr::InputAnalogActionData_t out; const auto rc = vr::VRInput()->GetAnalogActionData(actionHandle, &out, @@ -3918,26 +4071,26 @@ static void VR_DoInput_UpdateVRMouse() return out; }; - const auto readDigitalAction = - [](const vr::VRActionHandle_t& actionHandle) { - vr::InputDigitalActionData_t out; + const auto readDigitalAction = [](const vr::VRActionHandle_t& actionHandle) + { + vr::InputDigitalActionData_t out; - const vr::EVRInputError rc = vr::VRInput()->GetDigitalActionData( - actionHandle, &out, sizeof(vr::InputDigitalActionData_t), - vr::k_ulInvalidInputValueHandle); + const vr::EVRInputError rc = vr::VRInput()->GetDigitalActionData( + actionHandle, &out, sizeof(vr::InputDigitalActionData_t), + vr::k_ulInvalidInputValueHandle); - if(rc != vr::EVRInputError::VRInputError_None) - { - Con_Printf( - "Failed to read Steam VR digital action data, rc = %d\n", - (int)rc); - } + if(rc != vr::EVRInputError::VRInputError_None) + { + Con_Printf("Failed to read Steam VR digital action data, rc = %d\n", + (int)rc); + } - return out; - }; + return out; + }; - const auto readSkeletalSummary = [](const vr::VRActionHandle_t& - actionHandle) { + const auto readSkeletalSummary = + [](const vr::VRActionHandle_t& actionHandle) + { vr::InputSkeletalActionData_t outActionData; { @@ -4010,9 +4163,8 @@ static void VR_DoInput_UpdateVRMouse() const auto inpBTurnLeft = readDigitalAction(vrahBTurnLeft); const auto inpBTurnRight = readDigitalAction(vrahBTurnRight); - const auto isRisingEdge = [](const vr::InputDigitalActionData_t& data) { - return data.bState && data.bChanged; - }; + const auto isRisingEdge = [](const vr::InputDigitalActionData_t& data) + { return data.bState && data.bChanged; }; const bool mustFireMainHand = inpFireMainHand.bState; const bool mustFireOffHand = inpFireOffHand.bState; @@ -4097,6 +4249,19 @@ static void VR_DoInput_UpdateVRMouse() vr_left_reloading = in_reloadleft.state & 1; vr_right_reloading = in_reloadright.state & 1; + vr_left_reloadflicking = in_flickreloadleft.state & 1; + vr_right_reloadflicking = in_flickreloadright.state & 1; + + if(vr_left_reloadflicking) + { + flickreload_effect[cVR_OffHand] = 360.f; + } + + if(vr_right_reloadflicking) + { + flickreload_effect[cVR_MainHand] = 360.f; + } + VR_DoInput_UpdateFakeMouse(); } @@ -4107,7 +4272,8 @@ static void VR_DoInput_UpdateVRMouse() vr_menu_mult += static_cast(inpMenuMultiplierPlusOne.bState); vr_menu_mult += static_cast(inpMenuMultiplierPlusOne2.bState); - const auto doMenuHaptic = [&](const vr::VRInputValueHandle_t& origin) { + const auto doMenuHaptic = [&](const vr::VRInputValueHandle_t& origin) + { vr::VRInput()->TriggerHapticVibrationAction( vrahLeftHaptic, 0, 0.1, 50, 0.5, origin); @@ -4126,22 +4292,24 @@ static void VR_DoInput_UpdateVRMouse() */ const auto doMenuKeyEventWithHaptic = - [&](const int key, const vr::InputDigitalActionData_t& i) { - const bool pressed = isRisingEdge(i); + [&](const int key, const vr::InputDigitalActionData_t& i) + { + const bool pressed = isRisingEdge(i); - if(pressed) - { - doMenuHaptic(i.activeOrigin); - } + if(pressed) + { + doMenuHaptic(i.activeOrigin); + } - Key_Event(key, pressed); - return pressed; - }; + Key_Event(key, pressed); + return pressed; + }; if(inMenuOrConsole()) { const auto doAxis = [&](const int axis, const auto& inp, - const int quakeKeyNeg, const int quakeKeyPos) { + const int quakeKeyNeg, const int quakeKeyPos) + { const float lastVal = axis == 0 ? (inp.x - inp.deltaX) : (inp.y - inp.deltaY); @@ -4174,7 +4342,8 @@ static void VR_DoInput_UpdateVRMouse() } }; - const auto doBooleanInput = [&](const auto& inp, const int quakeKey) { + const auto doBooleanInput = [&](const auto& inp, const int quakeKey) + { if(inp.bChanged) { if(inp.bState) @@ -4289,8 +4458,9 @@ void VR_Move(usercmd_t* cmd) // VR: VR-related bits. { - const auto setBit = [](unsigned int& flags, const int bit, - const bool value) { + const auto setBit = + [](unsigned int& flags, const int bit, const bool value) + { if(value) { flags |= bit; @@ -4320,10 +4490,19 @@ void VR_Move(usercmd_t* cmd) cmd->vrbits0, QVR_VRBITS0_MAINHAND_RELOADING, vr_right_reloading); setBit(cmd->vrbits0, QVR_VRBITS0_MAINHAND_PREVRELOADING, vr_right_prevreloading); + setBit(cmd->vrbits0, QVR_VRBITS0_OFFHAND_RELOADFLICKING, + vr_left_reloadflicking); + setBit(cmd->vrbits0, QVR_VRBITS0_OFFHAND_PREVRELOADFLICKING, + vr_left_prevreloadflicking); + setBit(cmd->vrbits0, QVR_VRBITS0_MAINHAND_RELOADFLICKING, + vr_right_reloadflicking); + setBit(cmd->vrbits0, QVR_VRBITS0_MAINHAND_PREVRELOADFLICKING, + vr_right_prevreloadflicking); } // VR: Hands. - const auto computeHotSpot = [](const qvec3& hand) { + const auto computeHotSpot = [](const qvec3& hand) + { if(VR_InShoulderHolsterDistance(hand, VR_GetLeftShoulderHolsterPos())) { return QVR_HS_LEFT_SHOULDER_HOLSTER; @@ -4526,6 +4705,16 @@ void VR_OnLoadedPak(pack_t& pak) } } +void VR_ResetThrowAvgFrames() +{ + controllers[0].velocityHistory = controllers[1].velocityHistory = + VecHistory{static_cast(vr_throw_avg_frames.value)}; + + controllers[0].angularVelocityHistory = + controllers[1].angularVelocityHistory = VecHistory{ + static_cast(vr_throw_angvel_avg_frames.value)}; +} + // TODO VR: (P1): "seems like for the custom map a2 i can add bots with no // problem, but on ab2 if i rapidly add them then the game crashes" - can // reproduce, seems a problem with waypoint `._next`? diff --git a/Quake/vr.hpp b/Quake/vr.hpp index 8463f4c4..a827203e 100644 --- a/Quake/vr.hpp +++ b/Quake/vr.hpp @@ -239,6 +239,12 @@ enum class VrForceGrabMode : int Instant = 3, }; +enum class VrThrowAlgorithm : int +{ + Basic = 0, + CrossAngVel = 1, +}; + // // // @@ -370,6 +376,10 @@ void VR_ApplyModelMod( [[nodiscard]] bool VR_GetHorizFlip(const HandIdx handIdx) noexcept; +[[nodiscard]] bool VR_IsHandReloadFlicking(const int hand) noexcept; + +void VR_UpdateFlick(); + // // // @@ -629,3 +639,9 @@ VR_GetBodyYawAngleCalculations() noexcept; [[nodiscard]] std::string VR_ExtractPakName(const pack_t& pak); void VR_OnLoadedPak(pack_t& pak); + +// +// +// Debug + +void VR_ResetThrowAvgFrames(); diff --git a/Quake/vr_cvars.cpp b/Quake/vr_cvars.cpp index 93e71705..5ee21c10 100644 --- a/Quake/vr_cvars.cpp +++ b/Quake/vr_cvars.cpp @@ -17,7 +17,7 @@ static std::vector cvarsToRegister; { \ _cvar_registrar##name##__LINE__##_t() \ { \ - cvarsToRegister.emplace_back(&name); \ + cvarsToRegister.emplace_back(&(name)); \ } \ } _cvar_registrar##name##__LINE__ @@ -36,6 +36,7 @@ DEFINE_FCVAR(vr_viewkick, 0, CVAR_NONE); DEFINE_FCVAR(vr_lefthanded, 0, CVAR_NONE); DEFINE_FCVAR(vr_fakevr, 0, CVAR_NONE); DEFINE_FCVAR(vr_novrinit, 0, CVAR_NONE); +DEFINE_FCVAR(vr_fakevr_handroll, 0, CVAR_NONE); // // @@ -48,7 +49,7 @@ DEFINE_FCVAR_ARCHIVE(vr_crosshair, 1); DEFINE_FCVAR_ARCHIVE(vr_crosshair_depth, 0); DEFINE_FCVAR_ARCHIVE(vr_crosshair_size, 3.0); DEFINE_FCVAR_ARCHIVE(vr_crosshair_alpha, 0.25); -DEFINE_FCVAR_ARCHIVE(vr_aimmode, 7); +DEFINE_FCVAR_ARCHIVE(vr_aimmode, 6); DEFINE_FCVAR_ARCHIVE(vr_deadzone, 30); DEFINE_FCVAR_ARCHIVE(vr_gunangle, 32); DEFINE_FCVAR_ARCHIVE(vr_gunmodelpitch, 0); @@ -154,7 +155,7 @@ DEFINE_FCVAR_ARCHIVE(vr_enemy_drops_chance_mult, 1.0); DEFINE_FCVAR_ARCHIVE(vr_ammobox_drops, 0); DEFINE_FCVAR_ARCHIVE(vr_ammobox_drops_chance_mult, 1.0); DEFINE_FCVAR_ARCHIVE(vr_menumode, 0); -DEFINE_FCVAR_ARCHIVE(vr_forcegrab_powermult, 1.0); +DEFINE_FCVAR_ARCHIVE(vr_forcegrab_powermult, 0.75); DEFINE_FCVAR_ARCHIVE(vr_forcegrab_mode, 1); DEFINE_FCVAR_ARCHIVE(vr_forcegrab_range, 150.0); DEFINE_FCVAR_ARCHIVE(vr_forcegrab_radius, 18.0); @@ -174,6 +175,8 @@ DEFINE_FCVAR_ARCHIVE(vr_2h_disable_angle_threshold, 0); DEFINE_FCVAR_ARCHIVE(vr_autosave_seconds, 240); DEFINE_FCVAR_ARCHIVE(vr_autosave_on_changelevel, 1); DEFINE_FCVAR_ARCHIVE(vr_throw_up_center_of_mass, 0.1); +DEFINE_FCVAR_ARCHIVE(vr_throw_avg_frames, 15); +DEFINE_FCVAR_ARCHIVE(vr_throw_angvel_avg_frames, 5); DEFINE_FCVAR_ARCHIVE(vr_forcegrabbable_ammo_boxes, 1); DEFINE_FCVAR_ARCHIVE(vr_forcegrabbable_health_boxes, 1); DEFINE_FCVAR_ARCHIVE(vr_forcegrabbable_return_time_deathmatch, 4); @@ -186,6 +189,9 @@ DEFINE_FCVAR_ARCHIVE(vr_menu_mouse_pointer_hand, 1); DEFINE_FCVAR_ARCHIVE(vr_reload_mode, 2); DEFINE_FCVAR_ARCHIVE(vr_show_weapon_text, 1); DEFINE_FCVAR_ARCHIVE(vr_disablehaptics, 0); +DEFINE_FCVAR_ARCHIVE(vr_spinreload_pitch_speed, 1100); +DEFINE_FCVAR_ARCHIVE(vr_spinreload_x_angular_threshold, 6.5); +DEFINE_FCVAR_ARCHIVE(vr_throw_algorithm, 0); // // diff --git a/Quake/vr_cvars.hpp b/Quake/vr_cvars.hpp index 84a1cee3..62482bab 100644 --- a/Quake/vr_cvars.hpp +++ b/Quake/vr_cvars.hpp @@ -143,6 +143,7 @@ extern cvar_t vr_2h_disable_angle_threshold; extern cvar_t vr_autosave_seconds; extern cvar_t vr_autosave_on_changelevel; extern cvar_t vr_throw_up_center_of_mass; +extern cvar_t vr_throw_avg_frames; extern cvar_t vr_forcegrabbable_ammo_boxes; extern cvar_t vr_forcegrabbable_health_boxes; extern cvar_t vr_forcegrabbable_return_time_deathmatch; @@ -155,6 +156,11 @@ extern cvar_t vr_menu_mouse_pointer_hand; extern cvar_t vr_reload_mode; extern cvar_t vr_show_weapon_text; extern cvar_t vr_disablehaptics; +extern cvar_t vr_spinreload_pitch_speed; +extern cvar_t vr_spinreload_x_angular_threshold; +extern cvar_t vr_fakevr_handroll; +extern cvar_t vr_throw_algorithm; +extern cvar_t vr_throw_angvel_avg_frames; // // diff --git a/Quake/vr_showfn.cpp b/Quake/vr_showfn.cpp index 7cf6661a..0ffc8b1e 100644 --- a/Quake/vr_showfn.cpp +++ b/Quake/vr_showfn.cpp @@ -98,20 +98,22 @@ void show_virtual_stock() gl_showfn_guard guard; - guard.draw_points_and_lines([&] { - const auto [draw_main_hand, draw_off_hand] = - get_hands_to_draw(vr_show_virtual_stock.value); - - if(draw_main_hand) - { - show_virtual_stock_impl(cVR_MainHand, cVR_OffHand); - } - - if(draw_off_hand) + guard.draw_points_and_lines( + [&] { - show_virtual_stock_impl(cVR_OffHand, cVR_MainHand); - } - }); + const auto [draw_main_hand, draw_off_hand] = + get_hands_to_draw(vr_show_virtual_stock.value); + + if(draw_main_hand) + { + show_virtual_stock_impl(cVR_MainHand, cVR_OffHand); + } + + if(draw_off_hand) + { + show_virtual_stock_impl(cVR_OffHand, cVR_MainHand); + } + }); } // @@ -130,33 +132,36 @@ void show_vr_torso_debug_lines() gl_showfn_guard guard; - guard.draw_points_and_lines([&] { - const auto len = 20._qf; + guard.draw_points_and_lines( + [&] + { + const auto len = 20._qf; - const auto [adj_player_origin, adj_player_originLeft, - adj_player_originRight, head_fwd_dir, head_right_dir, head_up_dir, - mix_hand_dir, mix_final_dir] = VR_GetBodyYawAngleCalculations(); + const auto [adj_player_origin, adj_player_originLeft, + adj_player_originRight, head_fwd_dir, head_right_dir, + head_up_dir, mix_hand_dir, mix_final_dir] = + VR_GetBodyYawAngleCalculations(); - glColor4f(0, 1, 0, 0.75); - gl_vertex(adj_player_originLeft); - gl_vertex(cl.handpos[0]); + glColor4f(0, 1, 0, 0.75); + gl_vertex(adj_player_originLeft); + gl_vertex(cl.handpos[0]); - glColor4f(0, 1, 0, 0.75); - gl_vertex(adj_player_originRight); - gl_vertex(cl.handpos[1]); + glColor4f(0, 1, 0, 0.75); + gl_vertex(adj_player_originRight); + gl_vertex(cl.handpos[1]); - glColor4f(0, 1, 0, 0.75); - gl_vertex(adj_player_origin); - gl_vertex(adj_player_origin + head_fwd_dir * len); + glColor4f(0, 1, 0, 0.75); + gl_vertex(adj_player_origin); + gl_vertex(adj_player_origin + head_fwd_dir * len); - glColor4f(0, 0, 1, 0.75); - gl_vertex(adj_player_origin); - gl_vertex(adj_player_origin + mix_hand_dir * len); + glColor4f(0, 0, 1, 0.75); + gl_vertex(adj_player_origin); + gl_vertex(adj_player_origin + mix_hand_dir * len); - glColor4f(1, 0, 0, 0.75); - gl_vertex(adj_player_origin); - gl_vertex(adj_player_origin + mix_final_dir * len * 1.25_qf); - }); + glColor4f(1, 0, 0, 0.75); + gl_vertex(adj_player_origin); + gl_vertex(adj_player_origin + mix_final_dir * len * 1.25_qf); + }); } // @@ -181,7 +186,8 @@ void show_holster_impl( const auto left_holster_pos = f_left_pos(); const auto right_holster_pos = f_right_pos(); - const auto do_color = [&](const qvec3& hand, const qvec3& holster) { + const auto do_color = [&](const qvec3& hand, const qvec3& holster) + { if(VR_InHipHolsterDistance(hand, holster)) { glColor4f(1, 1, 0, 0.95); @@ -191,7 +197,8 @@ void show_holster_impl( glColor4f(0, 1, hand == main_hand_pos ? 1 : 0, 0.75); }; - const auto do_line = [&](const qvec3& hand, const qvec3& holster) { + const auto do_line = [&](const qvec3& hand, const qvec3& holster) + { do_color(hand, holster); gl_vertex(hand); gl_vertex(holster); @@ -199,22 +206,24 @@ void show_holster_impl( gl_showfn_guard guard; - guard.draw_points_and_lines([&] { - const auto [draw_main_hand, draw_off_hand] = - get_hands_to_draw(cvarValue); - - if(draw_main_hand) + guard.draw_points_and_lines( + [&] { - do_line(main_hand_pos, left_holster_pos); - do_line(main_hand_pos, right_holster_pos); - } - - if(draw_off_hand) - { - do_line(off_hand_pos, left_holster_pos); - do_line(off_hand_pos, right_holster_pos); - } - }); + const auto [draw_main_hand, draw_off_hand] = + get_hands_to_draw(cvarValue); + + if(draw_main_hand) + { + do_line(main_hand_pos, left_holster_pos); + do_line(main_hand_pos, right_holster_pos); + } + + if(draw_off_hand) + { + do_line(off_hand_pos, left_holster_pos); + do_line(off_hand_pos, right_holster_pos); + } + }); } // @@ -416,7 +425,8 @@ void show_teleport_line() const auto midB = glm::mix(start, impact, 0.85); // draw line - const auto set_color = [&](const float xAlpha) { + const auto set_color = [&](const float xAlpha) + { if(vr_teleporting_impact_valid) { glColor4f(0, 0, 1, xAlpha); @@ -428,17 +438,19 @@ void show_teleport_line() }; gl_showfn_guard guard; - guard.draw_line_strip(size, [&] { - set_color(alpha * 0.01f); - gl_vertex(start); + guard.draw_line_strip(size, + [&] + { + set_color(alpha * 0.01f); + gl_vertex(start); - set_color(alpha); - gl_vertex(midA); - gl_vertex(midB); + set_color(alpha); + gl_vertex(midA); + gl_vertex(midB); - set_color(alpha * 0.01f); - gl_vertex(impact); - }); + set_color(alpha * 0.01f); + gl_vertex(impact); + }); } // @@ -457,7 +469,8 @@ void show_wpn_offset_helper_offset() const auto do_color = [&] { glColor4f(0, 1, 1, 0.75); }; - const auto do_line = [&](const qvec3& a, const qvec3& b) { + const auto do_line = [&](const qvec3& a, const qvec3& b) + { do_color(); gl_vertex(a); gl_vertex(b); @@ -465,21 +478,24 @@ void show_wpn_offset_helper_offset() gl_showfn_guard guard; - guard.draw_points_and_lines([&] { - const auto [hand_pos, hand_rot, cvarEntry] = [&] { - const HandIdx hand_idx = vr_impl_draw_wpnoffset_helper_offset == 1 - ? cVR_MainHand - : cVR_OffHand; + guard.draw_points_and_lines( + [&] + { + const auto [hand_pos, hand_rot, cvarEntry] = [&] + { + const HandIdx hand_idx = + vr_impl_draw_wpnoffset_helper_offset == 1 ? cVR_MainHand + : cVR_OffHand; - return std::tuple{cl.handpos[hand_idx], cl.handrot[hand_idx], - VR_GetWpnCvarEntry(hand_idx)}; - }(); + return std::tuple{cl.handpos[hand_idx], cl.handrot[hand_idx], + VR_GetWpnCvarEntry(hand_idx)}; + }(); - const auto offsetPos = - quake::util::redirectVector(VR_GetWpnOffsets(cvarEntry), hand_rot); + const auto offsetPos = quake::util::redirectVector( + VR_GetWpnOffsets(cvarEntry), hand_rot); - do_line(hand_pos, hand_pos + offsetPos); - }); + do_line(hand_pos, hand_pos + offsetPos); + }); } // @@ -498,14 +514,16 @@ void show_wpn_offset_helper_muzzle() gl_showfn_guard guard; - guard.draw_points_and_lines([&] { - const auto muzzle_pos = vr_impl_draw_wpnoffset_helper_muzzle == 1 - ? VR_CalcFinalWpnMuzzlePos(cVR_MainHand) - : VR_CalcFinalWpnMuzzlePos(cVR_OffHand); + guard.draw_points_and_lines( + [&] + { + const auto muzzle_pos = vr_impl_draw_wpnoffset_helper_muzzle == 1 + ? VR_CalcFinalWpnMuzzlePos(cVR_MainHand) + : VR_CalcFinalWpnMuzzlePos(cVR_OffHand); - glColor4f(0, 1, 1, 0.75); - gl_vertex(muzzle_pos); - }); + glColor4f(0, 1, 1, 0.75); + gl_vertex(muzzle_pos); + }); } // @@ -524,15 +542,17 @@ void show_wpn_offset_helper_2h_offset() gl_showfn_guard guard; - guard.draw_points_and_lines([&] { - const auto pos = - vr_impl_draw_wpnoffset_helper_2h_offset == 1 - ? VR_Get2HHelpingHandPos(cVR_MainHand, cVR_OffHand) - : VR_Get2HHelpingHandPos(cVR_OffHand, cVR_MainHand); + guard.draw_points_and_lines( + [&] + { + const auto pos = + vr_impl_draw_wpnoffset_helper_2h_offset == 1 + ? VR_Get2HHelpingHandPos(cVR_MainHand, cVR_OffHand) + : VR_Get2HHelpingHandPos(cVR_OffHand, cVR_MainHand); - glColor4f(0, 1, 1, 0.75); - gl_vertex(pos); - }); + glColor4f(0, 1, 1, 0.75); + gl_vertex(pos); + }); } // @@ -551,24 +571,27 @@ void show_hand_pos_and_rot() gl_showfn_guard guard; - guard.draw_points_and_lines([&] { - const auto do_hand = [&](const HandIdx hand_idx) { - const auto& pos = cl.handpos[hand_idx]; - const auto& rot = cl.handrot[hand_idx]; + guard.draw_points_and_lines( + [&] + { + const auto do_hand = [&](const HandIdx hand_idx) + { + const auto& pos = cl.handpos[hand_idx]; + const auto& rot = cl.handrot[hand_idx]; - const auto fwd = quake::util::getFwdVecFromPitchYawRoll(rot); - const auto end = pos + fwd * 1._qf; + const auto fwd = quake::util::getFwdVecFromPitchYawRoll(rot); + const auto end = pos + fwd * 1._qf; - gl_vertex(pos); - gl_vertex(end); - }; + gl_vertex(pos); + gl_vertex(end); + }; - glColor4f(0, 1, 0, 0.75); - do_hand(cVR_MainHand); + glColor4f(0, 1, 0, 0.75); + do_hand(cVR_MainHand); - glColor4f(1, 0, 0, 0.75); - do_hand(cVR_OffHand); - }); + glColor4f(1, 0, 0, 0.75); + do_hand(cVR_OffHand); + }); } // TODO VR: (P1) move: @@ -578,26 +601,29 @@ void show_menu_intersection_point() gl_showfn_guard guard; - guard.draw_points_and_lines([&] { - const auto do_hand = [&](const HandIdx hand_idx) { - glColor4f(0, 1, 0, 0.75); - gl_vertex(cl.handpos[hand_idx]); - gl_vertex(vr_menu_intersection_point); - - // glColor4f(0, 0, 1, 0.5); - // gl_vertex(cl.handpos[hand_idx]); - // gl_vertex(vr_menu_target); - - // glColor4f(1, 0, 0, 0.5); - // gl_vertex(vr_menu_target); - // gl_vertex(vr_menu_target + vr_menu_normal * 205.f); - }; - - do_hand(cVR_MainHand); - - // glColor4f(1, 0, 0, 0.75); - // do_hand(cVR_OffHand); - }); + guard.draw_points_and_lines( + [&] + { + const auto do_hand = [&](const HandIdx hand_idx) + { + glColor4f(0, 1, 0, 0.75); + gl_vertex(cl.handpos[hand_idx]); + gl_vertex(vr_menu_intersection_point); + + // glColor4f(0, 0, 1, 0.5); + // gl_vertex(cl.handpos[hand_idx]); + // gl_vertex(vr_menu_target); + + // glColor4f(1, 0, 0, 0.5); + // gl_vertex(vr_menu_target); + // gl_vertex(vr_menu_target + vr_menu_normal * 205.f); + }; + + do_hand(cVR_MainHand); + + // glColor4f(1, 0, 0, 0.75); + // do_hand(cVR_OffHand); + }); } // @@ -625,7 +651,8 @@ void show_anchor_vertex_impl(const HandIdx hand_idx, const WpnCVar wpn_cvar) const bool horiz_flip = hand_idx == cVR_OffHand; - const auto do_vertex = [&](const VertexIdx vertex_idx_offset) { + const auto do_vertex = [&](const VertexIdx vertex_idx_offset) + { const auto pos = VR_GetScaledAndAngledAliasVertexPosition(anchor, anchor_vertex + vertex_idx_offset, vec3_zero, cl.handrot[hand_idx] + rots, horiz_flip); @@ -635,33 +662,39 @@ void show_anchor_vertex_impl(const HandIdx hand_idx, const WpnCVar wpn_cvar) gl_showfn_guard guard; - guard.draw_points_with_size(12.f, [&] { - glColor4f(1.f, 1.f, 1.f, 1.0f); - do_vertex(0); - }); - - guard.draw_points_with_size(6.f, [&] { - glColor4f(0.f, 0.f, 1.f, 0.95f); - do_vertex(1); - - glColor4f(0.f, 1.f, 0.f, 0.95f); - do_vertex(-1); - }); + guard.draw_points_with_size(12.f, + [&] + { + glColor4f(1.f, 1.f, 1.f, 1.0f); + do_vertex(0); + }); - guard.draw_points_with_size(3.25f, [&] { - // TODO VR: (P1) use the proper limit instead of 500 - glColor4f(0.f, 0.f, 1.f, 0.9f); - for(int i = 2; i < 500; ++i) + guard.draw_points_with_size(6.f, + [&] { - do_vertex(i); - } + glColor4f(0.f, 0.f, 1.f, 0.95f); + do_vertex(1); - glColor4f(0.f, 1.f, 0.f, 0.9f); - for(int i = 2; i < 500; ++i) + glColor4f(0.f, 1.f, 0.f, 0.95f); + do_vertex(-1); + }); + + guard.draw_points_with_size(3.25f, + [&] { - do_vertex(-i); - } - }); + // TODO VR: (P1) use the proper limit instead of 500 + glColor4f(0.f, 0.f, 1.f, 0.9f); + for(int i = 2; i < 500; ++i) + { + do_vertex(i); + } + + glColor4f(0.f, 1.f, 0.f, 0.9f); + for(int i = 2; i < 500; ++i) + { + do_vertex(-i); + } + }); } void show_anchor_vertex_for(const int impl_flag, WpnCVar wpn_cvar) diff --git a/Quake/world.cpp b/Quake/world.cpp index 1cd21d15..3f0c760a 100644 --- a/Quake/world.cpp +++ b/Quake/world.cpp @@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // world.c -- world query functions #include "quakedef.hpp" +#include "server.hpp" #include "util.hpp" #include "quakeglm_qvec3.hpp" #include "vr.hpp" @@ -320,7 +321,8 @@ them and risking the list getting corrupt. static void SV_AreaTriggerEdicts(edict_t* ent, areanode_t* node, edict_t** list, int* listcount, const int listspace) { - const auto loopEdicts = [&](link_t& edictList) { + const auto loopEdicts = [&](link_t& edictList) + { link_t* next; for(link_t* l = edictList.next; l != &edictList; l = next) @@ -410,7 +412,8 @@ void SV_TouchLinks(edict_t* ent) SV_AreaTriggerEdicts( ent, qcvm->areanodes, list, &listcount, qcvm->num_edicts); - const auto doTouch = [](edict_t* ent, edict_t* target) { + const auto doTouch = [](edict_t* ent, edict_t* target) + { const bool canBeTouched = quake::util::canBeTouched(target); if(!canBeTouched || !quake::util::entBoxIntersection(ent, target)) @@ -442,7 +445,8 @@ void SV_TouchLinks(edict_t* ent) pr_global_struct->other = old_other; }; - const auto doHandtouch = [](edict_t* ent, edict_t* target) { + const auto doHandtouch = [](edict_t* ent, edict_t* target) + { // Add some size to the hands. const qvec3 offsets{2.5f, 2.5f, 2.5f}; @@ -453,8 +457,8 @@ void SV_TouchLinks(edict_t* ent) const bool canBeHandTouched = quake::util::canBeHandTouched(target); - const auto intersects = [&](const qvec3& handMin, - const qvec3& handMax) { + const auto intersects = [&](const qvec3& handMin, const qvec3& handMax) + { // VR: This increases the boundaries for easier hand touching. const float bonus = quake::util::hasFlag(target, FL_EASYHANDTOUCH) ? VR_GetEasyHandTouchBonus() diff --git a/ReleaseFiles/Id1/config.cfg b/ReleaseFiles/Id1/config.cfg index 23f5ecbf..fcf57e95 100644 --- a/ReleaseFiles/Id1/config.cfg +++ b/ReleaseFiles/Id1/config.cfg @@ -24,10 +24,12 @@ bind "a" "+moveleft" bind "c" "+movedown" bind "d" "+moveright" bind "h" "+voip" +bind "i" "+flickreloadright" bind "k" "+grableft" bind "l" "+grabright" bind "m" "+reloadright" bind "n" "+reloadleft" +bind "o" "+flickreloadleft" bind "s" "+back" bind "t" "messagemode" bind "w" "+forward" @@ -123,7 +125,7 @@ r_shadows "1" r_slimealpha "0" r_telealpha "0.9" r_viewmodel_quake "0" -r_wateralpha "0.8" +r_wateralpha "0.3" saved1 "0" saved2 "-288" saved3 "270" @@ -213,7 +215,7 @@ vr_floor_offset "-21" vr_forcegrab_eligible_haptics "1" vr_forcegrab_eligible_particles "1" vr_forcegrab_mode "1" -vr_forcegrab_powermult "1.0" +vr_forcegrab_powermult "0.75" vr_forcegrab_radius "18" vr_forcegrab_range "150.0" vr_forcegrabbable_ammo_boxes "1" @@ -228,7 +230,7 @@ vr_gunmodely "1.3" vr_gunyaw "4" vr_headbutt_damage_mult "32" vr_headbutt_velocity_threshold "2.02" -vr_height_calibration "1.57799" +vr_height_calibration "1.646099" vr_hip_holster_thresh "6.5" vr_hip_offset_x "-3.5" vr_hip_offset_y "7.0" @@ -280,9 +282,14 @@ vr_show_upper_holsters "0" vr_show_virtual_stock "0" vr_show_weapon_text "1" vr_snap_turn "0" +vr_spinreload_pitch_speed "1100" +vr_spinreload_x_angular_threshold "6.5" vr_teleport_enabled "0" vr_teleport_range "400" -vr_throw_up_center_of_mass "0.065" +vr_throw_algorithm "1" +vr_throw_angvel_avg_frames "5" +vr_throw_avg_frames "15" +vr_throw_up_center_of_mass "0.01" vr_turn_speed "3.25" vr_upper_holster_offset_x "-4.25" vr_upper_holster_offset_y "7" @@ -1651,7 +1658,7 @@ vr_wofs_w_posmult_29 "1.0" vr_wofs_w_posmult_30 "1.0" vr_wofs_w_posmult_31 "1.0" vr_wofs_w_posmult_32 "1.0" -vr_wofs_weight_01 "0.6" +vr_wofs_weight_01 "0.5" vr_wofs_weight_02 "0.65" vr_wofs_weight_03 "0.7" vr_wofs_weight_04 "0.65" diff --git a/ReleaseFiles/Id1/pak11.pak b/ReleaseFiles/Id1/pak11.pak index c4185917..12316c39 100644 Binary files a/ReleaseFiles/Id1/pak11.pak and b/ReleaseFiles/Id1/pak11.pak differ diff --git a/Windows/VisualStudio/quakespasm-sdl2.vcxproj b/Windows/VisualStudio/quakespasm-sdl2.vcxproj index 27afb205..0aa676bc 100644 --- a/Windows/VisualStudio/quakespasm-sdl2.vcxproj +++ b/Windows/VisualStudio/quakespasm-sdl2.vcxproj @@ -112,6 +112,7 @@ Build-$(ProjectName)\$(Platform)\$(Configuration)\ true quakevr-debug + $(VC_IncludePath);$(WindowsSDK_IncludePath);C:\boost_1_80_0 $(SolutionDir)Build-$(ProjectName)\$(Platform)\$(Configuration)\ @@ -124,6 +125,7 @@ Build-$(ProjectName)\$(Platform)\$(Configuration)\ false quakevr + $(VC_IncludePath);$(WindowsSDK_IncludePath);C:\boost_1_80_0 @@ -225,7 +227,7 @@ copy "$(SolutionDir)\..\SDL2\lib\*.dll" "$(TargetDir)" Level3 EditAndContinue CompileAsCpp - stdcpp17 + stdcpp20 true @@ -312,7 +314,7 @@ make_pak.bat Level3 ProgramDatabase CompileAsCpp - stdcpp17 + stdcpp20 true AnySuitable Speed @@ -406,6 +408,7 @@ make_pak.bat + @@ -428,6 +431,7 @@ make_pak.bat + @@ -444,6 +448,7 @@ make_pak.bat + @@ -456,66 +461,118 @@ make_pak.bat + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -524,6 +581,7 @@ make_pak.bat + diff --git a/Windows/VisualStudio/quakespasm-sdl2.vcxproj.filters b/Windows/VisualStudio/quakespasm-sdl2.vcxproj.filters index 255ba06e..36d1cc68 100644 --- a/Windows/VisualStudio/quakespasm-sdl2.vcxproj.filters +++ b/Windows/VisualStudio/quakespasm-sdl2.vcxproj.filters @@ -309,6 +309,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + @@ -530,6 +539,165 @@ Header Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + diff --git a/Windows/glew/auto/extensions/gl/WGL_EXT_create_context_es2_profile b/Windows/glew/auto/extensions/gl/WGL_EXT_create_context_es2_profile index 3105737e..673c1fa4 100644 --- a/Windows/glew/auto/extensions/gl/WGL_EXT_create_context_es2_profile +++ b/Windows/glew/auto/extensions/gl/WGL_EXT_create_context_es2_profile @@ -1,4 +1,4 @@ -WGL_EXT_create_context_es2_profile +sWGL_EXT_create_context_es2_profile http://www.opengl.org/registry/specs/EXT/wgl_create_context_es2_profile.txt WGL_EXT_create_context_es2_profile diff --git a/Windows/glew/auto/src/glewinfo.rc b/Windows/glew/auto/src/glewinfo.rc index 2f46bc58..0e53152f 100644 --- a/Windows/glew/auto/src/glewinfo.rc +++ b/Windows/glew/auto/src/glewinfo.rc @@ -11,7 +11,7 @@ // // Version // -VS_VERSION_INFO VERSIONINFO +VS_VERSION_INFO VERSIONINFO FILEVERSION GLEW_MAJOR, GLEW_MINOR, GLEW_MICRO, 0 PRODUCTVERSION GLEW_MAJOR, GLEW_MINOR, GLEW_MICRO, 0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK @@ -28,7 +28,7 @@ BEGIN BEGIN BLOCK "040904b0" BEGIN - VALUE "Comments", + VALUE "Comments", "The OpenGL Extension Wrangler Library\r\n" "Copyright (C) 2002-2008, Milan Ikits \r\n" "Copyright (C) 2002-2008, Marcelo E. Magallon \r\n" @@ -107,7 +107,7 @@ BEGIN VALUE "FileDescription", "Utility for verifying extension entry points\0" VALUE "FileVersion", "GLEW_MAJOR,GLEW_MINOR,GLEW_MICRO,0\0" VALUE "InternalName", "glewinfo\0" - VALUE "LegalCopyright", "© 2002-2008 Milan Ikits & Marcelo Magallon\0" + VALUE "LegalCopyright", "� 2002-2008 Milan Ikits & Marcelo Magallon\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", FILENAME "\0" VALUE "PrivateBuild", "\0" diff --git a/clangformat_everthing.sh b/clangformat_everthing.sh new file mode 100644 index 00000000..a8d504b9 --- /dev/null +++ b/clangformat_everthing.sh @@ -0,0 +1,10 @@ +#!/bin/bash +for f in $(find ./Quake | grep pp | grep -v json | grep -v bak); do + echo $f + clang-format -i $f & +done + +wait +echo "Done" + +# find ./Quake | grep pp | grep -v bak | xargs clang-format -i