From eb66cad799ba18483fa555e9084ecb54057205cf Mon Sep 17 00:00:00 2001 From: ray <1041137+ray@users.noreply.github.com> Date: Sun, 29 Mar 2026 00:02:14 -0400 Subject: [PATCH 1/4] Merging a bunch of random stuff from old repos * Mostly null pointer fixes, spectator fixes * Added some episodic content to projects. A lot of it still crashes but I'm sick of looking at diffs * Added client-side vscript (vscript_client.nut is from Alien Swarm #noleaks) * Added achievements Signed-off-by: ray <1041137+ray@users.noreply.github.com> --- game/jbmod/cfg/autoexec.cfg | 2 +- game/jbmod/resource/clientscheme.res | 2 +- game/jbmod/resource/halflife2.ttf | Bin 55904 -> 92796 bytes .../scripts/vscripts/gamemodes/sandbox.nut | 3 +- game/jbmod/scripts/weapon_alyxgun.txt | 63 +++++++++++ game/jbmod/scripts/weapon_citizenpackage.txt | 67 ++++++++++++ game/jbmod/scripts/weapon_citizensuitcase.txt | 67 ++++++++++++ game/jbmod/scripts/weapon_oldmanharpoon.txt | 72 +++++++++++++ src/game/client/c_baseentity.cpp | 3 + src/game/client/c_baseplayer.cpp | 10 ++ src/game/client/c_baseplayer.h | 2 + src/game/client/c_prop_vehicle.cpp | 1 + src/game/client/c_vehicle_choreo_generic.cpp | 1 + src/game/client/c_vehicle_jeep.cpp | 2 + src/game/client/client_jbmod.vpc | 31 +++++- src/game/client/hl2/c_vehicle_airboat.cpp | 2 + src/game/client/hl2/c_vehicle_cannon.cpp | 1 + src/game/client/hl2/c_vehicle_crane.cpp | 1 + .../client/hl2/c_vehicle_prisoner_pod.cpp | 1 + src/game/client/hl2/c_weapon__stubs_hl2.cpp | 3 + src/game/client/hud_voicestatus.cpp | 15 ++- src/game/client/jbmod/c_jbmod_player.cpp | 20 +--- .../client/jbmod/clientmode_jbmodnormal.cpp | 44 ++++++++ .../client/jbmod/clientmode_jbmodnormal.h | 2 + src/game/client/jbmod/vscript_init.cpp | 59 +++++++++++ src/game/client/movehelper_client.cpp | 2 + src/game/client/physpropclientside.cpp | 2 + src/game/client/vscript_client.cpp | 5 +- src/game/client/vscript_client.nut | 19 ++++ src/game/server/EnvMessage.cpp | 21 +++- src/game/server/ai_activity.cpp | 2 + src/game/server/ai_basenpc.cpp | 25 ++++- src/game/server/ai_scriptconditions.h | 3 + src/game/server/baseanimating.cpp | 4 + src/game/server/baseanimating.h | 5 + src/game/server/baseentity.cpp | 11 +- src/game/server/buttons.cpp | 5 + src/game/server/client.cpp | 5 + src/game/server/colorcorrectionvolume.cpp | 2 +- src/game/server/env_zoom.cpp | 15 ++- src/game/server/filters.cpp | 2 +- src/game/server/fourwheelvehiclephysics.cpp | 2 + src/game/server/hl2/func_tank.cpp | 57 +++++++--- src/game/server/hl2/item_itemcrate.cpp | 17 +++ src/game/server/hl2/item_suit.cpp | 2 + src/game/server/hl2/npc_attackchopper.cpp | 3 +- src/game/server/hl2/npc_manhack.cpp | 5 +- src/game/server/hl2/npc_manhack.h | 1 + src/game/server/hl2/vehicle_airboat.cpp | 2 + src/game/server/hl2/vehicle_crane.cpp | 10 +- src/game/server/hl2/vehicle_jeep.cpp | 4 + src/game/server/hl2/vehicle_prisoner_pod.cpp | 12 +++ src/game/server/physics_impact_damage.cpp | 41 ++++++-- src/game/server/physics_prop_ragdoll.cpp | 37 ++++--- src/game/server/player.cpp | 99 +++++++++++------- src/game/server/player.h | 3 +- src/game/server/props.cpp | 4 + src/game/server/server_jbmod.vpc | 56 ++++++++-- src/game/server/soundscape_system.cpp | 4 +- src/game/server/vehicle_base.cpp | 8 ++ src/game/server/vehicle_base.h | 2 + src/game/shared/activitylist.cpp | 2 + src/game/shared/ai_activity.h | 2 + src/game/shared/basecombatweapon_shared.cpp | 6 +- src/game/shared/baseentity_shared.cpp | 4 + src/game/shared/baseplayer_shared.cpp | 10 ++ src/game/shared/gamemovement.cpp | 23 ++++ src/game/shared/hl2/hl2_gamerules.cpp | 2 +- src/game/shared/jbmod/jbmod_achievements.cpp | 94 +++++++++++++++++ src/game/shared/jbmod/jbmod_achievements.h | 34 ++++++ src/game/shared/jbmod/jbmod_gamerules.cpp | 11 ++ src/game/shared/jbmod/weapon_jbmodbase.cpp | 2 +- src/game/shared/jbmod/weapon_jbmodbase.h | 5 + .../jbmod/weapon_jbmodbasebasebludgeon.cpp | 7 ++ .../jbmod/weapon_jbmodbasebasebludgeon.h | 3 + src/game/shared/jbmod/weapon_physcannon.cpp | 9 ++ src/game/shared/jbmod/weapon_rpg.cpp | 27 +++++ src/game/shared/jbmod/weapon_rpg.h | 12 +++ src/game/shared/movevars_shared.cpp | 1 + src/game/shared/movevars_shared.h | 1 + src/game/shared/physics_saverestore.cpp | 2 +- src/game/shared/physics_shared.cpp | 2 +- src/game/shared/physics_shared.h | 4 + src/game/shared/ragdoll_shared.cpp | 9 +- src/game/shared/util_shared.cpp | 2 + src/game/shared/vscript_shared.cpp | 12 ++- src/public/bone_setup.cpp | 2 + src/tier1/NetAdr.cpp | 2 +- src/tier1/convar.cpp | 2 +- src/utils/common/threads.cpp | 2 +- src/utils/common/threads.h | 2 +- src/utils/common/utilmatlib.cpp | 2 + src/utils/vbsp/detail.cpp | 1 + 93 files changed, 1134 insertions(+), 136 deletions(-) create mode 100644 game/jbmod/scripts/weapon_alyxgun.txt create mode 100644 game/jbmod/scripts/weapon_citizenpackage.txt create mode 100644 game/jbmod/scripts/weapon_citizensuitcase.txt create mode 100644 game/jbmod/scripts/weapon_oldmanharpoon.txt create mode 100644 src/game/client/jbmod/vscript_init.cpp create mode 100644 src/game/client/vscript_client.nut create mode 100644 src/game/shared/jbmod/jbmod_achievements.cpp create mode 100644 src/game/shared/jbmod/jbmod_achievements.h diff --git a/game/jbmod/cfg/autoexec.cfg b/game/jbmod/cfg/autoexec.cfg index 2db53feee8d..02190b8dd13 100644 --- a/game/jbmod/cfg/autoexec.cfg +++ b/game/jbmod/cfg/autoexec.cfg @@ -3,4 +3,4 @@ sv_allowdownload "0" cl_allowupload "0" cl_allowdownload "0" cl_downloadfilter "mapsonly" -cl_playerspraydisable "1" \ No newline at end of file +cl_spraydisable "1" diff --git a/game/jbmod/resource/clientscheme.res b/game/jbmod/resource/clientscheme.res index 7e7213af955..ca644826fd1 100644 --- a/game/jbmod/resource/clientscheme.res +++ b/game/jbmod/resource/clientscheme.res @@ -1273,7 +1273,7 @@ Scheme "7" "resource/linux_fonts/DejaVuSans-BoldOblique.ttf" "8" "resource/linux_fonts/DejaVuSans-Oblique.ttf" "9" "resource/linux_fonts/LiberationSans-Regular.ttf" - "10" "resource/linux_fonts/LiberationSans-Bold.ttf" + "10" "resource/linux_fonts/LiberationSans-Bold.ttf" "11" "resource/linux_fonts/LiberationMono-Regular.ttf" "12" "resource/GorDIN-Regular.ttf" diff --git a/game/jbmod/resource/halflife2.ttf b/game/jbmod/resource/halflife2.ttf index d4555ad85f088e6b511ece00e262fff70b28b07e..059ed7c206c7551881d22e9d8e63c268a2455417 100644 GIT binary patch delta 48316 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 E22Je8s{jB1 delta 11289 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 G!2b^iEUZKT diff --git a/game/jbmod/scripts/vscripts/gamemodes/sandbox.nut b/game/jbmod/scripts/vscripts/gamemodes/sandbox.nut index ea7144a866e..e570c15bb3e 100644 --- a/game/jbmod/scripts/vscripts/gamemodes/sandbox.nut +++ b/game/jbmod/scripts/vscripts/gamemodes/sandbox.nut @@ -12,9 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -printl( "Initializing Sandbox Game Mode..." ); +printl( "Initializing Sandbox..." ); SetGameDescription( "JBMod Sandbox" ); Convars.SetValue( "sv_infinite_aux_power", 1 ); +Convars.SetValue( "mp_falldamage", 1 ); function OnPlayerSpawn( player ) { diff --git a/game/jbmod/scripts/weapon_alyxgun.txt b/game/jbmod/scripts/weapon_alyxgun.txt new file mode 100644 index 00000000000..d29c322dafd --- /dev/null +++ b/game/jbmod/scripts/weapon_alyxgun.txt @@ -0,0 +1,63 @@ +// Alyx Gun + +WeaponData +{ + // Weapon data is loaded by both the Game and Client DLLs. + "printname" "#HL2_AlyxGun" + "viewmodel" "models/weapons/W_Alyx_Gun.mdl" + "playermodel" "models/weapons/W_Alyx_Gun.mdl" //FIXME: + "anim_prefix" "alyxgun" + "bucket" "1" + "bucket_position" "4" + + "clip_size" "30" + "clip2_size" "-1" + + "default_clip" "30" + "default_clip2" "-1" + + "primary_ammo" "AlyxGun" + + "weight" "2" + "item_flags" "0" + + // Sounds for the weapon. There is a max of 16 sounds per category (i.e. max 16 "single_shot" sounds) + SoundData + { + + "reload" "Weapon_Alyx_Gun.Reload" + "reload_npc" "Weapon_Alyx_Gun.NPC_Reload" + "empty" "Weapon_Alyx_Gun.Empty" + "single_shot" "Weapon_Alyx_Gun.Single" + "single_shot_npc" "Weapon_Alyx_Gun.NPC_Single" + "special1" "Weapon_Alyx_Gun.Special1" + "special2" "Weapon_Alyx_Gun.Special2" + "burst" "Weapon_Alyx_Gun.Burst" + } + + // Weapon Sprite data is loaded by the Client DLL. + TextureData + { + "ammo" + { + "font" "WeaponIconsSmall" + "character" "p" + } + "crosshair" + { + "file" "sprites/crosshairs" + "x" "0" + "y" "48" + "width" "24" + "height" "24" + } + "autoaim" + { + "file" "sprites/crosshairs" + "x" "0" + "y" "48" + "width" "24" + "height" "24" + } + } +} \ No newline at end of file diff --git a/game/jbmod/scripts/weapon_citizenpackage.txt b/game/jbmod/scripts/weapon_citizenpackage.txt new file mode 100644 index 00000000000..0a3d1afe587 --- /dev/null +++ b/game/jbmod/scripts/weapon_citizenpackage.txt @@ -0,0 +1,67 @@ +// Citizen package. Not really a weapon, just needs to be a visible model for citizens to open. + +WeaponData +{ + // Weapon data is loaded by both the Game and Client DLLs. + "printname" "#HL2_CitizenPackage" + "viewmodel" "models/weapons/w_package.mdl" + "playermodel" "models/weapons/w_package.mdl" + "anim_prefix" "smg2" + "bucket" "5" + "bucket_position" "18" + + "clip_size" "-1" + "clip2_size" "-1" + + "default_clip" "-1" + "default_clip2" "-1" + + "primary_ammo" "None" + "secondary_ammo" "None" + + "weight" "0" + "item_flags" "0" + + // Sounds for the weapon. There is a max of 16 sounds per category (i.e. max 16 "single_shot" sounds) + SoundData + { + } + + // Weapon Sprite data is loaded by the Client DLL. + TextureData + { + "weapon" + { + "font" "WeaponIcons" + "character" "b" + } + "weapon_s" + { + "font" "WeaponIconsSelected" + "character" "b" + } + "weapon_small" + { + "font" "WeaponIconsSmall" + "character" "b" + } + "ammo" + { + "font" "WeaponIconsSmall" + "character" "s" + } + "crosshair" + { + "font" "Crosshairs" + "character" "Q" + } + "autoaim" + { + "file" "sprites/crosshairs" + "x" "0" + "y" "48" + "width" "24" + "height" "24" + } + } +} \ No newline at end of file diff --git a/game/jbmod/scripts/weapon_citizensuitcase.txt b/game/jbmod/scripts/weapon_citizensuitcase.txt new file mode 100644 index 00000000000..0d089b72c95 --- /dev/null +++ b/game/jbmod/scripts/weapon_citizensuitcase.txt @@ -0,0 +1,67 @@ +// Citizen package. Not really a weapon, just needs to be a visible model for citizens to open. + +WeaponData +{ + // Weapon data is loaded by both the Game and Client DLLs. + "printname" "#HL2_CitizenSuitcase" + "viewmodel" "models/weapons/w_suitcase_passenger.mdl" + "playermodel" "models/weapons/w_suitcase_passenger.mdl" + "anim_prefix" "smg2" + "bucket" "5" + "bucket_position" "17" + + "clip_size" "-1" + "clip2_size" "-1" + + "default_clip" "-1" + "default_clip2" "-1" + + "primary_ammo" "None" + "secondary_ammo" "None" + + "weight" "0" + "item_flags" "0" + + // Sounds for the weapon. There is a max of 16 sounds per category (i.e. max 16 "single_shot" sounds) + SoundData + { + } + + // Weapon Sprite data is loaded by the Client DLL. + TextureData + { + "weapon" + { + "font" "WeaponIcons" + "character" "b" + } + "weapon_s" + { + "font" "WeaponIconsSelected" + "character" "b" + } + "weapon_small" + { + "font" "WeaponIconsSmall" + "character" "b" + } + "ammo" + { + "font" "WeaponIconsSmall" + "character" "s" + } + "crosshair" + { + "font" "Crosshairs" + "character" "Q" + } + "autoaim" + { + "file" "sprites/crosshairs" + "x" "0" + "y" "48" + "width" "24" + "height" "24" + } + } +} \ No newline at end of file diff --git a/game/jbmod/scripts/weapon_oldmanharpoon.txt b/game/jbmod/scripts/weapon_oldmanharpoon.txt new file mode 100644 index 00000000000..9343eed23fe --- /dev/null +++ b/game/jbmod/scripts/weapon_oldmanharpoon.txt @@ -0,0 +1,72 @@ +WeaponData +{ + // Weapon data is loaded by both the Game and Client DLLs. + "printname" "#HL2_SMG1" + "viewmodel" "models/lostcoast/fisherman/harpoon.mdl" + "playermodel" "models/lostcoast/fisherman/harpoon.mdl" + "anim_prefix" "smg2" + "bucket" "2" + "bucket_position" "0" + + "clip_size" "-1" + "clip2_size" "-1" + + "default_clip" "-1" + "default_clip2" "-1" + + "primary_ammo" "None" + "secondary_ammo" "None" + + "weight" "0" + "item_flags" "0" + + // Sounds for the weapon. There is a max of 16 sounds per category (i.e. max 16 "single_shot" sounds) + SoundData + { + } + + // Weapon Sprite data is loaded by the Client DLL. + TextureData + { + "weapon" + { + "file" "sprites/w_icons1" + "x" "128" + "y" "128" + "width" "128" + "height" "64" + } + "weapon_s" + { + "file" "sprites/w_icons1b" + "x" "128" + "y" "128" + "width" "128" + "height" "64" + } + "ammo" + { + "file" "sprites/a_icons1" + "x" "55" + "y" "60" + "width" "73" + "height" "15" + } + "crosshair" + { + "file" "sprites/crosshairs" + "x" "0" + "y" "48" + "width" "24" + "height" "24" + } + "autoaim" + { + "file" "sprites/crosshairs" + "x" "0" + "y" "48" + "width" "24" + "height" "24" + } + } +} \ No newline at end of file diff --git a/src/game/client/c_baseentity.cpp b/src/game/client/c_baseentity.cpp index adbd3914412..6b65e3d908d 100644 --- a/src/game/client/c_baseentity.cpp +++ b/src/game/client/c_baseentity.cpp @@ -1962,6 +1962,9 @@ int C_BaseEntity::DrawBrushModel( bool bDrawingTranslucency, int nFlags, bool bT // Identity brushes are drawn in view->DrawWorld as an optimization Assert ( modelinfo->GetModelType( model ) == mod_brush ); + if ( !render ) + return 0; + ERenderDepthMode DepthMode = DEPTH_MODE_NORMAL; if ( ( nFlags & STUDIO_SSAODEPTHTEXTURE ) != 0 ) { diff --git a/src/game/client/c_baseplayer.cpp b/src/game/client/c_baseplayer.cpp index 76d669377d6..bf7f0b2f407 100644 --- a/src/game/client/c_baseplayer.cpp +++ b/src/game/client/c_baseplayer.cpp @@ -2892,6 +2892,16 @@ bool C_BasePlayer::GetSteamID( CSteamID *pID ) return false; } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +const Vector& C_BasePlayer::GetRenderOrigin(void) +{ + if ( IsInAVehicle() ) + InvalidateBoneCache(); + return BaseClass::GetRenderOrigin(); +} + #if defined USES_ECON_ITEMS //----------------------------------------------------------------------------- // Purpose: Update the visibility of our worn items. diff --git a/src/game/client/c_baseplayer.h b/src/game/client/c_baseplayer.h index 11a7fabca88..164cfdeb87e 100644 --- a/src/game/client/c_baseplayer.h +++ b/src/game/client/c_baseplayer.h @@ -83,6 +83,8 @@ class C_BasePlayer : public C_BaseCombatCharacter, public CGameEventListener virtual void SharedSpawn(); // Shared between client and server. virtual bool GetSteamID( CSteamID *pID ); + virtual const Vector& GetRenderOrigin(); + // IClientEntity overrides. virtual void OnPreDataChanged( DataUpdateType_t updateType ); virtual void OnDataChanged( DataUpdateType_t updateType ); diff --git a/src/game/client/c_prop_vehicle.cpp b/src/game/client/c_prop_vehicle.cpp index d093656ffff..c208f100129 100644 --- a/src/game/client/c_prop_vehicle.cpp +++ b/src/game/client/c_prop_vehicle.cpp @@ -203,6 +203,7 @@ void C_PropVehicleDriveable::DampenEyePosition( Vector &vecVehicleEyePos, QAngle //----------------------------------------------------------------------------- void C_PropVehicleDriveable::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV /*=NULL*/ ) { + if ( !m_hPlayer->IsLocalPlayer() ) return; SharedVehicleViewSmoothing( m_hPlayer, pAbsOrigin, pAbsAngles, m_bEnterAnimOn, m_bExitAnimOn, diff --git a/src/game/client/c_vehicle_choreo_generic.cpp b/src/game/client/c_vehicle_choreo_generic.cpp index 52eba09e125..88f2e0f5a69 100644 --- a/src/game/client/c_vehicle_choreo_generic.cpp +++ b/src/game/client/c_vehicle_choreo_generic.cpp @@ -206,6 +206,7 @@ int C_PropVehicleChoreoGeneric::GetPassengerRole( C_BaseCombatCharacter *pPassen //----------------------------------------------------------------------------- void C_PropVehicleChoreoGeneric::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV /*=NULL*/ ) { + if ( !m_hPlayer->IsLocalPlayer() ) return; SharedVehicleViewSmoothing( m_hPlayer, pAbsOrigin, pAbsAngles, m_bEnterAnimOn, m_bExitAnimOn, diff --git a/src/game/client/c_vehicle_jeep.cpp b/src/game/client/c_vehicle_jeep.cpp index a59e291eebb..735294aeace 100644 --- a/src/game/client/c_vehicle_jeep.cpp +++ b/src/game/client/c_vehicle_jeep.cpp @@ -144,9 +144,11 @@ void C_PropJeep::DampenEyePosition( Vector &vecVehicleEyePos, QAngle &vecVehicle return; } +#ifndef JBMOD // Keep static the sideways motion. // Dampen forward/backward motion. DampenForwardMotion( vecVehicleEyePos, vecVehicleEyeAngles, flFrameTime ); +#endif // Blend up/down motion. DampenUpMotion( vecVehicleEyePos, vecVehicleEyeAngles, flFrameTime ); diff --git a/src/game/client/client_jbmod.vpc b/src/game/client/client_jbmod.vpc index c9d0a663297..7bf9c66456e 100644 --- a/src/game/client/client_jbmod.vpc +++ b/src/game/client/client_jbmod.vpc @@ -13,11 +13,19 @@ $Configuration { $Compiler { - $AdditionalIncludeDirectories "$BASE;jbmod\ui,.\jbmod,$SRCDIR\game\shared\jbmod,.\hl2,.\hl2\elements,$SRCDIR\game\shared\hl2" - $PreprocessorDefinitions "$BASE;JBMOD;HL2MP;HL2_CLIENT_DLL;NEXT_BOT" + $AdditionalIncludeDirectories "$BASE;jbmod\ui,.\jbmod,$SRCDIR\game\shared\jbmod,.\hl2,.\hl2\elements,$SRCDIR\game\shared\hl2,$SRCDIR\game\shared\episodic" + $PreprocessorDefinitions "$BASE;JBMOD;HL2MP;HL2_CLIENT_DLL;HL2_EPISODIC;NEXT_BOT" } } +$CustomBuildStep "nut" +{ + $CommandLine "python $SRCDIR\devtools\bin\texttoarray.py $(InputPath) g_Script_$(InputName)> $(InputName)_nut.h" [$WINDOWS] + $CommandLine "python $SRCDIR\devtools\bin\texttoarray.py $(InputPath) g_Script_$(InputName)> $(InputName)_nut.h" [$POSIX] + $Description "$(InputFileName) produces $(InputName)_nut.h" + $Outputs "$(InputName)_nut.h" +} + $Project "Client (JBMod)" { $Folder "Source Files" @@ -71,6 +79,7 @@ $Project "Client (JBMod)" $File "hl2\c_plasma_beam_node.cpp" $File "hl2\c_prop_combine_ball.cpp" $File "hl2\c_prop_combine_ball.h" + $File "episodic\c_prop_scalable.cpp" $File "hl2\c_rotorwash.cpp" $File "hl2\c_script_intro.cpp" $File "$SRCDIR\game\shared\script_intro_shared.cpp" @@ -82,12 +91,19 @@ $Project "Client (JBMod)" $File "hl2\c_vehicle_cannon.cpp" $File "hl2\c_vehicle_crane.cpp" $File "hl2\c_vehicle_crane.h" + $File "episodic\c_vehicle_jeep_episodic.cpp" $File "hl2\c_vehicle_prisoner_pod.cpp" $File "hl2\c_weapon__stubs_hl2.cpp" $File "hl2\c_weapon_crossbow.cpp" + $File "episodic\c_weapon_hopwire.cpp" $File "$SRCDIR\game\shared\hl2\citadel_effects_shared.h" $File "$SRCDIR\game\shared\hl2\env_headcrabcanister_shared.cpp" $File "$SRCDIR\game\shared\hl2\env_headcrabcanister_shared.h" + $File "$SRCDIR\game\shared\episodic\npc_advisor_shared.h" + $File "episodic\c_npc_advisor.cpp" + $File "episodic\episodic_screenspaceeffects.cpp" + $File "episodic\episodic_screenspaceeffects.h" + $File "episodic\flesh_internal_material_proxy.cpp" $File "hl2\fx_antlion.cpp" $File "hl2\fx_bugbait.cpp" $File "hl2\fx_hl2_impacts.cpp" @@ -107,16 +123,21 @@ $Project "Client (JBMod)" $File "hl2\hud_credits.cpp" $File "hl2\hud_damageindicator.cpp" $File "hl2\hud_flashlight.cpp" + $File "hl2\hud_locator.cpp" $File "hl2\hud_health.cpp" $File "hl2\hud_poisondamageindicator.cpp" $File "hl2\hud_quickinfo.cpp" + $File "hl2\hud_radar.cpp" + $File "hl2\hud_radar.h" $File "hud_squadstatus.cpp" $File "hl2\hud_suitpower.cpp" $File "hl2\hud_suitpower.h" $File "hl2\hud_weaponselection.cpp" $File "hl2\hud_zoom.cpp" $File "hl2\shieldproxy.cpp" + $File "$SRCDIR\game\shared\hl2\survival_gamerules.cpp" $File "hl2\vgui_rootpanel_hl2.cpp" + $File "episodic\c_npc_puppet.cpp" } $Folder "JBMod" @@ -126,12 +147,18 @@ $Project "Client (JBMod)" $File "jbmod\c_te_jbmod_shotgun_shot.cpp" $File "jbmod\clientmode_jbmodnormal.cpp" $File "jbmod\clientmode_jbmodnormal.h" + $File "$SRCDIR\game\shared\jbmod\jbmod_achievements.cpp" + $File "$SRCDIR\game\shared\jbmod\jbmod_achievements.h" $File "$SRCDIR\game\shared\jbmod\jbmod_gamerules.cpp" $File "$SRCDIR\game\shared\jbmod\jbmod_gamerules.h" $File "$SRCDIR\game\shared\jbmod\jbmod_player_shared.cpp" $File "$SRCDIR\game\shared\jbmod\jbmod_player_shared.h" $File "$SRCDIR\game\shared\jbmod\jbmod_weapon_parse.cpp" $File "$SRCDIR\game\shared\jbmod\jbmod_weapon_parse.h" + $File "vscript_client.cpp" + $File "$SRCDIR\game\shared\vscript_shared.cpp" + $File "vscript_client.nut" + $File "jbmod\vscript_init.cpp" $Folder "Weapons" { diff --git a/src/game/client/hl2/c_vehicle_airboat.cpp b/src/game/client/hl2/c_vehicle_airboat.cpp index 167203706c5..cc1e69ac0a5 100644 --- a/src/game/client/hl2/c_vehicle_airboat.cpp +++ b/src/game/client/hl2/c_vehicle_airboat.cpp @@ -358,8 +358,10 @@ void C_PropAirboat::DampenEyePosition( Vector &vecVehicleEyePos, QAngle &vecVehi // Keep static the sideways motion. +#ifndef JBMOD // Dampen forward/backward motion. DampenForwardMotion( vecVehicleEyePos, vecVehicleEyeAngles, flFrameTime ); +#endif // Blend up/down motion. DampenUpMotion( vecVehicleEyePos, vecVehicleEyeAngles, flFrameTime ); diff --git a/src/game/client/hl2/c_vehicle_cannon.cpp b/src/game/client/hl2/c_vehicle_cannon.cpp index 74e49ce684e..9ab4d45d346 100644 --- a/src/game/client/hl2/c_vehicle_cannon.cpp +++ b/src/game/client/hl2/c_vehicle_cannon.cpp @@ -146,6 +146,7 @@ int C_PropCannon::GetPassengerRole( C_BaseCombatCharacter *pPassenger ) //----------------------------------------------------------------------------- void C_PropCannon::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV /*=NULL*/ ) { + if ( !m_hPlayer->IsLocalPlayer() ) return; SharedVehicleViewSmoothing( m_hPlayer, pAbsOrigin, pAbsAngles, m_bEnterAnimOn, m_bExitAnimOn, diff --git a/src/game/client/hl2/c_vehicle_crane.cpp b/src/game/client/hl2/c_vehicle_crane.cpp index 933bef81678..96b9fa61135 100644 --- a/src/game/client/hl2/c_vehicle_crane.cpp +++ b/src/game/client/hl2/c_vehicle_crane.cpp @@ -110,6 +110,7 @@ int C_PropCrane::GetPassengerRole( C_BaseCombatCharacter *pPassenger ) //----------------------------------------------------------------------------- void C_PropCrane::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV /*=NULL*/ ) { + if ( !m_hPlayer->IsLocalPlayer() ) return; SharedVehicleViewSmoothing( m_hPlayer, pAbsOrigin, pAbsAngles, m_bEnterAnimOn, m_bExitAnimOn, diff --git a/src/game/client/hl2/c_vehicle_prisoner_pod.cpp b/src/game/client/hl2/c_vehicle_prisoner_pod.cpp index 1b78bddab8d..13c61290359 100644 --- a/src/game/client/hl2/c_vehicle_prisoner_pod.cpp +++ b/src/game/client/hl2/c_vehicle_prisoner_pod.cpp @@ -184,6 +184,7 @@ int C_PropVehiclePrisonerPod::GetPassengerRole( C_BaseCombatCharacter *pPassenge //----------------------------------------------------------------------------- void C_PropVehiclePrisonerPod::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV /*=NULL*/ ) { + if ( !m_hPlayer->IsLocalPlayer() ) return; SharedVehicleViewSmoothing( m_hPlayer, pAbsOrigin, pAbsAngles, m_bEnterAnimOn, m_bExitAnimOn, diff --git a/src/game/client/hl2/c_weapon__stubs_hl2.cpp b/src/game/client/hl2/c_weapon__stubs_hl2.cpp index 68693bfc165..ab3b1839242 100644 --- a/src/game/client/hl2/c_weapon__stubs_hl2.cpp +++ b/src/game/client/hl2/c_weapon__stubs_hl2.cpp @@ -23,6 +23,9 @@ STUB_WEAPON_CLASS( weapon_cubemap, WeaponCubemap, C_BaseCombatWeapon ); STUB_WEAPON_CLASS( weapon_alyxgun, WeaponAlyxGun, C_HLSelectFireMachineGun ); STUB_WEAPON_CLASS( weapon_citizenpackage, WeaponCitizenPackage, C_BaseHLCombatWeapon ); STUB_WEAPON_CLASS( weapon_citizensuitcase, WeaponCitizenSuitcase, C_WeaponCitizenPackage ); +#ifdef JBMOD +STUB_WEAPON_CLASS( weapon_oldmanharpoon, WeaponOldManHarpoon, C_WeaponCitizenPackage ); +#endif #ifndef HL2MP STUB_WEAPON_CLASS( weapon_ar2, WeaponAR2, C_HLMachineGun ); diff --git a/src/game/client/hud_voicestatus.cpp b/src/game/client/hud_voicestatus.cpp index 1e396ffef93..2450c022507 100644 --- a/src/game/client/hud_voicestatus.cpp +++ b/src/game/client/hud_voicestatus.cpp @@ -59,7 +59,7 @@ void CHudVoiceSelfStatus::ApplySchemeSettings(vgui::IScheme *pScheme) { BaseClass::ApplySchemeSettings( pScheme ); -#ifdef HL2MP +#if defined( HL2MP ) || defined( JBMOD ) SetBgColor( Color( 0, 0, 0, 0 ) ); #endif } @@ -101,6 +101,8 @@ class CHudVoiceStatus : public CHudElement, public vgui::Panel virtual void Paint(); virtual void VidInit(); virtual void Init(); + virtual void LevelInit(); + virtual void LevelShutdown(); virtual void OnThink(); virtual void ApplySchemeSettings(vgui::IScheme *pScheme); @@ -188,7 +190,7 @@ void CHudVoiceStatus::ApplySchemeSettings(vgui::IScheme *pScheme) { BaseClass::ApplySchemeSettings( pScheme ); -#ifdef HL2MP +#if defined( HL2MP ) || defined( JBMOD ) SetBgColor( Color( 0, 0, 0, 0 ) ); #endif } @@ -198,6 +200,15 @@ void CHudVoiceStatus::Init( void ) ClearActiveList(); } +void CHudVoiceStatus::LevelInit(void) +{ + ClearActiveList(); +} +void CHudVoiceStatus::LevelShutdown(void) +{ + ClearActiveList(); +} + void CHudVoiceStatus::VidInit( void ) { m_pVoiceIcon = gHUD.GetIcon( "voice_player" ); diff --git a/src/game/client/jbmod/c_jbmod_player.cpp b/src/game/client/jbmod/c_jbmod_player.cpp index 256c142ef07..e411a14afd5 100644 --- a/src/game/client/jbmod/c_jbmod_player.cpp +++ b/src/game/client/jbmod/c_jbmod_player.cpp @@ -217,6 +217,8 @@ void C_JBMod_Player::Initialize( void ) CStudioHdr *C_JBMod_Player::OnNewModel( void ) { CStudioHdr *hdr = BaseClass::OnNewModel(); + if ( !hdr ) + return NULL; Initialize( ); @@ -799,16 +801,7 @@ void C_JBMod_Player::HandleSpeedChanges( CMoveData *mv ) { if ( bWantSprint ) { - if ( m_HL2Local.m_flSuitPower < 10.0f ) - { - if ( bJustPressedSpeed ) - { - CPASAttenuationFilter filter( this ); - filter.UsePredictionRules(); - EmitSound( filter, entindex(), "HL2Player.SprintNoPower" ); - } - } - else + if ( m_HL2Local.m_flSuitPower >= 10.0f ) { bSprinting = true; } @@ -844,12 +837,6 @@ void C_JBMod_Player::HandleSpeedChanges( CMoveData *mv ) if ( bSprinting ) { - if ( bJustPressedSpeed ) - { - CPASAttenuationFilter filter( this ); - filter.UsePredictionRules(); - EmitSound( filter, entindex(), "HL2Player.SprintStart" ); - } mv->m_flClientMaxSpeed = HL2_SPRINT_SPEED; } else if ( bWantWalking ) @@ -906,6 +893,7 @@ void C_JBMod_Player::ItemPreFrame( void ) { //FIXME: Held weapons like the grenade get sad when this happens m_nButtons &= ~(IN_ATTACK|IN_ATTACK2); + m_afButtonPressed &= ~(IN_ATTACK|IN_ATTACK2); } BaseClass::ItemPreFrame(); diff --git a/src/game/client/jbmod/clientmode_jbmodnormal.cpp b/src/game/client/jbmod/clientmode_jbmodnormal.cpp index 89c95982676..8de6d231945 100644 --- a/src/game/client/jbmod/clientmode_jbmodnormal.cpp +++ b/src/game/client/jbmod/clientmode_jbmodnormal.cpp @@ -18,9 +18,13 @@ #include "jbmodclientscoreboard.h" #include "jbmodtextwindow.h" #include "ienginevgui.h" +#include "jbmod_achievements.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" + +ConVar fov_desired("fov_desired", "75", FCVAR_ARCHIVE | FCVAR_USERINFO, "Sets the base field-of-view.", true, 75.0, true, 90.0); + //----------------------------------------------------------------------------- // Globals //----------------------------------------------------------------------------- @@ -122,6 +126,46 @@ void ClientModeJBModNormal::Init() { Warning( "Couldn't load combine panel scheme!\n" ); } + + CheckStartupAchievements(); + + const char *cvarsToUncheat[] = { + "cl_drawhud", + "hidehud", + NULL // End of list + }; + UnCheatConVars( cvarsToUncheat ); +} + +//----------------------------------------------------------------------------- +// Purpose: Helper to remove FCVAR_CHEAT from ConVars at runtime +// We do this instead of changing the shared code to make any future merges +// easier, and because some cvars can be defined in the engine code instead. +//----------------------------------------------------------------------------- +struct ConCommandBase_Hack +{ + void* m_pVTable; + ConCommandBase* m_pNext; + bool m_bRegistered; + const char* m_pszName; + const char* m_pszHelpString; + int m_nFlags; +}; + +void ClientModeJBModNormal::UnCheatConVars( const char **ppCVarNames ) +{ + if ( !ppCVarNames ) + return; + + for ( int i = 0; ppCVarNames[i]; i++ ) + { + ConVar *pVar = cvar->FindVar( ppCVarNames[i] ); + if ( pVar ) + { + ConCommandBase_Hack *pHack = reinterpret_cast( pVar ); + pHack->m_nFlags &= ~FCVAR_CHEAT; + } + } } diff --git a/src/game/client/jbmod/clientmode_jbmodnormal.h b/src/game/client/jbmod/clientmode_jbmodnormal.h index 457ac83792b..d7c7871fae7 100644 --- a/src/game/client/jbmod/clientmode_jbmodnormal.h +++ b/src/game/client/jbmod/clientmode_jbmodnormal.h @@ -32,6 +32,8 @@ class ClientModeJBModNormal : public ClientModeShared virtual void Init(); virtual int GetDeathMessageStartHeight( void ); + + void UnCheatConVars( const char **ppCVarNames ); }; extern IClientMode *GetClientModeNormal(); diff --git a/src/game/client/jbmod/vscript_init.cpp b/src/game/client/jbmod/vscript_init.cpp new file mode 100644 index 00000000000..cee729c8038 --- /dev/null +++ b/src/game/client/jbmod/vscript_init.cpp @@ -0,0 +1,59 @@ +// Copyright 2026 The JBMod Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cbase.h" +//#include "vscript_vgui.h" +#include "vscript_shared.h" +#include "igamesystem.h" +#include "icommandline.h" +#include "client_factorylist.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +IScriptManager *scriptmanager = NULL; + +class CScriptGameSystem : public CAutoGameSystem +{ +public: + CScriptGameSystem() : CAutoGameSystem( "CScriptGameSystem" ) {} + + virtual bool Init() + { + factorylist_t factories; + FactoryList_Retrieve( factories ); + + if ( factories.appSystemFactory && !CommandLine()->CheckParm( "-noscripting" ) ) + { + scriptmanager = (IScriptManager *)factories.appSystemFactory( VSCRIPT_INTERFACE_VERSION, NULL ); + } + + return true; + } + + virtual void LevelInitPostEntity() + { + if ( g_pScriptVM ) + { + //g_pScriptVM->RegisterInstance( &g_ScriptVGUI, "vgui" ); + } + } + + virtual void LevelShutdownPreEntity() + { + //g_ScriptVGUI.DestroyAllPanels(); + } +}; + +static CScriptGameSystem g_ScriptGameSystem; diff --git a/src/game/client/movehelper_client.cpp b/src/game/client/movehelper_client.cpp index cb4b3e169ce..59c15e88616 100644 --- a/src/game/client/movehelper_client.cpp +++ b/src/game/client/movehelper_client.cpp @@ -201,11 +201,13 @@ void CMoveHelperClient::ProcessImpacts( void ) m_pHost->SetAbsVelocity( vOldAbsVel ); //m_pHost->SetLocalVelocity( vOldLocalVel ); +#ifdef DEBUG if ( vOldLocalVel != vOldAbsVel ) { Msg( "vNewLocalVel: %f %f %f\n", m_pHost->GetLocalVelocity().x, m_pHost->GetLocalVelocity().y, m_pHost->GetLocalVelocity().z ); Msg( "vNewAbsVel: %f %f %f\n\n", m_pHost->GetAbsVelocity().x, m_pHost->GetAbsVelocity().y, m_pHost->GetAbsVelocity().z ); } +#endif // So no stuff is ever left over, sigh... ResetTouchList(); diff --git a/src/game/client/physpropclientside.cpp b/src/game/client/physpropclientside.cpp index 2f5c5f3b257..eab5d82d02a 100644 --- a/src/game/client/physpropclientside.cpp +++ b/src/game/client/physpropclientside.cpp @@ -612,6 +612,7 @@ const char *C_PhysPropClientside::ParseEntity( const char *pEntData ) Error( "classname missing from entity!\n" ); } +#ifndef JBMOD if ( !Q_strcmp( className, "prop_physics_multiplayer" ) ) { // always force clientside entitis placed in maps @@ -627,6 +628,7 @@ const char *C_PhysPropClientside::ParseEntity( const char *pEntData ) return entData.CurrentBufferPosition(); } } +#endif if ( !Q_strcmp( className, "func_proprrespawnzone" ) ) { diff --git a/src/game/client/vscript_client.cpp b/src/game/client/vscript_client.cpp index 57e00dc5414..444e2d9c80d 100644 --- a/src/game/client/vscript_client.cpp +++ b/src/game/client/vscript_client.cpp @@ -14,7 +14,9 @@ #include "isaverestore.h" #include "gamerules.h" #include "vscript_client_nut.h" +#ifndef JBMOD #include "gameui/gameui_interface.h" +#endif #ifdef PANORAMA_ENABLE #include "panorama/panorama.h" @@ -263,7 +265,7 @@ bool IsEntityCreationAllowedInScripts( void ) // // Slart: These were Portal 2 only, now they're not // - +#ifdef PORTAL2 bool __MsgFunc_SetMixLayerTriggerFactor(const CCSUsrMsg_SetMixLayerTriggerFactor &msg) { int iLayerID = engine->GetMixLayerIndex(msg.layer().c_str()); @@ -299,6 +301,7 @@ class CSetMixLayerTriggerHelper : public CAutoGameSystem }; static CSetMixLayerTriggerHelper g_SetMixLayerTriggerHelper; +#endif #ifdef PANORAMA_ENABLE diff --git a/src/game/client/vscript_client.nut b/src/game/client/vscript_client.nut new file mode 100644 index 00000000000..2efd34177b9 --- /dev/null +++ b/src/game/client/vscript_client.nut @@ -0,0 +1,19 @@ +//========== Copyright © 2008, Valve Corporation, All rights reserved. ======== +// +// Purpose: +// +//============================================================================= + +function UniqueString( string = "" ) +{ + return DoUniqueString( string.tostring() ); +} + +function IncludeScript( name, scope = null ) +{ + if ( scope == null ) + { + scope = this; + } + return ::DoIncludeScript( name, scope ); +} diff --git a/src/game/server/EnvMessage.cpp b/src/game/server/EnvMessage.cpp index a22dfc114b0..557c34c7936 100644 --- a/src/game/server/EnvMessage.cpp +++ b/src/game/server/EnvMessage.cpp @@ -219,10 +219,15 @@ void CCredits::RollOutroCredits() { sv_unlockedchapters.SetValue( "15" ); +#ifdef JBMOD + CRecipientFilter user; + user.AddAllPlayers(); + user.MakeReliable(); +#else CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - CSingleUserRecipientFilter user( pPlayer ); user.MakeReliable(); +#endif UserMessageBegin( user, "CreditsMsg" ); WRITE_BYTE( 3 ); @@ -241,10 +246,15 @@ void CCredits::InputRollOutroCredits( inputdata_t &inputdata ) void CCredits::InputShowLogo( inputdata_t &inputdata ) { +#ifdef JBMOD + CRecipientFilter user; + user.AddAllPlayers(); + user.MakeReliable(); +#else CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - CSingleUserRecipientFilter user( pPlayer ); user.MakeReliable(); +#endif if ( m_flLogoLength ) { @@ -267,10 +277,15 @@ void CCredits::InputSetLogoLength( inputdata_t &inputdata ) void CCredits::InputRollCredits( inputdata_t &inputdata ) { +#ifdef JBMOD + CRecipientFilter user; + user.AddAllPlayers(); + user.MakeReliable(); +#else CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - CSingleUserRecipientFilter user( pPlayer ); user.MakeReliable(); +#endif UserMessageBegin( user, "CreditsMsg" ); WRITE_BYTE( 2 ); diff --git a/src/game/server/ai_activity.cpp b/src/game/server/ai_activity.cpp index 3e620df68f0..0adf14baae1 100644 --- a/src/game/server/ai_activity.cpp +++ b/src/game/server/ai_activity.cpp @@ -1380,6 +1380,8 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_SLAM ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_SLAM ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_SIT_IN_VEHICLE ); + // Portal! ADD_ACTIVITY_TO_SR( ACT_VM_FIZZLE ); diff --git a/src/game/server/ai_basenpc.cpp b/src/game/server/ai_basenpc.cpp index ec4b17d1af0..e4d6bf8f860 100644 --- a/src/game/server/ai_basenpc.cpp +++ b/src/game/server/ai_basenpc.cpp @@ -662,6 +662,9 @@ ConVar ai_block_damage( "ai_block_damage","0" ); bool CAI_BaseNPC::PassesDamageFilter( const CTakeDamageInfo &info ) { +#ifdef JBMOD // We always want NPCs to die + return true; +#endif if ( ai_block_damage.GetBool() ) return false; // FIXME: hook a friendly damage filter to the npc instead? @@ -3222,7 +3225,10 @@ void CAI_BaseNPC::UpdateEfficiency( bool bInPVS ) } } - iSound = pCurrentSound->NextSound(); + if ( pCurrentSound ) + iSound = pCurrentSound->NextSound(); + else + break; } } @@ -3409,7 +3415,10 @@ void CAI_BaseNPC::UpdateSleepState( bool bInPVS ) break; } - iSound = pCurrentSound->NextSound(); + if ( pCurrentSound ) + iSound = pCurrentSound->NextSound(); + else + break; } } } @@ -6560,6 +6569,12 @@ float CAI_BaseNPC::ThrowLimit( const Vector &vecStart, //----------------------------------------------------------------------------- void CAI_BaseNPC::SetupVPhysicsHull() { + if ( GetModelPtr() == NULL ) + { + UTIL_Remove(this); + return; + } + if ( GetMoveType() == MOVETYPE_VPHYSICS || GetMoveType() == MOVETYPE_NONE ) return; @@ -6573,6 +6588,12 @@ void CAI_BaseNPC::SetupVPhysicsHull() IPhysicsObject *pPhysObj = VPhysicsGetObject(); if ( pPhysObj ) { + if ( !GetModelPtr() ) + { + DevMsg( "Warning: NPC has no model, removing it!\n" ); + this->Remove(); + return; + } float mass = Studio_GetMass(GetModelPtr()); if ( mass > 0 ) { diff --git a/src/game/server/ai_scriptconditions.h b/src/game/server/ai_scriptconditions.h index c1860c83e36..a7882671a37 100644 --- a/src/game/server/ai_scriptconditions.h +++ b/src/game/server/ai_scriptconditions.h @@ -38,6 +38,9 @@ class CAI_ProxTester { if ( m_distSq != 0 ) { + if ( pEntity1 == NULL || pEntity2 == NULL ) + return false; + float distSq = ( pEntity1->GetAbsOrigin() - pEntity2->GetAbsOrigin() ).LengthSqr(); bool fInside = ( distSq < m_distSq ); diff --git a/src/game/server/baseanimating.cpp b/src/game/server/baseanimating.cpp index fb59bca9ec4..c3dbb5673e8 100644 --- a/src/game/server/baseanimating.cpp +++ b/src/game/server/baseanimating.cpp @@ -2670,6 +2670,10 @@ void CBaseAnimating::SetModel( const char *szModelName ) { Msg( "Setting CBaseAnimating to non-studio model %s (type:%i)\n", szModelName, modelinfo->GetModelType( model ) ); } + if ( modelIndex == -1 ) + { + PrecacheModel( szModelName ); + } } if ( m_boneCacheHandle ) diff --git a/src/game/server/baseanimating.h b/src/game/server/baseanimating.h index 973162687e9..11c12346de8 100644 --- a/src/game/server/baseanimating.h +++ b/src/game/server/baseanimating.h @@ -73,6 +73,8 @@ class CBaseAnimating : public CBaseEntity // This defaults to off. void UseClientSideAnimation(); + void SetClientSideAnimation( bool val ) { m_bClientSideAnimation = val; }; + // Tells whether or not we're using client-side animation. Used for controlling // the transmission of animtime. bool IsUsingClientSideAnimation() { return m_bClientSideAnimation; } @@ -460,6 +462,9 @@ friend class CBlendingCycler; //----------------------------------------------------------------------------- inline CStudioHdr *CBaseAnimating::GetModelPtr( void ) { + if ( !this ) + return NULL; + if ( IsDynamicModelLoading() ) return NULL; diff --git a/src/game/server/baseentity.cpp b/src/game/server/baseentity.cpp index 306ce3709a2..357122bf03b 100644 --- a/src/game/server/baseentity.cpp +++ b/src/game/server/baseentity.cpp @@ -2509,7 +2509,8 @@ void CBaseEntity::UpdateOnRemove( void ) DevMsg( 2, "Warning: Deleting orphaned children of %s\n", GetClassname() ); for ( int i = childrenList.Count()-1; i >= 0; --i ) { - UTIL_Remove( childrenList[i] ); + if ( !childrenList[i]->IsPlayer() ) + UTIL_Remove( childrenList[i] ); } } @@ -5736,8 +5737,11 @@ void CC_Ent_Remove( const CCommand& args ) } // Found one? - if ( pEntity ) + if ( pEntity && pEntity != NULL ) { + if ( pEntity->IsPlayer() ) + return; + Msg( "Removed %s(%s)\n", STRING(pEntity->m_iClassname), pEntity->GetDebugName() ); UTIL_Remove( pEntity ); } @@ -5763,6 +5767,9 @@ void CC_Ent_RemoveAll( const CCommand& args ) (ent->m_iClassname != NULL_STRING && FStrEq(args[1], STRING(ent->m_iClassname))) || (ent->GetClassname()!=NULL && FStrEq(args[1], ent->GetClassname()))) { + if ( ent->IsPlayer() ) + continue; + UTIL_Remove( ent ); iCount++; } diff --git a/src/game/server/buttons.cpp b/src/game/server/buttons.cpp index e044dd84ee6..7ef5fb5a224 100644 --- a/src/game/server/buttons.cpp +++ b/src/game/server/buttons.cpp @@ -898,6 +898,11 @@ void CRotButton::Spawn( void ) SetUse(&CRotButton::ButtonUse); + if (HasSpawnFlags(SF_BUTTON_LOCKED)) + { + m_bLocked = true; + } + // // If touching activates the button, set its touch function. // diff --git a/src/game/server/client.cpp b/src/game/server/client.cpp index ae1840256fc..4594a87ccc6 100644 --- a/src/game/server/client.cpp +++ b/src/game/server/client.cpp @@ -949,6 +949,11 @@ void CC_Player_SetModel( const CCommand &args ) if ( gpGlobals->deathmatch ) return; +#ifdef JBMOD + Msg("Use cl_playermodel instead\n"); + return; +#endif + CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); if ( pPlayer && args.ArgC() == 2) { diff --git a/src/game/server/colorcorrectionvolume.cpp b/src/game/server/colorcorrectionvolume.cpp index a56cd533e38..19f45063dd6 100644 --- a/src/game/server/colorcorrectionvolume.cpp +++ b/src/game/server/colorcorrectionvolume.cpp @@ -162,7 +162,7 @@ void CColorCorrectionVolume::Spawn( void ) bool CColorCorrectionVolume::PassesTriggerFilters( CBaseEntity *pEntity ) { - if( pEntity == UTIL_GetLocalPlayer() ) + if( pEntity->IsPlayer() ) return true; return false; diff --git a/src/game/server/env_zoom.cpp b/src/game/server/env_zoom.cpp index 2a9f8478f40..e756d1c55b3 100644 --- a/src/game/server/env_zoom.cpp +++ b/src/game/server/env_zoom.cpp @@ -74,7 +74,11 @@ float GetZoomOwnerDesiredFOV( CBaseEntity *pZoomOwner ) //----------------------------------------------------------------------------- void CEnvZoom::InputZoom( inputdata_t &inputdata ) { - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + CBasePlayer *pPlayer; + if ( inputdata.pActivator && inputdata.pActivator->IsPlayer() ) + pPlayer = ToBasePlayer( inputdata.pActivator ); + else + pPlayer = UTIL_GetLocalPlayer(); if ( pPlayer ) { @@ -94,6 +98,9 @@ void CEnvZoom::InputZoom( inputdata_t &inputdata ) pPlayer->ClearZoomOwner(); } + if ( m_nFOV == pPlayer->GetDefaultFOV() ) + m_nFOV = 0; + //Stuff the values pPlayer->SetFOV( this, m_nFOV, m_flSpeed ); } @@ -105,7 +112,11 @@ void CEnvZoom::InputZoom( inputdata_t &inputdata ) //----------------------------------------------------------------------------- void CEnvZoom::InputUnZoom( inputdata_t &inputdata ) { - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + CBasePlayer *pPlayer; + if ( inputdata.pActivator && inputdata.pActivator->IsPlayer() ) + pPlayer = ToBasePlayer( inputdata.pActivator ); + else + pPlayer = UTIL_GetLocalPlayer(); if ( pPlayer ) { diff --git a/src/game/server/filters.cpp b/src/game/server/filters.cpp index 6179254dd3a..cacb8803f37 100644 --- a/src/game/server/filters.cpp +++ b/src/game/server/filters.cpp @@ -372,7 +372,7 @@ class FilterDamageType : public CBaseFilter bool PassesDamageFilterImpl(const CTakeDamageInfo &info) { - return info.GetDamageType() == m_iDamageType; + return ( ( info.GetDamageType() & m_iDamageType ) == m_iDamageType ); } int m_iDamageType; diff --git a/src/game/server/fourwheelvehiclephysics.cpp b/src/game/server/fourwheelvehiclephysics.cpp index 3a70d02d793..6bf2d3a65fa 100644 --- a/src/game/server/fourwheelvehiclephysics.cpp +++ b/src/game/server/fourwheelvehiclephysics.cpp @@ -400,6 +400,8 @@ bool CFourWheelVehiclePhysics::Initialize( const char *pVehicleScript, unsigned m_flMaxSpeed = vehicle.engine.maxSpeed; IPhysicsObject *pBody = m_pOuter->VPhysicsInitNormal( SOLID_VPHYSICS, 0, false, &solid ); + if ( !pBody ) + return false; PhysSetGameFlags( pBody, FVPHYSICS_NO_SELF_COLLISIONS | FVPHYSICS_MULTIOBJECT_ENTITY ); m_pVehicle = physenv->CreateVehicleController( pBody, vehicle, nVehicleType, physgametrace ); m_wheelCount = m_pVehicle->GetWheelCount(); diff --git a/src/game/server/hl2/func_tank.cpp b/src/game/server/hl2/func_tank.cpp index a990d1291e6..ee99d11e50c 100644 --- a/src/game/server/hl2/func_tank.cpp +++ b/src/game/server/hl2/func_tank.cpp @@ -753,6 +753,12 @@ void CFuncTank::Spawn( void ) AddSolidFlags( FSOLID_NOT_SOLID ); } + CDynamicProp *pProp = dynamic_cast( GetParent() ); + if ( pProp ) + { + pProp->SetClientSideAnimation( false ); + } + m_hControlVolume = NULL; if ( GetParent() && GetParent()->GetBaseAnimating() ) @@ -1038,6 +1044,9 @@ bool CFuncTank::StartControl( CBaseCombatCharacter *pController ) m_hController->GetActiveWeapon()->Holster(); } + if ( pController->IsPlayer() ) + pController->SetNextAttack( gpGlobals->curtime + 1.0f ); + // Set the controller's position to be the use position. m_vecControllerUsePos = m_hController->GetLocalOrigin(); @@ -2159,6 +2168,8 @@ void CFuncTank::DoMuzzleFlash( void ) CEffectData data; data.m_nAttachmentIndex = m_nBarrelAttachment; data.m_nEntIndex = pAnim->entindex(); + + pAnim->GetAttachment( m_nBarrelAttachment, data.m_vOrigin ); // FIXME: Create a custom entry here! DispatchEffect( "ChopperMuzzleFlash", data ); @@ -2171,6 +2182,8 @@ void CFuncTank::DoMuzzleFlash( void ) data.m_flScale = 1.0f; data.m_fFlags = MUZZLEFLASH_COMBINE; + pAnim->GetAttachment( m_nBarrelAttachment, data.m_vOrigin ); + DispatchEffect( "MuzzleFlash", data ); } } @@ -2437,6 +2450,8 @@ LINK_ENTITY_TO_CLASS( func_tank, CFuncTankGun ); //----------------------------------------------------------------------------- void CFuncTankGun::Fire( int bulletCount, const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker, bool bIgnoreSpread ) { + IPredictionSystem::SuppressHostEvents( NULL ); + int i; FireBulletsInfo_t info; @@ -2963,6 +2978,7 @@ void CFuncTankAirboatGun::DoMuzzleFlash( void ) data.m_nEntIndex = m_hAirboatGunModel->entindex(); data.m_nAttachmentIndex = m_nGunBarrelAttachment; data.m_flScale = 1.0f; + m_hAirboatGunModel->GetAttachment( m_nGunBarrelAttachment, data.m_vOrigin ); DispatchEffect( "AirboatMuzzleFlash", data ); } } @@ -3554,13 +3570,19 @@ void CMortarShell::FlyThink() // Beam updates START - m_pBeamEffect[0]->SetBrightness( 255 * curve1 ); - m_pBeamEffect[0]->SetWidth( 64.0f * curve1 ); - m_pBeamEffect[0]->SetEndWidth( 64.0f * curve1 ); + if ( m_pBeamEffect[0] ) + { + m_pBeamEffect[0]->SetBrightness( 255 * curve1 ); + m_pBeamEffect[0]->SetWidth( 64.0f * curve1 ); + m_pBeamEffect[0]->SetEndWidth( 64.0f * curve1 ); + } - m_pBeamEffect[1]->SetBrightness( 255 * curve1 ); - m_pBeamEffect[1]->SetWidth( 8.0f * curve1 ); - m_pBeamEffect[1]->SetEndWidth( 8.0f * curve1 ); + if ( m_pBeamEffect[1] ) + { + m_pBeamEffect[1]->SetBrightness( 255 * curve1 ); + m_pBeamEffect[1]->SetWidth( 8.0f * curve1 ); + m_pBeamEffect[1]->SetEndWidth( 8.0f * curve1 ); + } float curve2 = Bias( lifePerc, 0.1f ); @@ -3710,13 +3732,19 @@ void CMortarShell::FadeThink( void ) // Beam updates START - m_pBeamEffect[0]->SetBrightness( 255 * curve1 ); - m_pBeamEffect[0]->SetWidth( 64.0f * curve1 ); - m_pBeamEffect[0]->SetEndWidth( 64.0f * curve1 ); + if ( m_pBeamEffect[0] ) + { + m_pBeamEffect[0]->SetBrightness( 255 * curve1 ); + m_pBeamEffect[0]->SetWidth( 64.0f * curve1 ); + m_pBeamEffect[0]->SetEndWidth( 64.0f * curve1 ); + } - m_pBeamEffect[1]->SetBrightness( 255 * curve1 ); - m_pBeamEffect[1]->SetWidth( 8.0f * curve1 ); - m_pBeamEffect[1]->SetEndWidth( 8.0f * curve1 ); + if ( m_pBeamEffect[1] ) + { + m_pBeamEffect[1]->SetBrightness( 255 * curve1 ); + m_pBeamEffect[1]->SetWidth( 8.0f * curve1 ); + m_pBeamEffect[1]->SetEndWidth( 8.0f * curve1 ); + } float curve2 = Bias( lifePerc, 0.25f ); @@ -4216,6 +4244,11 @@ void CFuncTankCombineCannon::FuncTankPostThink() Vector vecTargetPosition = GetTargetPosition(); CBasePlayer *pPlayer = AI_GetSinglePlayer(); + if ( pPlayer == NULL ) + { + CreateBeam(); + return; + } Vector vecToPlayer = pPlayer->WorldSpaceCenter() - GetAbsOrigin(); vecToPlayer.NormalizeInPlace(); diff --git a/src/game/server/hl2/item_itemcrate.cpp b/src/game/server/hl2/item_itemcrate.cpp index 20ee2ff78d1..e46b75fad4a 100644 --- a/src/game/server/hl2/item_itemcrate.cpp +++ b/src/game/server/hl2/item_itemcrate.cpp @@ -8,6 +8,9 @@ #include "props.h" #include "items.h" #include "item_dynamic_resupply.h" +#ifdef JBMOD +#include "weapon_jbmodbasehlmpcombatweapon.h" +#endif // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -233,6 +236,20 @@ void CItem_ItemCrate::OnBreak( const Vector &vecVelocity, const AngularImpulse & pItem->ActivateWhenAtRest(); } +#ifdef JBMOD + if ( pItem ) + { + pItem->SetOriginalSpawnAngles( vecAngles ); + pItem->SetOriginalSpawnOrigin( vecOrigin ); + } + CWeaponJBModBase *pWeapon = dynamic_cast( pSpawn ); + if ( pWeapon ) + { + pWeapon->SetOriginalSpawnAngles( vecAngles ); + pWeapon->SetOriginalSpawnOrigin( vecOrigin ); + } +#endif + pSpawn->Spawn(); // Avoid missing items drops by a dynamic resupply because they don't think immediately diff --git a/src/game/server/hl2/item_suit.cpp b/src/game/server/hl2/item_suit.cpp index 5441234f656..e2cf32d530f 100644 --- a/src/game/server/hl2/item_suit.cpp +++ b/src/game/server/hl2/item_suit.cpp @@ -41,8 +41,10 @@ class CItemSuit : public CItem } bool MyTouch( CBasePlayer *pPlayer ) { +#ifndef JBMOD // Pick up suit even if we have one if ( pPlayer->IsSuitEquipped() ) return FALSE; +#endif if ( m_spawnflags & SF_SUIT_SHORTLOGON ) UTIL_EmitSoundSuit(pPlayer->edict(), "!HEV_A0"); // short version of suit logon, diff --git a/src/game/server/hl2/npc_attackchopper.cpp b/src/game/server/hl2/npc_attackchopper.cpp index f5a0477f321..02051bbc6b2 100644 --- a/src/game/server/hl2/npc_attackchopper.cpp +++ b/src/game/server/hl2/npc_attackchopper.cpp @@ -4737,7 +4737,8 @@ void CNPC_AttackHelicopter::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways // Make our smoke trails always come with us for ( int i = 0; i < m_nSmokeTrailCount; i++ ) { - m_hSmokeTrail[i]->SetTransmit( pInfo, bAlways ); + if ( m_hSmokeTrail[i] ) + m_hSmokeTrail[i]->SetTransmit( pInfo, bAlways ); } } diff --git a/src/game/server/hl2/npc_manhack.cpp b/src/game/server/hl2/npc_manhack.cpp index feef84f8b79..85922131207 100644 --- a/src/game/server/hl2/npc_manhack.cpp +++ b/src/game/server/hl2/npc_manhack.cpp @@ -3007,6 +3007,8 @@ void CNPC_Manhack::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t r } else { + m_pPrevOwner.Set( GetOwnerEntity() ); + // Suppress collisions between the manhack and the player; we're currently bumping // almost certainly because it's not purely a physics object. SetOwnerEntity( pPhysGunUser ); @@ -3023,7 +3025,8 @@ void CNPC_Manhack::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t r void CNPC_Manhack::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) { // Stop suppressing collisions between the manhack and the player - SetOwnerEntity( NULL ); + SetOwnerEntity( m_pPrevOwner.Get() ); + m_pPrevOwner.Set( NULL ); m_bHeld = false; diff --git a/src/game/server/hl2/npc_manhack.h b/src/game/server/hl2/npc_manhack.h index 17a3cedb181..cdc7bd5f83a 100644 --- a/src/game/server/hl2/npc_manhack.h +++ b/src/game/server/hl2/npc_manhack.h @@ -254,6 +254,7 @@ DECLARE_SERVERCLASS(); CSprite *m_pLightGlow; CHandle m_hSmokeTrail; + CHandle m_pPrevOwner; int m_iPanel1; int m_iPanel2; diff --git a/src/game/server/hl2/vehicle_airboat.cpp b/src/game/server/hl2/vehicle_airboat.cpp index f29931c0524..11d82da5df3 100644 --- a/src/game/server/hl2/vehicle_airboat.cpp +++ b/src/game/server/hl2/vehicle_airboat.cpp @@ -1572,6 +1572,8 @@ void CPropAirboat::FireGun( ) Vector vecGunPosition; Vector vecForward; GetAttachment( m_nGunBarrelAttachment, vecGunPosition, &vecForward ); + + CDisablePredictionFiltering disabler; // NOTE: For the airboat, unable to fire really means the aim is clamped Vector vecAimPoint; diff --git a/src/game/server/hl2/vehicle_crane.cpp b/src/game/server/hl2/vehicle_crane.cpp index c8e30b4ffba..7a9475bbc44 100644 --- a/src/game/server/hl2/vehicle_crane.cpp +++ b/src/game/server/hl2/vehicle_crane.cpp @@ -233,6 +233,8 @@ bool CPropCrane::CreateVPhysics( void ) //----------------------------------------------------------------------------- void CPropCrane::UpdateOnRemove( void ) { + if ( m_hPlayer != NULL ) + m_hPlayer->LeaveVehicle(); m_BoneFollowerManager.DestroyBoneFollowers(); BaseClass::UpdateOnRemove(); } @@ -404,7 +406,7 @@ bool CPropCrane::CanExitVehicle( CBaseEntity *pEntity ) void CPropCrane::DrawDebugGeometryOverlays(void) { // Draw if BBOX is on - if ( m_debugOverlays & OVERLAY_BBOX_BIT ) + if ( m_hCraneMagnet && m_debugOverlays & OVERLAY_BBOX_BIT ) { Vector vecPoint = m_hCraneMagnet->GetAbsOrigin(); int iIndex = m_hCraneMagnet->LookupAttachment("magnetcable_a"); @@ -596,7 +598,7 @@ void CPropCrane::DriveCrane( int iDriverButtons, int iButtonsPressed, float flNP //Msg("Turn: %f\nExtensionRate: %f\n", m_flTurn, m_flExtensionRate ); //If we're holding down an attack button, update our state - if ( iButtonsPressed & (IN_ATTACK | IN_ATTACK2) ) + if ( m_hCraneMagnet && iButtonsPressed & (IN_ATTACK | IN_ATTACK2) ) { // If we have something on the magnet, turn the magnet off if ( m_hCraneMagnet->GetTotalMassAttachedObjects() ) @@ -674,7 +676,7 @@ void CPropCrane::RunCraneMovement( float flTime ) if ( m_bDropping ) { // Drop until the magnet hits something - if ( m_hCraneMagnet->HasHitSomething() ) + if ( m_hCraneMagnet && m_hCraneMagnet->HasHitSomething() ) { // We hit the ground, stop dropping m_hCraneTip->m_pSpring->SetSpringConstant( CRANE_SPRING_CONSTANT_INITIAL_RAISING ); @@ -726,7 +728,7 @@ void CPropCrane::RunCraneMovement( float flTime ) */ // Play creak sounds on the magnet if there's heavy weight on it - if ( (m_flNextCreakSound < gpGlobals->curtime) && (m_hCraneMagnet->GetTotalMassAttachedObjects() > 100) ) + if ( m_hCraneMagnet && (m_flNextCreakSound < gpGlobals->curtime) && (m_hCraneMagnet->GetTotalMassAttachedObjects() > 100) ) { // Randomly play creaks from the magnet, and increase the chance based on the turning speed float flSpeedPercentage = clamp( fabs(m_flTurn) / m_flMaxTurnSpeed, 0, 1 ); diff --git a/src/game/server/hl2/vehicle_jeep.cpp b/src/game/server/hl2/vehicle_jeep.cpp index 80eb13683af..3ee75cedf98 100644 --- a/src/game/server/hl2/vehicle_jeep.cpp +++ b/src/game/server/hl2/vehicle_jeep.cpp @@ -898,6 +898,8 @@ void CPropJeep::FireCannon( void ) if ( m_bUnableToFire ) return; + CDisablePredictionFiltering disabler; + m_flCannonTime = gpGlobals->curtime + 0.2f; m_bCannonCharging = false; @@ -936,6 +938,8 @@ void CPropJeep::FireCannon( void ) //----------------------------------------------------------------------------- void CPropJeep::FireChargedCannon( void ) { + CDisablePredictionFiltering disabler; + bool penetrated = false; m_bCannonCharging = false; diff --git a/src/game/server/hl2/vehicle_prisoner_pod.cpp b/src/game/server/hl2/vehicle_prisoner_pod.cpp index 1288e082c59..7f9a4f16e52 100644 --- a/src/game/server/hl2/vehicle_prisoner_pod.cpp +++ b/src/game/server/hl2/vehicle_prisoner_pod.cpp @@ -110,6 +110,7 @@ class CPropVehiclePrisonerPod : public CPhysicsProp, public IDrivableVehicle bool ShouldForceExit() { return m_bForcedExit; } void ClearForcedExit() { m_bForcedExit = false; } + virtual void UpdateOnRemove(void); // CBaseAnimating void HandleAnimEvent( animevent_t *pEvent ); @@ -654,6 +655,17 @@ void CPropVehiclePrisonerPod::InputExitVehicle( inputdata_t &inputdata ) m_bForcedExit = true; } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPropVehiclePrisonerPod::UpdateOnRemove(void) +{ + if ( m_hPlayer != NULL ) + m_hPlayer->LeaveVehicle(); + + BaseClass::UpdateOnRemove(); +} + //======================================================================================================================================== // CRANE VEHICLE SERVER VEHICLE diff --git a/src/game/server/physics_impact_damage.cpp b/src/game/server/physics_impact_damage.cpp index 164568e2368..12bb5d65085 100644 --- a/src/game/server/physics_impact_damage.cpp +++ b/src/game/server/physics_impact_damage.cpp @@ -335,15 +335,28 @@ float CalculatePhysicsImpactDamage( int index, gamevcollisionevent_t *pEvent, co if ( pEvent->pObjects[otherIndex]->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) { + // if the player is holding the object, use it's real mass (player holding reduced the mass) + CBasePlayer* pPlayer = NULL; if ( gpGlobals->maxClients == 1 ) { - // if the player is holding the object, use it's real mass (player holding reduced the mass) CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - if ( pPlayer ) + } + else { + for ( int i = 1; i <= gpGlobals->maxClients; i++ ) { - otherMass = pPlayer->GetHeldObjectMass( pEvent->pObjects[otherIndex] ); + CBasePlayer *tempPlayer = UTIL_PlayerByIndex( i ); + if ( tempPlayer && pEvent->pEntities[index] == tempPlayer->GetHeldObject() ) + { + pPlayer = tempPlayer; + break; + } } } + + if ( pPlayer ) + { + otherMass = pPlayer->GetHeldObjectMass( pEvent->pObjects[otherIndex] ); + } } // NOTE: sum the mass of each object in this system for the purpose of damage @@ -438,19 +451,31 @@ float CalculatePhysicsImpactDamage( int index, gamevcollisionevent_t *pEvent, co } else if ( pEvent->pObjects[index]->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) { + // if the player is holding the object, use it's real mass (player holding reduced the mass) + CBasePlayer *pPlayer = NULL; if ( gpGlobals->maxClients == 1 ) { - // if the player is holding the object, use it's real mass (player holding reduced the mass) CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - if ( pPlayer ) + } else { + for (int i = 1; i <= gpGlobals->maxClients; i++) { - float mass = pPlayer->GetHeldObjectMass( pEvent->pObjects[index] ); - if ( mass > 0 ) + CBasePlayer *tempPlayer = UTIL_PlayerByIndex( i ); + if ( tempPlayer && pEvent->pEntities[index] == tempPlayer->GetHeldObject() ) { - invMass = 1.0f / mass; + pPlayer = tempPlayer; + break; } } } + + if ( pPlayer ) + { + float mass = pPlayer->GetHeldObjectMass( pEvent->pObjects[index] ); + if ( mass > 0 ) + { + invMass = 1.0f / mass; + } + } } eliminatedEnergy *= invMass * energyScale; diff --git a/src/game/server/physics_prop_ragdoll.cpp b/src/game/server/physics_prop_ragdoll.cpp index 72635ea897d..6f36fb4436c 100644 --- a/src/game/server/physics_prop_ragdoll.cpp +++ b/src/game/server/physics_prop_ragdoll.cpp @@ -942,25 +942,28 @@ void CRagdollProp::Teleport( const Vector *newPosition, const QAngle *newAngles, // we need to call the base class and it will teleport our vphysics object, // so set object 0 up and compute the origin/angles for its new position (base implementation has side effects) - VPhysicsSwapObject( m_ragdoll.list[0].pObject ); - matrix3x4_t obj0source, obj0Target; - m_ragdoll.list[0].pObject->GetPositionMatrix( &obj0source ); - ConcatTransforms( xform, obj0source, obj0Target ); - Vector obj0Pos; - QAngle obj0Angles; - MatrixAngles( obj0Target, obj0Angles, obj0Pos ); - BaseClass::Teleport( &obj0Pos, &obj0Angles, newVelocity ); + if ( m_ragdoll.list[0].pObject ) + { + VPhysicsSwapObject( m_ragdoll.list[0].pObject ); + matrix3x4_t obj0source, obj0Target; + m_ragdoll.list[0].pObject->GetPositionMatrix( &obj0source ); + ConcatTransforms( xform, obj0source, obj0Target ); + Vector obj0Pos; + QAngle obj0Angles; + MatrixAngles( obj0Target, obj0Angles, obj0Pos ); + BaseClass::Teleport( &obj0Pos, &obj0Angles, newVelocity ); - for ( int i = 1; i < m_ragdoll.listCount; i++ ) - { - matrix3x4_t matrix, newMatrix; - m_ragdoll.list[i].pObject->GetPositionMatrix( &matrix ); - ConcatTransforms( xform, matrix, newMatrix ); - m_ragdoll.list[i].pObject->SetPositionMatrix( newMatrix, true ); - UpdateNetworkDataFromVPhysics( m_ragdoll.list[i].pObject, i ); + for ( int i = 1; i < m_ragdoll.listCount; i++ ) + { + matrix3x4_t matrix, newMatrix; + m_ragdoll.list[i].pObject->GetPositionMatrix( &matrix ); + ConcatTransforms( xform, matrix, newMatrix ); + m_ragdoll.list[i].pObject->SetPositionMatrix( newMatrix, true ); + UpdateNetworkDataFromVPhysics( m_ragdoll.list[i].pObject, i ); + } + // fixup/relink object 0 + UpdateNetworkDataFromVPhysics( m_ragdoll.list[0].pObject, 0 ); } - // fixup/relink object 0 - UpdateNetworkDataFromVPhysics( m_ragdoll.list[0].pObject, 0 ); } void CRagdollProp::VPhysicsUpdate( IPhysicsObject *pPhysics ) diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index b8a0519d245..881d2a472ae 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -199,7 +199,7 @@ ConVar player_debug_print_damage( "player_debug_print_damage", "0", FCVAR_CHEAT void CC_GiveCurrentAmmo( void ) { - CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); + CBasePlayer *pPlayer = UTIL_GetCommandClient(); if( pPlayer ) { @@ -747,22 +747,31 @@ int CBasePlayer::ShouldTransmit( const CCheckTransmitInfo *pInfo ) } -bool CBasePlayer::WantsLagCompensationOnEntity( const CBasePlayer *pPlayer, const CUserCmd *pCmd, const CBitVec *pEntityTransmitBits ) const +bool CBasePlayer::WantsLagCompensationOnEntity( const CBaseEntity *pEntity, const CUserCmd *pCmd, const CBitVec *pEntityTransmitBits ) const { - // Team members shouldn't be adjusted unless friendly fire is on. - if ( !friendlyfire.GetInt() && pPlayer->GetTeamNumber() == GetTeamNumber() ) - return false; + if ( gpGlobals->teamplay ) + { + // Team members shouldn't be adjusted unless friendly fire is on. + if ( !friendlyfire.GetInt() && pEntity->GetTeamNumber() == GetTeamNumber() ) + return false; + } // If this entity hasn't been transmitted to us and acked, then don't bother lag compensating it. - if ( pEntityTransmitBits && !pEntityTransmitBits->Get( pPlayer->entindex() ) ) + if ( pEntityTransmitBits && !pEntityTransmitBits->Get( pEntity->entindex() ) ) return false; const Vector &vMyOrigin = GetAbsOrigin(); - const Vector &vHisOrigin = pPlayer->GetAbsOrigin(); + const Vector &vHisOrigin = pEntity->GetAbsOrigin(); // get max distance player could have moved within max lag compensation time, // multiply by 1.5 to to avoid "dead zones" (sqrt(2) would be the exact value) - float maxDistance = 1.5 * pPlayer->MaxSpeed() * sv_maxunlag.GetFloat(); + float maxspeed; + CBasePlayer *pPlayer = ToBasePlayer((CBaseEntity*)pEntity); + if ( pPlayer ) + maxspeed = pPlayer->MaxSpeed(); + else + maxspeed = 600; + float maxDistance = 1.5 * maxspeed * sv_maxunlag.GetFloat(); // If the player is within this distance, lag compensate them in case they're running past us. if ( vHisOrigin.DistTo( vMyOrigin ) < maxDistance ) @@ -2639,6 +2648,12 @@ void CBasePlayer::JumptoPosition(const Vector &origin, const QAngle &angles) bool CBasePlayer::SetObserverTarget(CBaseEntity *target) { + if ( target == NULL ) + { + m_hObserverTarget.Set( NULL ); + return true; + } + if ( !IsValidObserverTarget( target ) ) return false; @@ -2679,42 +2694,42 @@ bool CBasePlayer::IsValidObserverTarget(CBaseEntity * target) // MOD AUTHORS: Add checks on target here or in derived method - if ( !target->IsPlayer() ) // only track players - return false; - - CBasePlayer * player = ToBasePlayer( target ); + if ( target->IsPlayer() ) + { + CBasePlayer * player = ToBasePlayer( target ); - /* Don't spec observers or players who haven't picked a class yet - if ( player->IsObserver() ) - return false; */ + /* Don't spec observers or players who haven't picked a class yet + if ( player->IsObserver() ) + return false; */ - if( player == this ) - return false; // We can't observe ourselves. + if( player == this ) + return false; // We can't observe ourselves. - if ( player->IsEffectActive( EF_NODRAW ) ) // don't watch invisible players - return false; + if ( player->IsEffectActive( EF_NODRAW ) ) // don't watch invisible players + return false; - if ( player->m_lifeState == LIFE_RESPAWNABLE ) // target is dead, waiting for respawn - return false; + if ( player->m_lifeState == LIFE_RESPAWNABLE ) // target is dead, waiting for respawn + return false; - if ( player->m_lifeState == LIFE_DEAD || player->m_lifeState == LIFE_DYING ) - { - if ( (player->m_flDeathTime + DEATH_ANIMATION_TIME ) < gpGlobals->curtime ) + if ( player->m_lifeState == LIFE_DEAD || player->m_lifeState == LIFE_DYING ) { - return false; // allow watching until 3 seconds after death to see death animation + if ( (player->m_flDeathTime + DEATH_ANIMATION_TIME ) < gpGlobals->curtime ) + { + return false; // allow watching until 3 seconds after death to see death animation + } } - } - // check forcecamera settings for active players - if ( GetTeamNumber() != TEAM_SPECTATOR ) - { - switch ( mp_forcecamera.GetInt() ) + // check forcecamera settings for active players + if ( GetTeamNumber() != TEAM_SPECTATOR ) { - case OBS_ALLOW_ALL : break; - case OBS_ALLOW_TEAM : if ( GetTeamNumber() != target->GetTeamNumber() ) - return false; - break; - case OBS_ALLOW_NONE : return false; + switch ( mp_forcecamera.GetInt() ) + { + case OBS_ALLOW_ALL : break; + case OBS_ALLOW_TEAM : if ( GetTeamNumber() != target->GetTeamNumber() ) + return false; + break; + case OBS_ALLOW_NONE : return false; + } } } @@ -2841,6 +2856,8 @@ bool CBasePlayer::CanPickupObject( CBaseEntity *pObject, float massLimit, float } if ( pList[i]->GetGameFlags() & FVPHYSICS_NO_PLAYER_PICKUP ) return false; + if ( pList[i]->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) + return false; if ( pList[i]->IsHinged() ) return false; } @@ -2890,6 +2907,11 @@ float CBasePlayer::GetHeldObjectMass( IPhysicsObject *pHeldObject ) return 0; } +CBaseEntity *CBasePlayer::GetHeldObject(void) +{ + return NULL; +} + //----------------------------------------------------------------------------- // Purpose: Server side of jumping rules. Most jumping logic is already @@ -5579,10 +5601,12 @@ bool CBasePlayer::GetInVehicle( IServerVehicle *pVehicle, int nRole ) m_Local.m_iHideHUD |= HIDEHUD_INVEHICLE; } +#ifndef JBMOD if ( !pVehicle->IsPassengerVisible( nRole ) ) { AddEffects( EF_NODRAW ); } +#endif // Put us in the vehicle pVehicle->SetPassenger( nRole, this ); @@ -5987,6 +6011,9 @@ CBaseEntity *FindPickerEntity( CBasePlayer *pPlayer ) { MDLCACHE_CRITICAL_SECTION(); + if ( pPlayer == NULL ) + return NULL; + // First try to trace a hull to an entity CBaseEntity *pEntity = FindEntityForward( pPlayer, true ); @@ -6486,6 +6513,8 @@ void CBasePlayer::CheatImpulseCommands( int iImpulse ) pEntity = FindEntityForward( this, true ); if ( pEntity ) { + if ( pEntity->IsPlayer() ) + break; UTIL_Remove( pEntity ); // if ( pEntity->m_takedamage ) // pEntity->SetThink(SUB_Remove); diff --git a/src/game/server/player.h b/src/game/server/player.h index 902e0e627ca..755bd2846f4 100644 --- a/src/game/server/player.h +++ b/src/game/server/player.h @@ -285,7 +285,7 @@ class CBasePlayer : public CBaseCombatCharacter // Returns true if this player wants pPlayer to be moved back in time when this player runs usercmds. // Saves a lot of overhead on the server if we can cull out entities that don't need to lag compensate // (like team members, entities out of our PVS, etc). - virtual bool WantsLagCompensationOnEntity( const CBasePlayer *pPlayer, const CUserCmd *pCmd, const CBitVec *pEntityTransmitBits ) const; + virtual bool WantsLagCompensationOnEntity( const CBaseEntity *pEntity, const CUserCmd *pCmd, const CBitVec *pEntityTransmitBits ) const; virtual void Spawn( void ); virtual void Activate( void ); @@ -568,6 +568,7 @@ class CBasePlayer : public CBaseCombatCharacter virtual void PickupObject( CBaseEntity *pObject, bool bLimitMassAndSize = true ) {} virtual void ForceDropOfCarriedPhysObjects( CBaseEntity *pOnlyIfHoldindThis = NULL ) {} virtual float GetHeldObjectMass( IPhysicsObject *pHeldObject ); + virtual CBaseEntity *GetHeldObject(void); void CheckSuitUpdate(); void SetSuitUpdate(const char *name, int fgroup, int iNoRepeat); diff --git a/src/game/server/props.cpp b/src/game/server/props.cpp index dec14e42d4c..253fc9f8bd2 100644 --- a/src/game/server/props.cpp +++ b/src/game/server/props.cpp @@ -5685,7 +5685,11 @@ class CPhysicsPropMultiplayer : public CPhysicsProp, public IMultiplayerPhysics CNetworkVector( m_collisionMaxs ); }; +#ifdef JBMOD +LINK_ENTITY_TO_CLASS( prop_physics_multiplayer, CPhysicsProp ); +#else LINK_ENTITY_TO_CLASS( prop_physics_multiplayer, CPhysicsPropMultiplayer ); +#endif BEGIN_DATADESC( CPhysicsPropMultiplayer ) DEFINE_KEYFIELD( m_iPhysicsMode, FIELD_INTEGER, "physicsmode" ), diff --git a/src/game/server/server_jbmod.vpc b/src/game/server/server_jbmod.vpc index 39aeeb4090f..96c1dea4d46 100644 --- a/src/game/server/server_jbmod.vpc +++ b/src/game/server/server_jbmod.vpc @@ -14,8 +14,8 @@ $Configuration { $Compiler { - $AdditionalIncludeDirectories "$BASE;$SRCDIR\game\shared\hl2,.\hl2,.\jbmod,$SRCDIR\game\shared\jbmod" - $PreprocessorDefinitions "$BASE;JBMOD;HL2MP;HL2_DLL;NEXT_BOT" + $AdditionalIncludeDirectories "$BASE;$SRCDIR\game\shared\hl2,.\hl2,.\jbmod,.\episodic,$SRCDIR\game\shared\jbmod,$SRCDIR\game\shared\episodic" + $PreprocessorDefinitions "$BASE;JBMOD;HL2MP;HL2_DLL;HL2_EPISODIC;NEXT_BOT" } } @@ -23,6 +23,8 @@ $Project "Server (JBMod)" { $Folder "Source Files" { + $File "ai_eventresponse.cpp" + $File "ai_eventresponse.h" $File "ai_relationship.cpp" $File "basegrenade_concussion.cpp" $File "basegrenade_contact.cpp" @@ -33,6 +35,7 @@ $Project "Server (JBMod)" $File "grenadethrown.h" $File "h_cycler.cpp" $File "h_cycler.h" + $File "logic_achievement.cpp" $File "monstermaker.cpp" $File "monstermaker.h" $File "physics_bone_follower.h" @@ -59,6 +62,8 @@ $Project "Server (JBMod)" $File "trigger_area_capture.h" $File "$SRCDIR\game\shared\teamplay_round_timer.cpp" $File "$SRCDIR\game\shared\teamplay_round_timer.h" + $File "vehicle_choreo_generic.cpp" + $File "$SRCDIR\game\shared\vehicle_choreo_generic_shared.h" $Folder "NextBot" { @@ -132,10 +137,20 @@ $Project "Server (JBMod)" $File "hl2\ai_allymanager.cpp" $File "hl2\ai_behavior_actbusy.cpp" $File "hl2\ai_behavior_actbusy.h" + $File "episodic\ai_behavior_alyx_injured.cpp" + $File "episodic\ai_behavior_alyx_injured.h" $File "hl2\ai_behavior_functank.cpp" $File "hl2\ai_behavior_functank.h" $File "hl2\ai_behavior_holster.cpp" $File "hl2\ai_behavior_holster.h" + $File "hl2\ai_behavior_operator.cpp" + $File "hl2\ai_behavior_operator.h" + $File "ai_behavior_passenger.cpp" + $File "ai_behavior_passenger.h" + $File "episodic\ai_behavior_passenger_companion.cpp" + $File "episodic\ai_behavior_passenger_companion.h" + $File "episodic\ai_behavior_passenger_zombie.cpp" + $File "episodic\ai_behavior_passenger_zombie.h" $File "hl2\ai_behavior_police.cpp" $File "hl2\ai_behavior_police.h" $File "hl2\ai_goal_police.cpp" @@ -180,10 +195,14 @@ $Project "Server (JBMod)" $File "hl2\grenade_bugbait.h" $File "hl2\grenade_frag.cpp" $File "hl2\grenade_frag.h" + $File "hl2\grenade_spit.cpp" + $File "hl2\grenade_spit.h" $File "hl2\hl2_ai_network.cpp" $File "hl2\hl2_eventlog.cpp" $File "$SRCDIR\game\shared\hl2\hl2_gamerules.cpp" $File "$SRCDIR\game\shared\hl2\hl2_gamerules.h" + $File "hl2\hl2_gamestats.cpp" + $File "hl2\hl2_gamestats.h" $File "hl2\hl2_player.cpp" $File "hl2\hl2_player.h" $File "$SRCDIR\game\shared\hl2\hl2_player_shared.h" @@ -196,6 +215,8 @@ $Project "Server (JBMod)" $File "$SRCDIR\game\shared\hl2\hl_gamemovement.h" $File "$SRCDIR\game\shared\hl2\hl_movedata.h" $File "hl2\hl_playermove.cpp" + $File "hl2\info_darknessmode_lightsource.cpp" + $File "hl2\info_darknessmode_lightsource.h" $File "hl2\info_teleporter_countdown.cpp" $File "hl2\item_ammo.cpp" $File "hl2\item_battery.cpp" @@ -206,11 +227,14 @@ $Project "Server (JBMod)" $File "hl2\item_suit.cpp" $File "hl2\look_door.cpp" $File "hl2\monster_dummy.cpp" - $File "hl2\npc_alyx.cpp" - $File "hl2\npc_alyx.h" + $File "$SRCDIR\game\shared\episodic\npc_advisor_shared.h" + $File "episodic\npc_advisor.cpp" + $File "hl2\npc_alyx_episodic.cpp" + $File "hl2\npc_alyx_episodic.h" $File "hl2\npc_antlion.cpp" $File "hl2\npc_antlion.h" $File "hl2\npc_antlionguard.cpp" + $File "hl2\npc_antliongrub.cpp" $File "hl2\npc_apcdriver.cpp" $File "hl2\npc_attackchopper.cpp" $File "hl2\npc_attackchopper.h" @@ -226,6 +250,7 @@ $Project "Server (JBMod)" $File "hl2\npc_bullseye.h" $File "hl2\npc_citizen17.cpp" $File "hl2\npc_citizen17.h" + $File "episodic\npc_combine_cannon.cpp" $File "hl2\npc_combine.cpp" $File "hl2\npc_combine.h" $File "hl2\npc_combinecamera.cpp" @@ -239,13 +264,17 @@ $Project "Server (JBMod)" $File "hl2\npc_dog.cpp" $File "hl2\npc_eli.cpp" $File "hl2\npc_enemyfinder.cpp" + $File "hl2\npc_fastzombie.cpp" $File "hl2\npc_fisherman.cpp" $File "hl2\npc_gman.cpp" $File "hl2\npc_headcrab.cpp" $File "hl2\npc_headcrab.h" + $File "episodic\npc_hunter.cpp" + $File "episodic\npc_hunter.h" $File "hl2\npc_ichthyosaur.cpp" $File "hl2\npc_kleiner.cpp" $File "hl2\npc_launcher.cpp" + $File "episodic\npc_magnusson.cpp" $File "hl2\npc_manhack.cpp" $File "hl2\npc_manhack.h" $File "hl2\npc_metropolice.cpp" @@ -270,9 +299,11 @@ $Project "Server (JBMod)" $File "hl2\npc_vortigaunt_episodic.cpp" $File "hl2\npc_vortigaunt_episodic.h" $File "hl2\npc_zombie.cpp" + $File "hl2\npc_zombine.cpp" $File "hl2\point_apc_controller.cpp" $File "hl2\prop_combine_ball.cpp" $File "hl2\prop_combine_ball.h" + $File "episodic\prop_scalable.cpp" $File "hl2\prop_thumper.cpp" $File "hl2\proto_sniper.cpp" $File "hl2\rotorwash.cpp" @@ -282,15 +313,30 @@ $Project "Server (JBMod)" $File "$SRCDIR\game\shared\script_intro_shared.cpp" $File "hl2\vehicle_airboat.cpp" $File "hl2\vehicle_apc.h" + $File "hl2\vehicle_cannon.cpp" $File "hl2\vehicle_crane.cpp" $File "hl2\vehicle_crane.h" + $File "hl2\vehicle_jeep.cpp" + $File "episodic\vehicle_jeep_episodic.cpp" + $File "episodic\vehicle_jeep_episodic.h" $File "hl2\vehicle_prisoner_pod.cpp" $File "hl2\vehicle_viewcontroller.cpp" + $File "hl2\weapon_alyxgun.cpp" $File "hl2\weapon_alyxgun.h" $File "hl2\weapon_annabelle.cpp" $File "hl2\weapon_bugbait.cpp" + $File "hl2\weapon_citizenpackage.cpp" + $File "hl2\weapon_citizenpackage.h" $File "hl2\weapon_crowbar.h" $File "weapon_cubemap.cpp" + $File "episodic\weapon_striderbuster.cpp" + $File "episodic\weapon_striderbuster.h" + $File "hl2\weapon_flaregun.cpp" + $File "hl2\weapon_flaregun.h" + $File "episodic\weapon_oldmanharpoon.cpp" + $File "hl2\func_bulletshield.cpp" + $File "hl2\func_bulletshield.h" + $File "episodic\npc_puppet.cpp" $Folder "unused" { @@ -303,8 +349,6 @@ $Project "Server (JBMod)" $File "hl2\npc_missiledefense.cpp" $File "hl2\vehicle_apc.cpp" $File "hl2\weapon_cguard.cpp" - $File "hl2\weapon_flaregun.cpp" - $File "hl2\weapon_flaregun.h" } } diff --git a/src/game/server/soundscape_system.cpp b/src/game/server/soundscape_system.cpp index 15793bfa8d2..376ba72405d 100644 --- a/src/game/server/soundscape_system.cpp +++ b/src/game/server/soundscape_system.cpp @@ -63,7 +63,7 @@ void CSoundscapeSystem::AddSoundscapeFile( const char *filename ) MEM_ALLOC_CREDIT(); // Open the soundscape data file, and abort if we can't KeyValues *pKeyValuesData = new KeyValues( filename ); - if ( filesystem->LoadKeyValues( *pKeyValuesData, IFileSystem::TYPE_SOUNDSCAPE, filename, "GAME" ) ) + if ( pKeyValuesData->LoadFromFile( filesystem, filename, "GAME" ) ) { // parse out all of the top level sections and save their names KeyValues *pKeys = pKeyValuesData; @@ -140,7 +140,7 @@ bool CSoundscapeSystem::Init() } KeyValues *manifest = new KeyValues( SOUNDSCAPE_MANIFEST_FILE ); - if ( filesystem->LoadKeyValues( *manifest, IFileSystem::TYPE_SOUNDSCAPE, SOUNDSCAPE_MANIFEST_FILE, "GAME" ) ) + if ( manifest->LoadFromFile( filesystem, SOUNDSCAPE_MANIFEST_FILE, "GAME" ) ) { for ( KeyValues *sub = manifest->GetFirstSubKey(); sub != NULL; sub = sub->GetNextKey() ) { diff --git a/src/game/server/vehicle_base.cpp b/src/game/server/vehicle_base.cpp index f916ba69153..7e2c27fc23a 100644 --- a/src/game/server/vehicle_base.cpp +++ b/src/game/server/vehicle_base.cpp @@ -1089,6 +1089,14 @@ void CPropVehicleDriveable::Event_KilledOther( CBaseEntity *pVictim, const CTake BaseClass::Event_KilledOther( pVictim, info ); } +void CPropVehicleDriveable::UpdateOnRemove(void) +{ + if ( m_hPlayer != NULL ) + m_hPlayer->LeaveVehicle(); + + BaseClass::UpdateOnRemove(); +} + //======================================================================================================================================== // FOUR WHEEL PHYSICS VEHICLE SERVER VEHICLE //======================================================================================================================================== diff --git a/src/game/server/vehicle_base.h b/src/game/server/vehicle_base.h index ab63005a7a0..2376990a299 100644 --- a/src/game/server/vehicle_base.h +++ b/src/game/server/vehicle_base.h @@ -208,6 +208,8 @@ class CPropVehicleDriveable : public CPropVehicle, public IDrivableVehicle, publ void StopEngine( void ); bool IsEngineOn( void ); + virtual void UpdateOnRemove( void ); + // IDrivableVehicle public: virtual CBaseEntity *GetDriver( void ); diff --git a/src/game/shared/activitylist.cpp b/src/game/shared/activitylist.cpp index edfcb66bb01..6c3bd5a4acb 100644 --- a/src/game/shared/activitylist.cpp +++ b/src/game/shared/activitylist.cpp @@ -1497,6 +1497,8 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RELOAD_SLAM ); REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_JUMP_SLAM ); + REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_SIT_IN_VEHICLE ); + // Portal REGISTER_SHARED_ACTIVITY ( ACT_VM_FIZZLE ); diff --git a/src/game/shared/ai_activity.h b/src/game/shared/ai_activity.h index 3702cb839e9..dff140af5e6 100644 --- a/src/game/shared/ai_activity.h +++ b/src/game/shared/ai_activity.h @@ -1325,6 +1325,8 @@ typedef enum ACT_HL2MP_GESTURE_RELOAD_SLAM, ACT_HL2MP_JUMP_SLAM, + ACT_HL2MP_SIT_IN_VEHICLE, + // Portal! ACT_VM_FIZZLE, diff --git a/src/game/shared/basecombatweapon_shared.cpp b/src/game/shared/basecombatweapon_shared.cpp index b843026a627..b9c95a0ee94 100644 --- a/src/game/shared/basecombatweapon_shared.cpp +++ b/src/game/shared/basecombatweapon_shared.cpp @@ -1030,7 +1030,8 @@ void CBaseCombatWeapon::SetActivity( Activity act, float duration ) { //Adrian: Oh man... #if !defined( CLIENT_DLL ) && (defined( HL2MP ) || defined( PORTAL )) - SetModel( GetWorldModel() ); + if ( GetOwner()->IsPlayer() ) + SetModel( GetWorldModel() ); #endif int sequence = SelectWeightedSequence( act ); @@ -1041,7 +1042,8 @@ void CBaseCombatWeapon::SetActivity( Activity act, float duration ) //Adrian: Oh man again... #if !defined( CLIENT_DLL ) && (defined( HL2MP ) || defined( PORTAL )) - SetModel( GetViewModel() ); + if ( GetOwner()->IsPlayer() ) + SetModel( GetViewModel() ); #endif if ( sequence != ACTIVITY_NOT_AVAILABLE ) diff --git a/src/game/shared/baseentity_shared.cpp b/src/game/shared/baseentity_shared.cpp index 0194f19303f..1b3018bfcda 100644 --- a/src/game/shared/baseentity_shared.cpp +++ b/src/game/shared/baseentity_shared.cpp @@ -2514,6 +2514,10 @@ void CBaseEntity::CollisionRulesChanged() } IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; int count = VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); + if ( count == NULL || pList == NULL ) + { + return; + } for ( int i = 0; i < count; i++ ) { if ( pList[i] != NULL ) //this really shouldn't happen, but it does >_< diff --git a/src/game/shared/baseplayer_shared.cpp b/src/game/shared/baseplayer_shared.cpp index abbd3196495..0e0aac558b7 100644 --- a/src/game/shared/baseplayer_shared.cpp +++ b/src/game/shared/baseplayer_shared.cpp @@ -679,6 +679,11 @@ void CBasePlayer::PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, flo if ( !psurface ) return; +#ifdef JBMOD + if ( GetFlags() & FL_DUCKING ) + return; +#endif + int nSide = m_Local.m_nStepside; unsigned short stepSoundName = nSide ? psurface->sounds.stepleft : psurface->sounds.stepright; if ( !stepSoundName ) @@ -1278,6 +1283,11 @@ void CBasePlayer::PlayerUse ( void ) if ( ! ((m_nButtons | m_afButtonPressed | m_afButtonReleased) & IN_USE) ) return; +#ifdef JBMOD + if ( m_nButtons & IN_ATTACK ) + return; +#endif + if ( IsObserver() ) { // do special use operation in oberserver mode diff --git a/src/game/shared/gamemovement.cpp b/src/game/shared/gamemovement.cpp index 4b79f72c531..a41c7481d1c 100644 --- a/src/game/shared/gamemovement.cpp +++ b/src/game/shared/gamemovement.cpp @@ -2185,10 +2185,21 @@ void CGameMovement::FullObserverMove( void ) float factor = sv_specspeed.GetFloat(); +#ifdef JBMOD + if ( mv->m_nButtons & IN_DUCK ) + { + factor /= sv_noclipsprint.GetFloat(); + } + if ( mv->m_nButtons & IN_SPEED ) + { + factor *= sv_noclipsprint.GetFloat(); + } +#else if ( mv->m_nButtons & IN_SPEED ) { factor /= 2.0f; } +#endif float fmove = mv->m_flForwardMove * factor; float smove = mv->m_flSideMove * factor; @@ -2261,10 +2272,22 @@ void CGameMovement::FullNoClipMove( float factor, float maxacceleration ) AngleVectors (mv->m_vecViewAngles, &forward, &right, &up); // Determine movement angles +#ifdef JBMOD + if ( mv->m_nButtons & IN_DUCK ) + { + factor /= sv_noclipsprint.GetFloat(); + } + if ( mv->m_nButtons & IN_SPEED ) + { + factor *= sv_noclipsprint.GetFloat(); + } + maxspeed = sv_maxspeed.GetFloat() * factor; +#else if ( mv->m_nButtons & IN_SPEED ) { factor /= 2.0f; } +#endif // Copy movement amounts float fmove = mv->m_flForwardMove * factor; diff --git a/src/game/shared/hl2/hl2_gamerules.cpp b/src/game/shared/hl2/hl2_gamerules.cpp index bdd5abec195..d87f0acbda5 100644 --- a/src/game/shared/hl2/hl2_gamerules.cpp +++ b/src/game/shared/hl2/hl2_gamerules.cpp @@ -1372,7 +1372,7 @@ ConVar alyx_darkness_force( "alyx_darkness_force", "0", FCVAR_CHEAT | FCVAR_REP flDamage = BaseClass::GetAmmoDamage( pAttacker, pVictim, nAmmoType ); } - if( pAttacker->IsPlayer() && pVictim->IsNPC() ) + if( pAttacker && pAttacker->IsPlayer() && pVictim->IsNPC() ) { if( pVictim->MyCombatCharacterPointer() ) { diff --git a/src/game/shared/jbmod/jbmod_achievements.cpp b/src/game/shared/jbmod/jbmod_achievements.cpp new file mode 100644 index 00000000000..62cd9a66820 --- /dev/null +++ b/src/game/shared/jbmod/jbmod_achievements.cpp @@ -0,0 +1,94 @@ +// Copyright 2025 The JBMod Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cbase.h" +#include "jbmod_achievements.h" + +#ifdef CLIENT_DLL +#include "achievementmgr.h" +#include "baseachievement.h" +#include "steam/steam_api.h" +#include "vcr_shared.h" + +CAchievementMgr g_AchievementMgrJB; + +class CBaseJBModAchievement : public CBaseAchievement +{ + DECLARE_CLASS( CBaseJBModAchievement, CBaseAchievement ); +public: +}; + +//----------------------------------------------------------------------------- +// JBMOD_PLAYED: Awarded for simply playing the game. +//----------------------------------------------------------------------------- +DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_JBMOD_PLAYED, "JBMOD_PLAYED", 10 ); + +//----------------------------------------------------------------------------- +// JBMOD_PLAYED_ATLAUNCH: Awarded for playing on launch day (on any year). +//----------------------------------------------------------------------------- +DECLARE_MAP_EVENT_ACHIEVEMENT_HIDDEN( ACHIEVEMENT_JBMOD_PLAYED_ATLAUNCH, "JBMOD_PLAYED_ATLAUNCH", 10 ); + +//----------------------------------------------------------------------------- +// JBMOD_PLAYED_90DAYS: Awarded for playing 90 days after install. +//----------------------------------------------------------------------------- +DECLARE_MAP_EVENT_ACHIEVEMENT_HIDDEN( ACHIEVEMENT_JBMOD_PLAYED_90DAYS, "JBMOD_PLAYED_90DAYS", 10 ); + +//----------------------------------------------------------------------------- +// Startup check logic +//----------------------------------------------------------------------------- +void CheckStartupAchievements() +{ +#ifndef NO_STEAM + if ( !g_AchievementMgrJB.HasAchieved( "JBMOD_PLAYED" ) ) + { + g_AchievementMgrJB.AwardAchievement( ACHIEVEMENT_JBMOD_PLAYED ); + } + + if ( steamapicontext && steamapicontext->SteamApps() && steamapicontext->SteamUtils() ) + { + uint32 installed = steamapicontext->SteamApps()->GetEarliestPurchaseUnixTime( steamapicontext->SteamUtils()->GetAppID() ); + if ( installed > 0 ) + { + if ( !g_AchievementMgrJB.HasAchieved( "JBMOD_PLAYED_ATLAUNCH" ) ) + { + if ( installed <= 1666568334 ) // installed before October 23, 2022 + { + g_AchievementMgrJB.AwardAchievement( ACHIEVEMENT_JBMOD_PLAYED_ATLAUNCH ); + } + else + { + tm today; + VCRHook_LocalTime( &today ); + if ( today.tm_mon == 9 && today.tm_mday == 22 ) // October 22 (month is 0-indexed) + { + g_AchievementMgrJB.AwardAchievement( ACHIEVEMENT_JBMOD_PLAYED_ATLAUNCH ); + } + } + } + + if ( !g_AchievementMgrJB.HasAchieved( "JBMOD_PLAYED_90DAYS" ) ) + { + long today; + VCRHook_Time( &today); + if ( (int)today - (int)installed >= 7776000 ) // 90 * 24 * 60 * 60 = 7776000 + { + g_AchievementMgrJB.AwardAchievement( ACHIEVEMENT_JBMOD_PLAYED_90DAYS ); + } + } + } + } +#endif // NO_STEAM +} + +#endif // CLIENT_DLL diff --git a/src/game/shared/jbmod/jbmod_achievements.h b/src/game/shared/jbmod/jbmod_achievements.h new file mode 100644 index 00000000000..2d40534dc2d --- /dev/null +++ b/src/game/shared/jbmod/jbmod_achievements.h @@ -0,0 +1,34 @@ +// Copyright 2025 The JBMod Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef JBMOD_ACHIEVEMENTS_H +#define JBMOD_ACHIEVEMENTS_H +#ifdef _WIN32 +#pragma once +#endif + +#include "achievementmgr.h" + +enum +{ + ACHIEVEMENT_JBMOD_PLAYED = 1001, + ACHIEVEMENT_JBMOD_PLAYED_ATLAUNCH, + ACHIEVEMENT_JBMOD_PLAYED_90DAYS, +}; + +extern CAchievementMgr g_AchievementMgrJB; + +void CheckStartupAchievements(); + +#endif // JBMOD_ACHIEVEMENTS_H diff --git a/src/game/shared/jbmod/jbmod_gamerules.cpp b/src/game/shared/jbmod/jbmod_gamerules.cpp index 81a188476c1..4927509761f 100644 --- a/src/game/shared/jbmod/jbmod_gamerules.cpp +++ b/src/game/shared/jbmod/jbmod_gamerules.cpp @@ -649,6 +649,9 @@ void CJBModRules::ClientDisconnected( edict_t *pClient ) { pPlayer->GetTeam()->RemovePlayer( pPlayer ); } + + if ( pPlayer->IsInAVehicle() ) + pPlayer->LeaveVehicle(); } BaseClass::ClientDisconnected( pClient ); @@ -814,6 +817,14 @@ void CJBModRules::ClientSettingsChanged( CBasePlayer *pPlayer ) UTIL_LogPrintf( "\"%s\" cl_cmdrate = \"%s\"\n", pHL2Player->GetPlayerName(), engine->GetClientConVarValue( pHL2Player->entindex(), "cl_cmdrate" )); } + const char *pszFov = engine->GetClientConVarValue( pHL2Player->entindex(), "fov_desired" ); + if ( pszFov ) + { + int iFov = atoi( pszFov ); + iFov = clamp( iFov, 75, 90 ); + pHL2Player->SetDefaultFOV( iFov ); + } + BaseClass::ClientSettingsChanged( pPlayer ); #endif diff --git a/src/game/shared/jbmod/weapon_jbmodbase.cpp b/src/game/shared/jbmod/weapon_jbmodbase.cpp index dc14cc73980..9ed384f28dc 100644 --- a/src/game/shared/jbmod/weapon_jbmodbase.cpp +++ b/src/game/shared/jbmod/weapon_jbmodbase.cpp @@ -119,7 +119,7 @@ void CWeaponJBModBase::WeaponSound( WeaponSound_t sound_type, float soundtime /* if ( !te->CanPredict() ) return; - CBaseEntity::EmitSound( filter, GetPlayerOwner()->entindex(), shootsound, &GetPlayerOwner()->GetAbsOrigin() ); + CBaseEntity::EmitSound( filter, GetJBModPlayerOwner()->entindex(), shootsound, &GetJBModPlayerOwner()->GetAbsOrigin() ); #else BaseClass::WeaponSound( sound_type, soundtime ); #endif diff --git a/src/game/shared/jbmod/weapon_jbmodbase.h b/src/game/shared/jbmod/weapon_jbmodbase.h index bfa88c2aa7a..7cd234e5137 100644 --- a/src/game/shared/jbmod/weapon_jbmodbase.h +++ b/src/game/shared/jbmod/weapon_jbmodbase.h @@ -13,6 +13,9 @@ #include "jbmod_player_shared.h" #include "basecombatweapon_shared.h" #include "jbmod_weapon_parse.h" +#ifndef CLIENT_DLL +#include "ai_basenpc.h" +#endif #if defined( CLIENT_DLL ) #define CWeaponJBModBase C_WeaponJBModBase @@ -80,6 +83,8 @@ class CWeaponJBModBase : public CBaseCombatWeapon Vector GetOriginalSpawnOrigin( void ) { return m_vOriginalSpawnOrigin; } QAngle GetOriginalSpawnAngles( void ) { return m_vOriginalSpawnAngles; } + void SetOriginalSpawnOrigin( const Vector& origin ) { m_vOriginalSpawnOrigin = origin; } + void SetOriginalSpawnAngles( const QAngle& angles ) { m_vOriginalSpawnAngles = angles; } private: diff --git a/src/game/shared/jbmod/weapon_jbmodbasebasebludgeon.cpp b/src/game/shared/jbmod/weapon_jbmodbasebasebludgeon.cpp index a7edc6f35fa..20ae588ce4c 100644 --- a/src/game/shared/jbmod/weapon_jbmodbasebasebludgeon.cpp +++ b/src/game/shared/jbmod/weapon_jbmodbasebasebludgeon.cpp @@ -69,6 +69,13 @@ void CBaseJBModBludgeonWeapon::Precache( void ) BaseClass::Precache(); } +#ifndef CLIENT_DLL +int CBaseJBModBludgeonWeapon::CapabilitiesGet() +{ + return bits_CAP_WEAPON_MELEE_ATTACK1; +} +#endif + //------------------------------------------------------------------------------ // Purpose : Update weapon //------------------------------------------------------------------------------ diff --git a/src/game/shared/jbmod/weapon_jbmodbasebasebludgeon.h b/src/game/shared/jbmod/weapon_jbmodbasebasebludgeon.h index ac2cd817ef3..4c60edd6adc 100644 --- a/src/game/shared/jbmod/weapon_jbmodbasebasebludgeon.h +++ b/src/game/shared/jbmod/weapon_jbmodbasebasebludgeon.h @@ -36,6 +36,9 @@ class CBaseJBModBludgeonWeapon : public CBaseJBModCombatWeapon virtual void Spawn( void ); virtual void Precache( void ); +#ifndef CLIENT_DLL + virtual int CapabilitiesGet(void); +#endif //Attack functions virtual void PrimaryAttack( void ); diff --git a/src/game/shared/jbmod/weapon_physcannon.cpp b/src/game/shared/jbmod/weapon_physcannon.cpp index c3058e6271e..455080c0b05 100644 --- a/src/game/shared/jbmod/weapon_physcannon.cpp +++ b/src/game/shared/jbmod/weapon_physcannon.cpp @@ -810,6 +810,9 @@ void CPlayerPickupController::Use( CBaseEntity *pActivator, CBaseEntity *pCaller // +ATTACK will throw phys objects if ( m_pPlayer->m_nButtons & IN_ATTACK ) { + if ( !pPhys ) + return; + Shutdown( true ); Vector vecLaunch; m_pPlayer->EyeVectors( &vecLaunch ); @@ -2452,6 +2455,8 @@ bool CWeaponPhysCannon::CanPickupObject( CBaseEntity *pTarget ) //----------------------------------------------------------------------------- void CWeaponPhysCannon::OpenElements( void ) { + CDisablePredictionFiltering disabler; + if ( m_bOpen ) return; @@ -2480,6 +2485,8 @@ void CWeaponPhysCannon::OpenElements( void ) //----------------------------------------------------------------------------- void CWeaponPhysCannon::CloseElements( void ) { + CDisablePredictionFiltering disabler; + if ( m_bOpen == false ) return; @@ -2531,6 +2538,8 @@ float CWeaponPhysCannon::GetLoadPercentage( void ) //----------------------------------------------------------------------------- CSoundPatch *CWeaponPhysCannon::GetMotorSound( void ) { + CDisablePredictionFiltering disabler; + #ifdef CLIENT_DLL if ( m_sndMotor == NULL ) { diff --git a/src/game/shared/jbmod/weapon_rpg.cpp b/src/game/shared/jbmod/weapon_rpg.cpp index cbaad2da009..a232179cc7d 100644 --- a/src/game/shared/jbmod/weapon_rpg.cpp +++ b/src/game/shared/jbmod/weapon_rpg.cpp @@ -671,6 +671,33 @@ CMissile *CMissile::Create( const Vector &vecOrigin, const QAngle &vecAngles, ed return pMissile; } +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +CUtlVector CMissile::gm_CustomDetonators; + +void CMissile::AddCustomDetonator( CBaseEntity* pEntity, float radius, float height ) +{ + int i = gm_CustomDetonators.AddToTail(); + gm_CustomDetonators[i].hEntity = pEntity; + gm_CustomDetonators[i].radiusSq = Square( radius ); + gm_CustomDetonators[i].halfHeight = height * 0.5f; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CMissile::RemoveCustomDetonator( CBaseEntity* pEntity ) +{ + for ( int i = 0; i < gm_CustomDetonators.Count(); i++ ) + { + if ( gm_CustomDetonators[i].hEntity == pEntity ) + { + gm_CustomDetonators.FastRemove( i ); + break; + } + } +} + //----------------------------------------------------------------------------- diff --git a/src/game/shared/jbmod/weapon_rpg.h b/src/game/shared/jbmod/weapon_rpg.h index bdd75d29ccb..a6983c6ffa2 100644 --- a/src/game/shared/jbmod/weapon_rpg.h +++ b/src/game/shared/jbmod/weapon_rpg.h @@ -70,6 +70,9 @@ class CMissile : public CBaseCombatCharacter static CMissile *Create( const Vector &vecOrigin, const QAngle &vecAngles, edict_t *pentOwner ); + static void AddCustomDetonator( CBaseEntity* pEntity, float radius, float height = -1 ); + static void RemoveCustomDetonator( CBaseEntity* pEntity ); + protected: virtual void DoExplosion(); virtual void ComputeActualDotPosition( CLaserDot *pLaserDot, Vector *pActualDotPosition, float *pHomingSpeed ); @@ -86,6 +89,15 @@ class CMissile : public CBaseCombatCharacter float m_flMarkDeadTime; float m_flDamage; + struct CustomDetonator_t + { + EHANDLE hEntity; + float radiusSq; + float halfHeight; + }; + + static CUtlVector gm_CustomDetonators; + private: float m_flGracePeriodEndsAt; diff --git a/src/game/shared/movevars_shared.cpp b/src/game/shared/movevars_shared.cpp index df89471f60e..6955f0273bf 100644 --- a/src/game/shared/movevars_shared.cpp +++ b/src/game/shared/movevars_shared.cpp @@ -43,6 +43,7 @@ ConVar sv_stopspeed ( "sv_stopspeed","100", FCVAR_NOTIFY | FCVAR_REPLICATED, "Mi #endif // DOD_DLL || CSTRIKE_DLL ConVar sv_noclipaccelerate( "sv_noclipaccelerate", "5", FCVAR_NOTIFY | FCVAR_ARCHIVE | FCVAR_REPLICATED); +ConVar sv_noclipsprint ( "sv_noclipsprint", "2", FCVAR_ARCHIVE | FCVAR_NOTIFY | FCVAR_REPLICATED); ConVar sv_noclipspeed ( "sv_noclipspeed", "5", FCVAR_ARCHIVE | FCVAR_NOTIFY | FCVAR_REPLICATED); ConVar sv_specaccelerate( "sv_specaccelerate", "5", FCVAR_NOTIFY | FCVAR_ARCHIVE | FCVAR_REPLICATED); ConVar sv_specspeed ( "sv_specspeed", "3", FCVAR_ARCHIVE | FCVAR_NOTIFY | FCVAR_REPLICATED); diff --git a/src/game/shared/movevars_shared.h b/src/game/shared/movevars_shared.h index 58412eb59b3..02c8ea49ccc 100644 --- a/src/game/shared/movevars_shared.h +++ b/src/game/shared/movevars_shared.h @@ -17,6 +17,7 @@ float GetCurrentGravity( void ); extern ConVar sv_gravity; extern ConVar sv_stopspeed; extern ConVar sv_noclipaccelerate; +extern ConVar sv_noclipsprint; extern ConVar sv_noclipspeed; extern ConVar sv_maxspeed; extern ConVar sv_accelerate; diff --git a/src/game/shared/physics_saverestore.cpp b/src/game/shared/physics_saverestore.cpp index 434be1f4207..84ec085220c 100644 --- a/src/game/shared/physics_saverestore.cpp +++ b/src/game/shared/physics_saverestore.cpp @@ -444,7 +444,7 @@ class CPhysSaveRestoreBlockHandler : public CDefSaveRestoreBlockHandler, // Don't doing the box thing for things like wheels on cars IPhysicsObject *pPhysObj = (IPhysicsObject *)(*ppPhysObj); - if ( pPhysObj ) + if ( pPhysObj && physcollision ) { item.header.modelName = GetModelName( pPhysObj ); item.header.iCollide = physcollision->CollideIndex( pPhysObj->GetCollide() ); diff --git a/src/game/shared/physics_shared.cpp b/src/game/shared/physics_shared.cpp index c6539bae773..0faacd7c1a3 100644 --- a/src/game/shared/physics_shared.cpp +++ b/src/game/shared/physics_shared.cpp @@ -1003,7 +1003,7 @@ void PhysFrictionSound( CBaseEntity *pEntity, IPhysicsObject *pObject, float ene if ( psurf->sounds.scrapeSmooth && phit->audio.roughnessFactor < psurf->audio.roughThreshold ) { soundName = psurf->sounds.scrapeSmooth; - soundHandle = &psurf->soundhandles.scrapeRough; + soundHandle = &psurf->soundhandles.scrapeSmooth; } const char *pSoundName = physprops->GetString( soundName ); diff --git a/src/game/shared/physics_shared.h b/src/game/shared/physics_shared.h index 0f1178ae430..871104a5fbd 100644 --- a/src/game/shared/physics_shared.h +++ b/src/game/shared/physics_shared.h @@ -100,6 +100,8 @@ void PhysFrictionEffect( Vector &vecPos, Vector vecVel, float energy, int surfac // ORs gameFlags with the physics object's current game flags inline unsigned short PhysSetGameFlags( IPhysicsObject *pPhys, unsigned short gameFlags ) { + if ( !pPhys ) return 0; + unsigned short flags = pPhys->GetGameFlags(); flags |= gameFlags; pPhys->SetGameFlags( flags ); @@ -109,6 +111,8 @@ inline unsigned short PhysSetGameFlags( IPhysicsObject *pPhys, unsigned short ga // mask off gameFlags inline unsigned short PhysClearGameFlags( IPhysicsObject *pPhys, unsigned short gameFlags ) { + if ( !pPhys ) return 0; + unsigned short flags = pPhys->GetGameFlags(); flags &= ~gameFlags; pPhys->SetGameFlags( flags ); diff --git a/src/game/shared/ragdoll_shared.cpp b/src/game/shared/ragdoll_shared.cpp index 51376d6f40c..617f3f9df1c 100644 --- a/src/game/shared/ragdoll_shared.cpp +++ b/src/game/shared/ragdoll_shared.cpp @@ -1017,9 +1017,12 @@ void CRagdollLRURetirement::Update( float frametime ) // Non-episodic version CBaseAnimating *pRagdoll = m_LRU[i].Get(); - //Just ignore it until we're done burning/dissolving. - if ( pRagdoll && pRagdoll->GetEffectEntity() ) - continue; + if (pRagdoll) + { + //Just ignore it until we're done burning/dissolving. + if ( pRagdoll && pRagdoll->GetEffectEntity() ) + continue; + } #ifdef CLIENT_DLL m_LRU[ i ]->SUB_Remove(); diff --git a/src/game/shared/util_shared.cpp b/src/game/shared/util_shared.cpp index c3cca293f82..fbc02078bbe 100644 --- a/src/game/shared/util_shared.cpp +++ b/src/game/shared/util_shared.cpp @@ -778,6 +778,8 @@ void UTIL_Tracer( const Vector &vecStart, const Vector &vecEnd, int iEntIndex, void UTIL_BloodDrips( const Vector &origin, const Vector &direction, int color, int amount ) { + IPredictionSystem::SuppressHostEvents( NULL ); + if ( !UTIL_ShouldShowBlood( color ) ) return; diff --git a/src/game/shared/vscript_shared.cpp b/src/game/shared/vscript_shared.cpp index 64088e10919..d1e13884638 100644 --- a/src/game/shared/vscript_shared.cpp +++ b/src/game/shared/vscript_shared.cpp @@ -1,4 +1,4 @@ -//========== Copyright © 2008, Valve Corporation, All rights reserved. ======== +//========== Copyright � 2008, Valve Corporation, All rights reserved. ======== // // Purpose: // @@ -185,8 +185,10 @@ CON_COMMAND( script, "Run the text as a script" ) #endif { #ifdef CLIENT_DLL +#ifndef JBMOD if ( !engine->IsClientLocalToActiveServer() ) return; +#endif #else if ( !UTIL_IsCommandIssuedByServerAdmin() ) return; @@ -253,8 +255,10 @@ CON_COMMAND( script_execute, "Run a vscript file" ) #endif { #ifdef CLIENT_DLL +#ifndef JBMOD if ( !engine->IsClientLocalToActiveServer() ) return; +#endif #else if ( !UTIL_IsCommandIssuedByServerAdmin() ) return; @@ -282,8 +286,10 @@ CON_COMMAND( script_debug, "Connect the vscript VM to the script debugger" ) #endif { #ifdef CLIENT_DLL +#ifndef JBMOD if ( !engine->IsClientLocalToActiveServer() ) return; +#endif #else if ( !UTIL_IsCommandIssuedByServerAdmin() ) return; @@ -304,8 +310,10 @@ CON_COMMAND( script_help, "Output help for script functions, optionally with a s #endif { #ifdef CLIENT_DLL +#ifndef JBMOD if ( !engine->IsClientLocalToActiveServer() ) return; +#endif #else if ( !UTIL_IsCommandIssuedByServerAdmin() ) return; @@ -332,8 +340,10 @@ CON_COMMAND( script_dump_all, "Dump the state of the VM to the console" ) #endif { #ifdef CLIENT_DLL +#ifndef JBMOD if ( !engine->IsClientLocalToActiveServer() ) return; +#endif #else if ( !UTIL_IsCommandIssuedByServerAdmin() ) return; diff --git a/src/public/bone_setup.cpp b/src/public/bone_setup.cpp index dac6699f71a..3953310b315 100644 --- a/src/public/bone_setup.cpp +++ b/src/public/bone_setup.cpp @@ -5926,6 +5926,8 @@ const char *Studio_GetDefaultSurfaceProps( CStudioHdr *pstudiohdr ) float Studio_GetMass( CStudioHdr *pstudiohdr ) { + if ( pstudiohdr == NULL ) + return 0.f; return pstudiohdr->mass(); } diff --git a/src/tier1/NetAdr.cpp b/src/tier1/NetAdr.cpp index 00514d6e679..e7214e598de 100644 --- a/src/tier1/NetAdr.cpp +++ b/src/tier1/NetAdr.cpp @@ -97,7 +97,7 @@ bool netadr_t::IsReservedAdr () const if ( (ip[0] == 10) || // 10.x.x.x is reserved (ip[0] == 127) || // 127.x.x.x (ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31) || // 172.16.x.x - 172.31.x.x - (ip[0] == 192 && ip[1] >= 168) ) // 192.168.x.x + (ip[0] == 192 && ip[1] == 168) ) // 192.168.x.x return true; } return false; diff --git a/src/tier1/convar.cpp b/src/tier1/convar.cpp index 9aa66bbfe2c..b55f6d59cb1 100644 --- a/src/tier1/convar.cpp +++ b/src/tier1/convar.cpp @@ -360,7 +360,7 @@ CCommand::CCommand( int nArgC, const char **ppArgV ) { *pSBuf++ = '\"'; } - memcpy( pSBuf, ppArgV[i], nLen ); + memcpy( pSBuf, ppArgV[i], nLen + 1 ); pSBuf += nLen; if ( bContainsSpace ) { diff --git a/src/utils/common/threads.cpp b/src/utils/common/threads.cpp index 74e457a9ce9..88a1318bcf1 100644 --- a/src/utils/common/threads.cpp +++ b/src/utils/common/threads.cpp @@ -19,7 +19,7 @@ #include "threads.h" #include "pacifier.h" -#define MAX_THREADS 16 +#define MAX_THREADS 32 class CRunThreadsData diff --git a/src/utils/common/threads.h b/src/utils/common/threads.h index 0908b67ad00..906d0b7ba8c 100644 --- a/src/utils/common/threads.h +++ b/src/utils/common/threads.h @@ -18,7 +18,7 @@ // Arrays that are indexed by thread should always be MAX_TOOL_THREADS+1 // large so THREADINDEX_MAIN can be used from the main thread. -#define MAX_TOOL_THREADS 16 +#define MAX_TOOL_THREADS 32 #define THREADINDEX_MAIN (MAX_TOOL_THREADS) diff --git a/src/utils/common/utilmatlib.cpp b/src/utils/common/utilmatlib.cpp index f2dc49fa838..f4e3920be37 100644 --- a/src/utils/common/utilmatlib.cpp +++ b/src/utils/common/utilmatlib.cpp @@ -52,6 +52,8 @@ void LoadMaterialSystemInterface( CreateInterfaceFn fileSystemFactory ) { Error( "Could not start the empty shader (shaderapiempty.dll)!" ); } + + g_pMaterialSystem->ModInit(); } void InitMaterialSystem( const char *materialBaseDirPath, CreateInterfaceFn fileSystemFactory ) diff --git a/src/utils/vbsp/detail.cpp b/src/utils/vbsp/detail.cpp index 840068def67..913c99c0758 100644 --- a/src/utils/vbsp/detail.cpp +++ b/src/utils/vbsp/detail.cpp @@ -440,6 +440,7 @@ face_t *MakeBrushFace( side_t *originalSide, winding_t *winding ) f->split[0] = f->split[1] = NULL; f->w = CopyWinding( winding ); f->originalface = originalSide; + f->smoothingGroups = originalSide->smoothingGroups; // // save material info // From 1581e9939ad98cd518938c141f04a56dd1806d4e Mon Sep 17 00:00:00 2001 From: ray <1041137+ray@users.noreply.github.com> Date: Sun, 29 Mar 2026 00:21:10 -0400 Subject: [PATCH 2/4] survival_gamerules fails to build on Linux + reverted an unnecessary change (was already fixed since 2013, skimmed over it) Signed-off-by: ray <1041137+ray@users.noreply.github.com> --- src/game/shared/hl2/survival_gamerules.cpp | 2 +- src/game/shared/ragdoll_shared.cpp | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/game/shared/hl2/survival_gamerules.cpp b/src/game/shared/hl2/survival_gamerules.cpp index a216fabf227..2bc23cef563 100644 --- a/src/game/shared/hl2/survival_gamerules.cpp +++ b/src/game/shared/hl2/survival_gamerules.cpp @@ -207,7 +207,7 @@ void CHalfLife2Survival::ParseSurvivalSettings( KeyValues *pSubKey ) } else if ( !stricmp( pTestKey->GetName(), "spawnhealth" ) ) { - m_SurvivalSettings.m_iSpawnHealth = pTestKey->GetInt( NULL, 100 ); + m_SurvivalSettings.m_iSpawnHealth = pTestKey->GetInt( nullptr, 100 ); } else if ( !stricmp( pTestKey->GetName(), "allowedpickups" ) ) { diff --git a/src/game/shared/ragdoll_shared.cpp b/src/game/shared/ragdoll_shared.cpp index 617f3f9df1c..51376d6f40c 100644 --- a/src/game/shared/ragdoll_shared.cpp +++ b/src/game/shared/ragdoll_shared.cpp @@ -1017,12 +1017,9 @@ void CRagdollLRURetirement::Update( float frametime ) // Non-episodic version CBaseAnimating *pRagdoll = m_LRU[i].Get(); - if (pRagdoll) - { - //Just ignore it until we're done burning/dissolving. - if ( pRagdoll && pRagdoll->GetEffectEntity() ) - continue; - } + //Just ignore it until we're done burning/dissolving. + if ( pRagdoll && pRagdoll->GetEffectEntity() ) + continue; #ifdef CLIENT_DLL m_LRU[ i ]->SUB_Remove(); From d36d1f6b61d9986b65448e2f4071457171072743 Mon Sep 17 00:00:00 2001 From: ray <1041137+ray@users.noreply.github.com> Date: Sun, 29 Mar 2026 00:32:43 -0400 Subject: [PATCH 3/4] npc_playercompanion also fails to build on linux Signed-off-by: ray <1041137+ray@users.noreply.github.com> --- src/game/server/hl2/npc_playercompanion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/server/hl2/npc_playercompanion.cpp b/src/game/server/hl2/npc_playercompanion.cpp index a03a752f182..980274aff41 100644 --- a/src/game/server/hl2/npc_playercompanion.cpp +++ b/src/game/server/hl2/npc_playercompanion.cpp @@ -3538,7 +3538,7 @@ void CNPC_PlayerCompanion::InputClearAllOuputs( inputdata_t &inputdata ) typedescription_t *dataDesc = &dmap->dataDesc[i]; if ( ( dataDesc->fieldType == FIELD_CUSTOM ) && ( dataDesc->flags & FTYPEDESC_OUTPUT ) ) { - CBaseEntityOutput *pOutput = (CBaseEntityOutput *)((int)this + (int)dataDesc->fieldOffset[0]); + CBaseEntityOutput *pOutput = (CBaseEntityOutput *)((char *)this + dataDesc->fieldOffset[0]); pOutput->DeleteAllElements(); /* int nConnections = pOutput->NumberOfElements(); From 3f2b00017ad4ec2eaae63df3eaba9182aadde390 Mon Sep 17 00:00:00 2001 From: ray <1041137+ray@users.noreply.github.com> Date: Sun, 29 Mar 2026 00:48:22 -0400 Subject: [PATCH 4/4] Pull autoexec out of vpk Signed-off-by: ray <1041137+ray@users.noreply.github.com> --- .github/workflows/pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 02999812a65..258258e35e7 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -186,7 +186,7 @@ jobs: run: | cp -r valve/game/jbmod game/jbmod_base cp -r game/jbmod/* game/jbmod_base/ - vpk-ctrl -b game/jbmod_base game/jbmod_base/*.cfg game/jbmod_base/*.txt !game/jbmod_base/gameinfo.txt !game/jbmod_base/steam.inf game/jbmod_base/cfg !game/jbmod_base/cfg/*_example.txt !game/jbmod_base/cfg/settings.scr game/jbmod_base/maps !game/jbmod_base/maps/*.bsp game/jbmod_base/materials game/jbmod_base/media game/jbmod_base/models game/jbmod_base/resource !game/jbmod_base/resource/*.ico !game/jbmod_base/resource/*.ttf game/jbmod_base/scripts game/jbmod_base/servers game/jbmod_base/sound > pak01.vdf + vpk-ctrl -b game/jbmod_base game/jbmod_base/*.cfg game/jbmod_base/*.txt !game/jbmod_base/gameinfo.txt !game/jbmod_base/steam.inf game/jbmod_base/cfg !game/jbmod_base/cfg/autoexec.cfg !game/jbmod_base/cfg/*_example.txt !game/jbmod_base/cfg/settings.scr game/jbmod_base/maps !game/jbmod_base/maps/*.bsp game/jbmod_base/materials game/jbmod_base/media game/jbmod_base/models game/jbmod_base/resource !game/jbmod_base/resource/*.ico !game/jbmod_base/resource/*.ttf game/jbmod_base/scripts game/jbmod_base/servers game/jbmod_base/sound > pak01.vdf vpk -M -P -K privatekey.vdf -k publickey.vdf k game/jbmod_base/jbmod_pak pak01.vdf cp pak01.vdf pak01.vdf.bak vpk-cleaner -c pak01.vdf game/jbmod_base game/jbmod_clean