From e1518d15887325abfd1bc4ffae5e0fb92c7ea02d Mon Sep 17 00:00:00 2001 From: nuv3x Date: Tue, 8 Jul 2025 16:19:15 +0400 Subject: [PATCH 1/2] Physgun --- src/game/client/c_baseplayer.cpp | 14 +- src/game/client/c_baseplayer.h | 2 + src/game/client/client_openmod.vpc | 3 +- src/game/client/clientmode_shared.cpp | 10 + src/game/client/clientmode_shared.h | 1 + src/game/client/hl2mp/c_hl2mp_player.cpp | 1 + src/game/client/hud.cpp | 10 + src/game/client/hud.h | 1 + src/game/client/iclientmode.h | 1 + src/game/client/in_mouse.cpp | 11 +- src/game/server/player.cpp | 3 + src/game/server/player.h | 2 + src/game/server/server_openmod.vpc | 2 + src/game/shared/basecombatweapon_shared.h | 1 + src/game/shared/openmod/weapon_physgun.cpp | 1464 ++++++++++++++++++++ 15 files changed, 1522 insertions(+), 4 deletions(-) create mode 100644 src/game/shared/openmod/weapon_physgun.cpp diff --git a/src/game/client/c_baseplayer.cpp b/src/game/client/c_baseplayer.cpp index b5ce6728b..7409e1db3 100644 --- a/src/game/client/c_baseplayer.cpp +++ b/src/game/client/c_baseplayer.cpp @@ -244,7 +244,7 @@ END_RECV_TABLE() RecvPropFloat ( RECVINFO(m_vecVelocity[2]), 0, RecvProxy_LocalVelocityZ ), RecvPropVector ( RECVINFO( m_vecBaseVelocity ) ), - + RecvPropVector(RECVINFO(m_vecUseAngles)), RecvPropEHandle ( RECVINFO( m_hConstraintEntity)), RecvPropVector ( RECVINFO( m_vecConstraintCenter) ), RecvPropFloat ( RECVINFO( m_flConstraintRadius )), @@ -295,6 +295,7 @@ END_RECV_TABLE() RecvPropFloat (RECVINFO(m_flMaxspeed)), RecvPropInt (RECVINFO(m_fFlags)), + RecvPropVector(RECVINFO(m_vecUseAngles)), RecvPropInt (RECVINFO(m_iObserverMode), 0, RecvProxy_ObserverMode ), @@ -1418,6 +1419,17 @@ void C_BasePlayer::CreateWaterEffects( void ) //----------------------------------------------------------------------------- void C_BasePlayer::OverrideView( CViewSetup *pSetup ) { + C_BaseCombatWeapon* pWeapon = GetActiveWeapon(); + if (pWeapon) + { + // adnan + if (pWeapon->OverrideViewAngles()) { + // use the useAngles! + // override with the angles the server sends to us as useAngles + // use the useAngles only if we're holding and rotating with the grav gun + pSetup->angles = m_vecUseAngles; + } + } } bool C_BasePlayer::ShouldInterpolate() diff --git a/src/game/client/c_baseplayer.h b/src/game/client/c_baseplayer.h index 11a7fabca..0eab06daa 100644 --- a/src/game/client/c_baseplayer.h +++ b/src/game/client/c_baseplayer.h @@ -440,6 +440,8 @@ class C_BasePlayer : public C_BaseCombatCharacter, public CGameEventListener CUserCmd *m_pCurrentCommand; + QAngle m_vecUseAngles; + // Movement constraints EHANDLE m_hConstraintEntity; Vector m_vecConstraintCenter; diff --git a/src/game/client/client_openmod.vpc b/src/game/client/client_openmod.vpc index 357eeab7b..eefa22147 100644 --- a/src/game/client/client_openmod.vpc +++ b/src/game/client/client_openmod.vpc @@ -14,7 +14,7 @@ $Configuration $Compiler { $AdditionalIncludeDirectories "$BASE;hl2mp\ui,.\hl2mp,$SRCDIR\game\shared\hl2mp,.\hl2,.\hl2\elements,$SRCDIR\game\shared\hl2,.\openmod,$SRCDIR\game\shared\openmod" - $PreprocessorDefinitions "$BASE;HL2MP;HL2_CLIENT_DLL;NEXT_BOT;OPENMOD" + $PreprocessorDefinitions "$BASE;HL2MP;HL2_CLIENT_DLL;NEXT_BOT;OPENMOD;OMOD" } } @@ -42,6 +42,7 @@ $Project "Client (OpenMod)" $Folder "OpenMod" { + $File "..\shared\openmod\weapon_physgun.cpp" $Folder "Lua" { $File "$SRCDIR\game\shared\openmod\lua\luamanager.cpp" diff --git a/src/game/client/clientmode_shared.cpp b/src/game/client/clientmode_shared.cpp index 54933d249..ca569a037 100644 --- a/src/game/client/clientmode_shared.cpp +++ b/src/game/client/clientmode_shared.cpp @@ -519,6 +519,16 @@ void ClientModeShared::OverrideMouseInput( float *x, float *y ) } } +bool ClientModeShared::OverrideViewAngles(void) +{ + C_BaseCombatWeapon* pWeapon = GetActiveWeapon(); + if (pWeapon) + { + return pWeapon->OverrideViewAngles(); + } + return false; +} + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- diff --git a/src/game/client/clientmode_shared.h b/src/game/client/clientmode_shared.h index 4d82c719c..76a0e7ad5 100644 --- a/src/game/client/clientmode_shared.h +++ b/src/game/client/clientmode_shared.h @@ -86,6 +86,7 @@ class ClientModeShared : public IClientMode, public CGameEventListener // Input virtual int KeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ); + virtual bool OverrideViewAngles(void); virtual int HudElementKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ); virtual void OverrideMouseInput( float *x, float *y ); virtual void StartMessageMode( int iMessageModeType ); diff --git a/src/game/client/hl2mp/c_hl2mp_player.cpp b/src/game/client/hl2mp/c_hl2mp_player.cpp index 367a61632..f96936c44 100644 --- a/src/game/client/hl2mp/c_hl2mp_player.cpp +++ b/src/game/client/hl2mp/c_hl2mp_player.cpp @@ -14,6 +14,7 @@ #include "iviewrender_beams.h" // flashlight beam #include "r_efx.h" #include "dlight.h" +#include "iclientmode.h" // Don't alias here #if defined( CHL2MP_Player ) diff --git a/src/game/client/hud.cpp b/src/game/client/hud.cpp index e00129fbe..6858397d9 100644 --- a/src/game/client/hud.cpp +++ b/src/game/client/hud.cpp @@ -387,6 +387,8 @@ CHud::CHud() SetDefLessFunc( m_RenderGroups ); m_flScreenShotTime = -1; + + m_bSkipClear = false; } //----------------------------------------------------------------------------- @@ -1178,8 +1180,16 @@ bool CHud::DoesRenderGroupExist( int iGroupIndex ) //----------------------------------------------------------------------------- void CHud::UpdateHud( bool bActive ) { +#ifndef OPENMOD // clear the weapon bits. gHUD.m_iKeyBits &= (~(IN_WEAPON1|IN_WEAPON2)); +#else + if (!gHUD.m_bSkipClear) + { + // clear the weapon bits. + gHUD.m_iKeyBits &= (~(IN_WEAPON1 | IN_WEAPON2)); + } +#endif g_pClientMode->Update(); diff --git a/src/game/client/hud.h b/src/game/client/hud.h index 3005f67a7..bbb8f11e4 100644 --- a/src/game/client/hud.h +++ b/src/game/client/hud.h @@ -173,6 +173,7 @@ class CHud public: int m_iKeyBits; + bool m_bSkipClear; #ifndef _XBOX float m_flMouseSensitivity; float m_flMouseSensitivityFactor; diff --git a/src/game/client/iclientmode.h b/src/game/client/iclientmode.h index a313d8ffd..43f5d05c7 100644 --- a/src/game/client/iclientmode.h +++ b/src/game/client/iclientmode.h @@ -86,6 +86,7 @@ abstract_class IClientMode virtual int KeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ) = 0; virtual void StartMessageMode( int iMessageModeType ) = 0; virtual vgui::Panel *GetMessagePanel() = 0; + virtual bool OverrideViewAngles(void) = 0; virtual void OverrideMouseInput( float *x, float *y ) = 0; virtual bool CreateMove( float flInputSampleTime, CUserCmd *cmd ) = 0; diff --git a/src/game/client/in_mouse.cpp b/src/game/client/in_mouse.cpp index 8d503c260..6cdac16d5 100644 --- a/src/game/client/in_mouse.cpp +++ b/src/game/client/in_mouse.cpp @@ -740,8 +740,15 @@ void CInput::MouseMove( CUserCmd *cmd ) ResetMouse(); } - // Store out the new viewangles. - engine->SetViewAngles( viewangles ); + // adnan + // only set the new viewangles if we're not supposed to override them + if (!(g_pClientMode->OverrideViewAngles())) + { + + // Store out the new viewangles. + engine->SetViewAngles(viewangles); + } + // end adnan } //----------------------------------------------------------------------------- diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index b8a0519d2..80ba477fd 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -425,6 +425,7 @@ BEGIN_DATADESC( CBasePlayer ) DEFINE_FIELD( m_flOldPlayerViewOffsetZ, FIELD_FLOAT ), DEFINE_FIELD( m_bPlayerUnderwater, FIELD_BOOLEAN ), DEFINE_FIELD( m_hViewEntity, FIELD_EHANDLE ), + DEFINE_FIELD(m_vecUseAngles, FIELD_VECTOR), DEFINE_FIELD( m_hConstraintEntity, FIELD_EHANDLE ), DEFINE_FIELD( m_vecConstraintCenter, FIELD_VECTOR ), @@ -8143,6 +8144,8 @@ void CMovementSpeedMod::InputSpeedMod(inputdata_t &data) SendPropVector ( SENDINFO( m_vecBaseVelocity ), 32, SPROP_NOSCALE ), + SendPropVector(SENDINFO(m_vecUseAngles), 0, SPROP_NOSCALE), + SendPropEHandle ( SENDINFO( m_hConstraintEntity)), SendPropVector ( SENDINFO( m_vecConstraintCenter), 0, SPROP_NOSCALE ), SendPropFloat ( SENDINFO( m_flConstraintRadius ), 0, SPROP_NOSCALE ), diff --git a/src/game/server/player.h b/src/game/server/player.h index 902e0e627..937bc9602 100644 --- a/src/game/server/player.h +++ b/src/game/server/player.h @@ -1150,6 +1150,8 @@ class CBasePlayer : public CBaseCombatCharacter EHANDLE m_hViewEntity; + CNetworkQAngle(m_vecUseAngles); + // Movement constraints CNetworkHandle( CBaseEntity, m_hConstraintEntity ); CNetworkVector( m_vecConstraintCenter ); diff --git a/src/game/server/server_openmod.vpc b/src/game/server/server_openmod.vpc index 262418c49..6e0b8bbc9 100644 --- a/src/game/server/server_openmod.vpc +++ b/src/game/server/server_openmod.vpc @@ -129,6 +129,8 @@ $Project "Server (OpenMod)" $Folder "OpenMod" { + + $File "..\shared\openmod\weapon_physgun.cpp" $Folder "Lua" { $File "$SRCDIR\game\shared\openmod\lua\luamanager.cpp" diff --git a/src/game/shared/basecombatweapon_shared.h b/src/game/shared/basecombatweapon_shared.h index 4ca7cd03d..693d1264a 100644 --- a/src/game/shared/basecombatweapon_shared.h +++ b/src/game/shared/basecombatweapon_shared.h @@ -497,6 +497,7 @@ class CBaseCombatWeapon : public BASECOMBATWEAPON_DERIVED_FROM virtual bool ShouldDraw( void ); virtual bool ShouldDrawPickup( void ); virtual void HandleInput( void ) { return; }; + virtual bool OverrideViewAngles(void) { return false; };s virtual void OverrideMouseInput( float *x, float *y ) { return; }; virtual int KeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ) { return 1; } virtual bool AddLookShift( void ) { return true; }; diff --git a/src/game/shared/openmod/weapon_physgun.cpp b/src/game/shared/openmod/weapon_physgun.cpp new file mode 100644 index 000000000..1e4f724f1 --- /dev/null +++ b/src/game/shared/openmod/weapon_physgun.cpp @@ -0,0 +1,1464 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" +#include "beam_shared.h" +#ifndef CLIENT_DLL +#include "player.h" +#endif +#include "gamerules.h" +#ifdef CLIENT_DLL +#include "ClientEffectPrecacheSystem.h" +#endif +#include "weapon_hl2mpbasehlmpcombatweapon.h" +#ifndef CLIENT_DLL +#include "baseviewmodel.h" +#endif +#include "vphysics/constraints.h" +#include "physics.h" +#include "in_buttons.h" +#include "IEffects.h" +#include "soundenvelope.h" +#include "engine/IEngineSound.h" +#ifndef CLIENT_DLL +#include "ndebugoverlay.h" +#endif +#include "physics_saverestore.h" +#ifndef CLIENT_DLL +#include "player_pickup.h" +#endif +#include "soundemittersystem/isoundemittersystembase.h" +#ifdef CLIENT_DLL +#include "model_types.h" +#include "view_shared.h" +#include "view.h" +#include "iviewrender.h" +#include "ragdoll.h" +#else +#include "physics_prop_ragdoll.h" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static int g_physgunBeam1; +static int g_physgunBeam; +static int g_physgunGlow; +#define PHYSGUN_BEAM_SPRITE1 "sprites/physbeam1.vmt" +#define PHYSGUN_BEAM_SPRITE "sprites/physbeam.vmt" +#define PHYSGUN_BEAM_GLOW "sprites/physglow.vmt" + +#define PHYSGUN_SKIN 1 + +class CWeaponGravityGun; + +#ifdef CLIENT_DLL +CLIENTEFFECT_REGISTER_BEGIN(PrecacheEffectGravityGun) +CLIENTEFFECT_MATERIAL("sprites/physbeam1") +CLIENTEFFECT_MATERIAL("sprites/physbeam") +CLIENTEFFECT_MATERIAL("sprites/physglow") +CLIENTEFFECT_REGISTER_END() + + +#endif + + +#ifndef OMOD +#define OMOD OPENMOD +#endif // !OMOD + + +IPhysicsObject* GetPhysObjFromPhysicsBone(CBaseEntity* pEntity, short physicsbone) +{ + if (pEntity->IsNPC()) + { + return pEntity->VPhysicsGetObject(); + } + + CBaseAnimating* pModel = static_cast(pEntity); + if (pModel != NULL) + { + IPhysicsObject* pPhysicsObject = NULL; + + //Find the real object we hit. + if (physicsbone >= 0) + { +#ifdef CLIENT_DLL + if (pModel->m_pRagdoll) + { + CRagdoll* pCRagdoll = dynamic_cast (pModel->m_pRagdoll); +#else + // Affect the object + CRagdollProp* pCRagdoll = dynamic_cast(pEntity); +#endif + if (pCRagdoll) + { + ragdoll_t* pRagdollT = pCRagdoll->GetRagdoll(); + + if (physicsbone < pRagdollT->listCount) + { + pPhysicsObject = pRagdollT->list[physicsbone].pObject; + } + return pPhysicsObject; + } +#ifdef CLIENT_DLL + } +#endif + } + } + +return pEntity->VPhysicsGetObject(); +} + +class CGravControllerPoint : public IMotionEvent +{ + DECLARE_SIMPLE_DATADESC(); + +public: + CGravControllerPoint(void); + ~CGravControllerPoint(void); + void AttachEntity(CBasePlayer* pPlayer, CBaseEntity* pEntity, IPhysicsObject* pPhys, short physicsbone, const Vector& position); + void DetachEntity(void); + + bool UpdateObject(CBasePlayer* pPlayer, CBaseEntity* pEntity); + + void SetTargetPosition(const Vector& target, const QAngle& targetOrientation) + { + m_shadow.targetPosition = target; + m_shadow.targetRotation = targetOrientation; + + m_timeToArrive = gpGlobals->frametime; + + CBaseEntity* pAttached = m_attachedEntity; + if (pAttached) + { + IPhysicsObject* pObj = GetPhysObjFromPhysicsBone(pAttached, m_attachedPhysicsBone); + + if (pObj != NULL) + { + pObj->Wake(); + } + else + { + DetachEntity(); + } + } + } + QAngle TransformAnglesToPlayerSpace(const QAngle& anglesIn, CBasePlayer* pPlayer); + QAngle TransformAnglesFromPlayerSpace(const QAngle& anglesIn, CBasePlayer* pPlayer); + + IMotionEvent::simresult_e Simulate(IPhysicsMotionController* pController, IPhysicsObject* pObject, float deltaTime, Vector& linear, AngularImpulse& angular); + Vector m_localPosition; + Vector m_targetPosition; + Vector m_worldPosition; + float m_saveDamping; + float m_saveMass; + float m_maxAcceleration; + Vector m_maxAngularAcceleration; + EHANDLE m_attachedEntity; + short m_attachedPhysicsBone; + QAngle m_targetRotation; + float m_timeToArrive; + +#ifdef OMOD + // adnan + // set up the modified pickup angles... allow the player to rotate the object in their grip + QAngle m_vecRotatedCarryAngles; + bool m_bHasRotatedCarryAngles; + // end adnan +#endif + + IPhysicsMotionController* m_controller; + +private: + hlshadowcontrol_params_t m_shadow; +}; + + +BEGIN_SIMPLE_DATADESC(CGravControllerPoint) + +DEFINE_FIELD(m_localPosition, FIELD_VECTOR), +DEFINE_FIELD(m_targetPosition, FIELD_POSITION_VECTOR), +DEFINE_FIELD(m_worldPosition, FIELD_POSITION_VECTOR), +DEFINE_FIELD(m_saveDamping, FIELD_FLOAT), +DEFINE_FIELD(m_saveMass, FIELD_FLOAT), +DEFINE_FIELD(m_maxAcceleration, FIELD_FLOAT), +DEFINE_FIELD(m_maxAngularAcceleration, FIELD_VECTOR), +DEFINE_FIELD(m_attachedEntity, FIELD_EHANDLE), +DEFINE_FIELD(m_attachedPhysicsBone, FIELD_SHORT), +DEFINE_FIELD(m_targetRotation, FIELD_VECTOR), +DEFINE_FIELD(m_timeToArrive, FIELD_FLOAT), +#ifdef OMOD +// adnan +// set up the fields for our added vars +DEFINE_FIELD(m_vecRotatedCarryAngles, FIELD_VECTOR), +DEFINE_FIELD(m_bHasRotatedCarryAngles, FIELD_BOOLEAN), +// end adnan +#endif + + // Physptrs can't be saved in embedded classes... this is to silence classcheck + // DEFINE_PHYSPTR( m_controller ), + + END_DATADESC() + + + CGravControllerPoint::CGravControllerPoint(void) +{ + m_shadow.dampFactor = 0.8; + m_shadow.teleportDistance = 0; + // make this controller really stiff! + m_shadow.maxSpeed = 5000; + m_shadow.maxAngular = m_shadow.maxSpeed; + m_shadow.maxDampSpeed = m_shadow.maxSpeed * 2; + m_shadow.maxDampAngular = m_shadow.maxAngular * 2; + m_attachedEntity = NULL; + m_attachedPhysicsBone = 0; + +#ifdef OMOD + // adnan + // initialize our added vars + m_vecRotatedCarryAngles = vec3_angle; + m_bHasRotatedCarryAngles = false; + // end adnan +#endif +} + +CGravControllerPoint::~CGravControllerPoint(void) +{ + DetachEntity(); +} + + +QAngle CGravControllerPoint::TransformAnglesToPlayerSpace(const QAngle& anglesIn, CBasePlayer* pPlayer) +{ + matrix3x4_t test; + QAngle angleTest = pPlayer->EyeAngles(); + angleTest.x = 0; + AngleMatrix(angleTest, test); + return TransformAnglesToLocalSpace(anglesIn, test); +} + +QAngle CGravControllerPoint::TransformAnglesFromPlayerSpace(const QAngle& anglesIn, CBasePlayer* pPlayer) +{ + matrix3x4_t test; + QAngle angleTest = pPlayer->EyeAngles(); + angleTest.x = 0; + AngleMatrix(angleTest, test); + return TransformAnglesToWorldSpace(anglesIn, test); +} + + +void CGravControllerPoint::AttachEntity(CBasePlayer* pPlayer, CBaseEntity* pEntity, IPhysicsObject* pPhys, short physicsbone, const Vector& vGrabPosition) +{ + m_attachedEntity = pEntity; + m_attachedPhysicsBone = physicsbone; + pPhys->WorldToLocal(&m_localPosition, vGrabPosition); + m_worldPosition = vGrabPosition; + pPhys->GetDamping(NULL, &m_saveDamping); + m_saveMass = pPhys->GetMass(); + float damping = 2; + pPhys->SetDamping(NULL, &damping); + pPhys->SetMass(50000); + m_controller = physenv->CreateMotionController(this); + m_controller->AttachObject(pPhys, true); + Vector position; + QAngle angles; + pPhys->GetPosition(&position, &angles); + SetTargetPosition(vGrabPosition, angles); + m_targetRotation = TransformAnglesToPlayerSpace(angles, pPlayer); +#ifdef OMOD + // adnan + // we need to grab the preferred/non preferred carry angles here for the rotatedcarryangles + m_vecRotatedCarryAngles = m_targetRotation; + // end adnan +#endif +} + +void CGravControllerPoint::DetachEntity(void) +{ + CBaseEntity* pEntity = m_attachedEntity; + if (pEntity) + { + IPhysicsObject* pPhys = GetPhysObjFromPhysicsBone(pEntity, m_attachedPhysicsBone); + if (pPhys) + { + // on the odd chance that it's gone to sleep while under anti-gravity + pPhys->Wake(); + pPhys->SetDamping(NULL, &m_saveDamping); + pPhys->SetMass(m_saveMass); + } + } + m_attachedEntity = NULL; + m_attachedPhysicsBone = 0; + if (physenv) + { + physenv->DestroyMotionController(m_controller); + } + m_controller = NULL; + + // UNDONE: Does this help the networking? + m_targetPosition = vec3_origin; + m_worldPosition = vec3_origin; +} + +void AxisAngleQAngle(const Vector& axis, float angle, QAngle& outAngles) +{ + // map back to HL rotation axes + outAngles.z = axis.x * angle; + outAngles.x = axis.y * angle; + outAngles.y = axis.z * angle; +} + +IMotionEvent::simresult_e CGravControllerPoint::Simulate(IPhysicsMotionController* pController, IPhysicsObject* pObject, float deltaTime, Vector& linear, AngularImpulse& angular) +{ + hlshadowcontrol_params_t shadowParams = m_shadow; +#ifndef CLIENT_DLL + m_timeToArrive = pObject->ComputeShadowControl(shadowParams, m_timeToArrive, deltaTime); +#else + m_timeToArrive = pObject->ComputeShadowControl(shadowParams, (TICK_INTERVAL * 2), deltaTime); +#endif + + linear.Init(); + angular.Init(); + + return SIM_LOCAL_ACCELERATION; +} + + +#ifdef CLIENT_DLL +#define CWeaponGravityGun C_WeaponGravityGun +#endif + +class CWeaponGravityGun : public CBaseHL2MPCombatWeapon +{ + DECLARE_DATADESC(); + +public: + DECLARE_CLASS(CWeaponGravityGun, CBaseHL2MPCombatWeapon); + + DECLARE_NETWORKCLASS(); + DECLARE_PREDICTABLE(); + + CWeaponGravityGun(); + +#ifdef CLIENT_DLL + void GetRenderBounds(Vector& mins, Vector& maxs) + { + BaseClass::GetRenderBounds(mins, maxs); + + // add to the bounds, don't clear them. + // ClearBounds( mins, maxs ); + AddPointToBounds(vec3_origin, mins, maxs); + AddPointToBounds(m_targetPosition, mins, maxs); + AddPointToBounds(m_worldPosition, mins, maxs); + CBaseEntity* pEntity = GetBeamEntity(); + if (pEntity) + { + mins -= pEntity->GetRenderOrigin(); + maxs -= pEntity->GetRenderOrigin(); + } + } + + void GetRenderBoundsWorldspace(Vector& mins, Vector& maxs) + { + BaseClass::GetRenderBoundsWorldspace(mins, maxs); + + // add to the bounds, don't clear them. + // ClearBounds( mins, maxs ); + AddPointToBounds(vec3_origin, mins, maxs); + AddPointToBounds(m_targetPosition, mins, maxs); + AddPointToBounds(m_worldPosition, mins, maxs); + mins -= GetRenderOrigin(); + maxs -= GetRenderOrigin(); + } + + int KeyInput(int down, ButtonCode_t keynum, const char* pszCurrentBinding) + { + if (gHUD.m_iKeyBits & IN_ATTACK) + { + switch (keynum) + { + case MOUSE_WHEEL_UP: + m_bInWeapon1 = true; + // gHUD.m_iKeyBits |= IN_WEAPON1; + if (gpGlobals->maxClients > 1) + gHUD.m_bSkipClear = true; + return 0; + + case MOUSE_WHEEL_DOWN: + m_bInWeapon2 = true; + // gHUD.m_iKeyBits |= IN_WEAPON2; + if (gpGlobals->maxClients > 1) + gHUD.m_bSkipClear = true; + return 0; + } + } + + // Allow engine to process + return BaseClass::KeyInput(down, keynum, pszCurrentBinding); + } + + void HandleInput() + { + if (m_bInWeapon1) + { + gHUD.m_iKeyBits |= IN_WEAPON1; + m_bInWeapon1 = false; + } + + if (m_bInWeapon2) + { + gHUD.m_iKeyBits |= IN_WEAPON2; + m_bInWeapon2 = false; + } + } + + int DrawModel(int flags); + void ViewModelDrawn(C_BaseViewModel* pBaseViewModel); + bool IsTransparent(void); + + // We need to render opaque and translucent pieces + RenderGroup_t GetRenderGroup(void) { return RENDER_GROUP_TWOPASS; } +#endif + + void Spawn(void); + void OnRestore(void); + void Precache(void); + +#ifdef OMOD + // adnan + // for overriding the mouse -> view angles (but still calc view angles) + bool OverrideViewAngles(void); + // end adnan +#endif + + virtual void UpdateOnRemove(void); + void PrimaryAttack(void); + void SecondaryAttack(void); + void ItemPreFrame(void); + void ItemPostFrame(void); + virtual bool Holster(CBaseCombatWeapon* pSwitchingTo) + { + EffectDestroy(); + SoundDestroy(); + return BaseClass::Holster(pSwitchingTo); + } + + bool Reload(void); + void Drop(const Vector& vecVelocity) + { + EffectDestroy(); + SoundDestroy(); + +#ifndef CLIENT_DLL + UTIL_Remove(this); +#endif + } + + bool HasAnyAmmo(void); + + void AttachObject(CBaseEntity* pEdict, IPhysicsObject* pPhysics, short physicsbone, const Vector& start, const Vector& end, float distance); + void UpdateObject(void); + void DetachObject(void); + + void TraceLine(trace_t* ptr); + + void EffectCreate(void); + void EffectUpdate(void); + void EffectDestroy(void); + + void SoundCreate(void); + void SoundDestroy(void); + void SoundStop(void); + void SoundStart(void); + void SoundUpdate(void); + + int ObjectCaps(void) + { + int caps = BaseClass::ObjectCaps(); + if (m_active) + { + caps |= FCAP_DIRECTIONAL_USE; + } + return caps; + } + + CBaseEntity* GetBeamEntity(); + +private: + CNetworkVar(int, m_active); + bool m_useDown; + CNetworkHandle(CBaseEntity, m_hObject); + CNetworkVar(int, m_physicsBone); + float m_distance; + float m_movementLength; + int m_soundState; + Vector m_originalObjectPosition; + CNetworkVector(m_targetPosition); + CNetworkVector(m_worldPosition); + +#ifdef OMOD + // adnan + // this is how we tell if we're rotating what we're holding + CNetworkVar(bool, m_bIsCurrentlyRotating); + // end adnan +#endif + + CSoundPatch* m_sndMotor; // Whirring sound for the gun + CSoundPatch* m_sndLockedOn; + CSoundPatch* m_sndLightObject; + CSoundPatch* m_sndHeavyObject; + + CGravControllerPoint m_gravCallback; + + bool m_bInWeapon1; + bool m_bInWeapon2; + + DECLARE_ACTTABLE(); +}; + +IMPLEMENT_NETWORKCLASS_ALIASED(WeaponGravityGun, DT_WeaponGravityGun) + +BEGIN_NETWORK_TABLE(CWeaponGravityGun, DT_WeaponGravityGun) +#ifdef CLIENT_DLL +RecvPropEHandle(RECVINFO(m_hObject)), +RecvPropInt(RECVINFO(m_physicsBone)), +RecvPropVector(RECVINFO(m_targetPosition)), +RecvPropVector(RECVINFO(m_worldPosition)), +RecvPropInt(RECVINFO(m_active)), +#ifdef OMOD +// adnan +// also receive if we're rotating what we're holding (by pressing use) +RecvPropBool(RECVINFO(m_bIsCurrentlyRotating)), +// end adnan +#endif +#else +SendPropEHandle(SENDINFO(m_hObject)), +SendPropInt(SENDINFO(m_physicsBone)), +SendPropVector(SENDINFO(m_targetPosition), -1, SPROP_COORD), +SendPropVector(SENDINFO(m_worldPosition), -1, SPROP_COORD), +SendPropInt(SENDINFO(m_active), 1, SPROP_UNSIGNED), +#ifdef OMOD +// adnan +// need to seind if we're rotating what we're holding +SendPropBool(SENDINFO(m_bIsCurrentlyRotating)), +// end adnan +#endif +#endif +END_NETWORK_TABLE() + +#ifdef CLIENT_DLL +BEGIN_PREDICTION_DATA(CWeaponGravityGun) +END_PREDICTION_DATA() +#endif + +LINK_ENTITY_TO_CLASS(weapon_physgun, CWeaponGravityGun); +PRECACHE_WEAPON_REGISTER(weapon_physgun); + +acttable_t CWeaponGravityGun::m_acttable[] = +{ + { ACT_MP_STAND_IDLE, ACT_HL2MP_IDLE_PHYSGUN, false }, + { ACT_MP_CROUCH_IDLE, ACT_HL2MP_IDLE_CROUCH_PHYSGUN, false }, + + { ACT_MP_RUN, ACT_HL2MP_RUN_PHYSGUN, false }, + { ACT_MP_CROUCHWALK, ACT_HL2MP_WALK_CROUCH_PHYSGUN, false }, + + { ACT_MP_ATTACK_STAND_PRIMARYFIRE, ACT_HL2MP_GESTURE_RANGE_ATTACK_PHYSGUN, false }, + { ACT_MP_ATTACK_CROUCH_PRIMARYFIRE, ACT_HL2MP_GESTURE_RANGE_ATTACK_PHYSGUN, false }, + + { ACT_MP_RELOAD_STAND, ACT_HL2MP_GESTURE_RELOAD_PHYSGUN, false }, + { ACT_MP_RELOAD_CROUCH, ACT_HL2MP_GESTURE_RELOAD_PHYSGUN, false }, + + { ACT_MP_JUMP, ACT_HL2MP_JUMP_PHYSGUN, false }, +}; + +IMPLEMENT_ACTTABLE(CWeaponGravityGun); + + +//--------------------------------------------------------- +// Save/Restore +//--------------------------------------------------------- +BEGIN_DATADESC(CWeaponGravityGun) + +DEFINE_FIELD(m_active, FIELD_INTEGER), +DEFINE_FIELD(m_useDown, FIELD_BOOLEAN), +DEFINE_FIELD(m_hObject, FIELD_EHANDLE), +DEFINE_FIELD(m_physicsBone, FIELD_INTEGER), +DEFINE_FIELD(m_distance, FIELD_FLOAT), +DEFINE_FIELD(m_movementLength, FIELD_FLOAT), +DEFINE_FIELD(m_soundState, FIELD_INTEGER), +DEFINE_FIELD(m_originalObjectPosition, FIELD_POSITION_VECTOR), +#ifdef OMOD +// adnan +DEFINE_FIELD(m_bIsCurrentlyRotating, FIELD_BOOLEAN), +// end adnan +#endif +DEFINE_SOUNDPATCH(m_sndMotor), +DEFINE_SOUNDPATCH(m_sndLockedOn), +DEFINE_SOUNDPATCH(m_sndLightObject), +DEFINE_SOUNDPATCH(m_sndHeavyObject), +DEFINE_EMBEDDED(m_gravCallback), +// Physptrs can't be saved in embedded classes.. +DEFINE_PHYSPTR(m_gravCallback.m_controller), + +END_DATADESC() + + +enum physgun_soundstate { SS_SCANNING, SS_LOCKEDON }; +enum physgun_soundIndex { SI_LOCKEDON = 0, SI_SCANNING = 1, SI_LIGHTOBJECT = 2, SI_HEAVYOBJECT = 3, SI_ON, SI_OFF }; + + +//========================================================= +//========================================================= + +CWeaponGravityGun::CWeaponGravityGun() +{ + m_active = false; + m_bFiresUnderwater = true; + m_bInWeapon1 = false; + m_bInWeapon2 = false; +} + + +//----------------------------------------------------------------------------- +// On Remove +//----------------------------------------------------------------------------- +void CWeaponGravityGun::UpdateOnRemove(void) +{ + EffectDestroy(); + SoundDestroy(); + BaseClass::UpdateOnRemove(); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// adnan +// want to add an angles modifier key +bool CGravControllerPoint::UpdateObject(CBasePlayer* pPlayer, CBaseEntity* pEntity) +{ + IPhysicsObject* pPhysics = GetPhysObjFromPhysicsBone(pEntity, m_attachedPhysicsBone); + if (!pEntity || !pPhysics) + { + return false; + } + +#ifdef OMOD + // adnan + // if we've been rotating it, set it to its proper new angles (change m_attachedAnglesPlayerSpace while modifier) + //Pickup_GetRotatedCarryAngles( pEntity, pPlayer, pPlayer->EntityToWorldTransform(), angles ); + // added the ... && (mousedx | mousedy) so we dont have to calculate if no mouse movement + // UPDATE: m_vecRotatedCarryAngles has become a temp variable... can be cleaned up by using actual temp vars +#ifdef CLIENT_DLL + if (m_bHasRotatedCarryAngles && (pPlayer->m_pCurrentCommand->mousedx || pPlayer->m_pCurrentCommand->mousedy)) +#else + if (m_bHasRotatedCarryAngles && (pPlayer->GetCurrentCommand()->mousedx || pPlayer->GetCurrentCommand()->mousedy)) +#endif + { + // method II: relative orientation + VMatrix vDeltaRotation, vCurrentRotation, vNewRotation; + + MatrixFromAngles(m_targetRotation, vCurrentRotation); + +#ifdef CLIENT_DLL + m_vecRotatedCarryAngles[YAW] = pPlayer->m_pCurrentCommand->mousedx * 0.05; + m_vecRotatedCarryAngles[PITCH] = pPlayer->m_pCurrentCommand->mousedy * -0.05; +#else + m_vecRotatedCarryAngles[YAW] = pPlayer->GetCurrentCommand()->mousedx * 0.05; + m_vecRotatedCarryAngles[PITCH] = pPlayer->GetCurrentCommand()->mousedy * -0.05; +#endif + m_vecRotatedCarryAngles[ROLL] = 0; + MatrixFromAngles(m_vecRotatedCarryAngles, vDeltaRotation); + + MatrixMultiply(vDeltaRotation, vCurrentRotation, vNewRotation); + MatrixToAngles(vNewRotation, m_targetRotation); + } + // end adnan +#endif + + SetTargetPosition(m_targetPosition, m_targetRotation); + + return true; +} + +#ifdef OMOD +// adnan +// this is where we say that we dont want ot apply the current calculated view angles +//----------------------------------------------------------------------------- +// Purpose: Allow weapons to override mouse input to viewangles (for orbiting) +//----------------------------------------------------------------------------- +bool CWeaponGravityGun::OverrideViewAngles(void) +{ + CBasePlayer* pPlayer = ToBasePlayer(GetOwner()); + + if (!pPlayer) + return false; + + if (m_bIsCurrentlyRotating) { + return true; + } + + return false; +} +// end adnan +#endif + +//========================================================= +//========================================================= +void CWeaponGravityGun::Spawn() +{ + BaseClass::Spawn(); + // SetModel( GetWorldModel() ); + + // The physgun uses a different skin + m_nSkin = PHYSGUN_SKIN; + + FallInit(); +} + +void CWeaponGravityGun::OnRestore(void) +{ + BaseClass::OnRestore(); + + if (m_gravCallback.m_controller) + { + m_gravCallback.m_controller->SetEventHandler(&m_gravCallback); + } +} + + +//========================================================= +//========================================================= +void CWeaponGravityGun::Precache(void) +{ + BaseClass::Precache(); + + g_physgunBeam1 = PrecacheModel(PHYSGUN_BEAM_SPRITE1); + g_physgunBeam = PrecacheModel(PHYSGUN_BEAM_SPRITE); + g_physgunGlow = PrecacheModel(PHYSGUN_BEAM_GLOW); + + PrecacheScriptSound("Weapon_Physgun.Scanning"); + PrecacheScriptSound("Weapon_Physgun.LockedOn"); + PrecacheScriptSound("Weapon_Physgun.Scanning"); + PrecacheScriptSound("Weapon_Physgun.LightObject"); + PrecacheScriptSound("Weapon_Physgun.HeavyObject"); +} + +void CWeaponGravityGun::EffectCreate(void) +{ + EffectUpdate(); + m_active = true; +} + + +// Andrew; added so we can trace both in EffectUpdate and DrawModel with the same results +void CWeaponGravityGun::TraceLine(trace_t* ptr) +{ + CBasePlayer* pOwner = ToBasePlayer(GetOwner()); + if (!pOwner) + return; + + Vector start, forward, right; + pOwner->EyeVectors(&forward, &right, NULL); + + start = pOwner->Weapon_ShootPosition(); + Vector end = start + forward * 4096; + + // UTIL_TraceLine( start, end, MASK_SHOT, pOwner, COLLISION_GROUP_NONE, ptr ); + UTIL_TraceLine(start, end, MASK_SHOT | CONTENTS_GRATE, pOwner, COLLISION_GROUP_NONE, ptr); +} + + +void CWeaponGravityGun::EffectUpdate(void) +{ + Vector start, forward, right; + trace_t tr; + + CBasePlayer* pOwner = ToBasePlayer(GetOwner()); + if (!pOwner) + return; + + pOwner->EyeVectors(&forward, &right, NULL); + + start = pOwner->Weapon_ShootPosition(); + + TraceLine(&tr); + Vector end = tr.endpos; + float distance = tr.fraction * 4096; + + if (m_hObject == NULL && tr.DidHitNonWorldEntity()) + { + CBaseEntity* pEntity = tr.m_pEnt; + AttachObject(pEntity, GetPhysObjFromPhysicsBone(pEntity, tr.physicsbone), tr.physicsbone, start, tr.endpos, distance); + } + + // Add the incremental player yaw to the target transform + QAngle angles = m_gravCallback.TransformAnglesFromPlayerSpace(m_gravCallback.m_targetRotation, pOwner); + + CBaseEntity* pObject = m_hObject; + if (pObject) + { + if (m_useDown) + { + if (pOwner->m_afButtonPressed & IN_USE) + { + m_useDown = false; + } + } + else + { + if (pOwner->m_afButtonPressed & IN_USE) + { + m_useDown = true; + } + } + + if (m_useDown) + { +#ifndef CLIENT_DLL + pOwner->SetPhysicsFlag(PFLAG_DIROVERRIDE, true); +#endif + if (pOwner->m_nButtons & IN_FORWARD) + { + m_distance = Approach(1024, m_distance, gpGlobals->frametime * 100); + } + if (pOwner->m_nButtons & IN_BACK) + { + m_distance = Approach(40, m_distance, gpGlobals->frametime * 100); + } + } + + if (pOwner->m_nButtons & IN_WEAPON1) + { + m_distance = Approach(1024, m_distance, m_distance * 0.1); +#ifdef CLIENT_DLL + if (gpGlobals->maxClients > 1) + { + gHUD.m_bSkipClear = false; + } +#endif + } + if (pOwner->m_nButtons & IN_WEAPON2) + { + m_distance = Approach(40, m_distance, m_distance * 0.1); +#ifdef CLIENT_DLL + if (gpGlobals->maxClients > 1) + { + gHUD.m_bSkipClear = false; + } +#endif + } + + IPhysicsObject* pPhys = GetPhysObjFromPhysicsBone(pObject, m_physicsBone); + if (pPhys) + { + if (pPhys->IsAsleep()) + { + // on the odd chance that it's gone to sleep while under anti-gravity + pPhys->Wake(); + } + + Vector newPosition = start + forward * m_distance; + Vector offset; + pPhys->LocalToWorld(&offset, m_worldPosition); + Vector vecOrigin; + pPhys->GetPosition(&vecOrigin, NULL); + m_gravCallback.SetTargetPosition(newPosition + (vecOrigin - offset), angles); + Vector dir = (newPosition - pObject->GetLocalOrigin()); + m_movementLength = dir.Length(); + } + } + else + { + m_targetPosition = end; + //m_gravCallback.SetTargetPosition( end, m_gravCallback.m_targetRotation ); + } +} + +void CWeaponGravityGun::SoundCreate(void) +{ + m_soundState = SS_SCANNING; + SoundStart(); +} + + +void CWeaponGravityGun::SoundDestroy(void) +{ + SoundStop(); +} + + +void CWeaponGravityGun::SoundStop(void) +{ + CBasePlayer* pOwner = ToBasePlayer(GetOwner()); + if (!pOwner) + return; + + switch (m_soundState) + { + case SS_SCANNING: + (CSoundEnvelopeController::GetController()).SoundDestroy(m_sndMotor); + m_sndMotor = NULL; + break; + case SS_LOCKEDON: + (CSoundEnvelopeController::GetController()).SoundDestroy(m_sndMotor); + m_sndMotor = NULL; + (CSoundEnvelopeController::GetController()).SoundDestroy(m_sndLockedOn); + m_sndLockedOn = NULL; + (CSoundEnvelopeController::GetController()).SoundDestroy(m_sndLightObject); + m_sndLightObject = NULL; + (CSoundEnvelopeController::GetController()).SoundDestroy(m_sndHeavyObject); + m_sndHeavyObject = NULL; + break; + } +} + + + +//----------------------------------------------------------------------------- +// Purpose: returns the linear fraction of value between low & high (0.0 - 1.0) * scale +// e.g. UTIL_LineFraction( 1.5, 1, 2, 1 ); will return 0.5 since 1.5 is +// halfway between 1 and 2 +// Input : value - a value between low & high (clamped) +// low - the value that maps to zero +// high - the value that maps to "scale" +// scale - the output scale +// Output : parametric fraction between low & high +//----------------------------------------------------------------------------- +static float UTIL_LineFraction(float value, float low, float high, float scale) +{ + if (value < low) + value = low; + if (value > high) + value = high; + + float delta = high - low; + if (delta == 0) + return 0; + + return scale * (value - low) / delta; +} + +void CWeaponGravityGun::SoundStart(void) +{ + CPASAttenuationFilter filter(this); + + switch (m_soundState) + { + case SS_SCANNING: + { + m_sndMotor = (CSoundEnvelopeController::GetController()).SoundCreate(filter, entindex(), CHAN_STATIC, "Weapon_Physgun.Scanning", ATTN_NORM); + (CSoundEnvelopeController::GetController()).Play(m_sndMotor, 1.0f, 100); + } + break; + case SS_LOCKEDON: + { + m_sndLockedOn = (CSoundEnvelopeController::GetController()).SoundCreate(filter, entindex(), CHAN_STATIC, "Weapon_Physgun.LockedOn", ATTN_NORM); + (CSoundEnvelopeController::GetController()).Play(m_sndLockedOn, 1.0f, 100); + m_sndMotor = (CSoundEnvelopeController::GetController()).SoundCreate(filter, entindex(), CHAN_STATIC, "Weapon_Physgun.Scanning", ATTN_NORM); + (CSoundEnvelopeController::GetController()).Play(m_sndMotor, 1.0f, 100); + m_sndLightObject = (CSoundEnvelopeController::GetController()).SoundCreate(filter, entindex(), CHAN_STATIC, "Weapon_Physgun.LightObject", ATTN_NORM); + (CSoundEnvelopeController::GetController()).Play(m_sndLightObject, 1.0f, 100); + m_sndHeavyObject = (CSoundEnvelopeController::GetController()).SoundCreate(filter, entindex(), CHAN_STATIC, "Weapon_Physgun.HeavyObject", ATTN_NORM); + (CSoundEnvelopeController::GetController()).Play(m_sndHeavyObject, 1.0f, 100); + } + break; + } + // volume, att, flags, pitch +} + +void CWeaponGravityGun::SoundUpdate(void) +{ + int newState; + + if (m_hObject) + newState = SS_LOCKEDON; + else + newState = SS_SCANNING; + + if (newState != m_soundState) + { + SoundStop(); + m_soundState = newState; + SoundStart(); + } + + switch (m_soundState) + { + case SS_SCANNING: + break; + case SS_LOCKEDON: + { + CPASAttenuationFilter filter(this); + + float height = m_hObject->GetAbsOrigin().z - m_originalObjectPosition.z; + + // go from pitch 90 to 150 over a height of 500 + int pitch = 90 + (int)UTIL_LineFraction(height, 0, 500, 60); + + assert(m_sndLockedOn != NULL); + if (m_sndLockedOn != NULL) + { + (CSoundEnvelopeController::GetController()).SoundChangePitch(m_sndLockedOn, pitch, 0.0f); + } + + // attenutate the movement sounds over 200 units of movement + float distance = UTIL_LineFraction(m_movementLength, 0, 200, 1.0); + + // blend the "mass" sounds between 50 and 500 kg + IPhysicsObject* pPhys = GetPhysObjFromPhysicsBone(m_hObject, m_physicsBone); + if (pPhys == NULL) + { + // we no longer exist! + break; + } + + float fade = UTIL_LineFraction(pPhys->GetMass(), 50, 500, 1.0); + + (CSoundEnvelopeController::GetController()).SoundChangeVolume(m_sndLightObject, fade * distance, 0.0f); + + (CSoundEnvelopeController::GetController()).SoundChangeVolume(m_sndHeavyObject, (1.0 - fade) * distance, 0.0f); + } + break; + } +} + + +CBaseEntity* CWeaponGravityGun::GetBeamEntity() +{ + CBasePlayer* pOwner = ToBasePlayer(GetOwner()); + if (!pOwner) + return NULL; + + // Make sure I've got a view model + CBaseViewModel* vm = pOwner->GetViewModel(); + if (vm) + return vm; + + return pOwner; +} + +void CWeaponGravityGun::EffectDestroy(void) +{ +#ifdef CLIENT_DLL + gHUD.m_bSkipClear = false; +#endif + m_active = false; + SoundStop(); + + DetachObject(); +} + +void CWeaponGravityGun::UpdateObject(void) +{ + CBasePlayer* pPlayer = ToBasePlayer(GetOwner()); + Assert(pPlayer); + + CBaseEntity* pObject = m_hObject; + if (!pObject) + return; + + if (!m_gravCallback.UpdateObject(pPlayer, pObject)) + { + DetachObject(); + return; + } +} + +void CWeaponGravityGun::DetachObject(void) +{ + if (m_hObject) + { +#ifndef CLIENT_DLL + CBasePlayer* pOwner = ToBasePlayer(GetOwner()); + Pickup_OnPhysGunDrop(m_hObject, pOwner, DROPPED_BY_CANNON); +#endif + + IPhysicsObject* pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; + int count = m_hObject->VPhysicsGetObjectList(pList, ARRAYSIZE(pList)); + for (int i = 0; i < count; i++) + { + PhysClearGameFlags(pList[i], FVPHYSICS_PLAYER_HELD); + } + m_gravCallback.DetachEntity(); + m_hObject = NULL; + m_physicsBone = 0; + } +} + +void CWeaponGravityGun::AttachObject(CBaseEntity* pObject, IPhysicsObject* pPhysics, short physicsbone, const Vector& start, const Vector& end, float distance) +{ + CBasePlayer* pOwner = ToBasePlayer(GetOwner()); + if (!pOwner) + return; + m_hObject = pObject; + m_physicsBone = physicsbone; + m_useDown = false; + if (pPhysics && pObject->GetMoveType() == MOVETYPE_VPHYSICS) + { + m_distance = distance; + + Vector worldPosition; + pPhysics->WorldToLocal(&worldPosition, end); + m_worldPosition = worldPosition; + Vector vecOrigin; + pPhysics->GetPosition(&vecOrigin, NULL); + m_gravCallback.AttachEntity(pOwner, pObject, pPhysics, physicsbone, vecOrigin); + + m_originalObjectPosition = vecOrigin; + + pPhysics->Wake(); + IPhysicsObject* pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; + int count = pObject->VPhysicsGetObjectList(pList, ARRAYSIZE(pList)); + for (int i = 0; i < count; i++) + { + PhysSetGameFlags(pList[i], FVPHYSICS_PLAYER_HELD); + } + +#ifndef CLIENT_DLL + Pickup_OnPhysGunPickup(pObject, pOwner); +#endif + } + else + { + m_hObject = NULL; + m_physicsBone = 0; + } +} + +//========================================================= +//========================================================= +void CWeaponGravityGun::PrimaryAttack(void) +{ + if (!m_active) + { + SendWeaponAnim(ACT_VM_PRIMARYATTACK); + EffectCreate(); + SoundCreate(); + } + else + { + EffectUpdate(); + SoundUpdate(); + } +} + +void CWeaponGravityGun::SecondaryAttack(void) +{ + return; +} + +#ifdef CLIENT_DLL +//----------------------------------------------------------------------------- +// Purpose: Third-person function call to render world model +//----------------------------------------------------------------------------- +int CWeaponGravityGun::DrawModel(int flags) +{ + // Only render these on the transparent pass + if (flags & STUDIO_TRANSPARENCY) + { + if (!m_active) + return 0; + + C_BasePlayer* pOwner = ToBasePlayer(GetOwner()); + + if (!pOwner) + return 0; + + Vector points[3]; + QAngle tmpAngle; + + C_BaseEntity* pObject = m_hObject; + //if ( pObject == NULL ) + // return 0; + + GetAttachment(1, points[0], tmpAngle); + + // a little noise 11t & 13t should be somewhat non-periodic looking + //points[1].z += 4*sin( gpGlobals->curtime*11 ) + 5*cos( gpGlobals->curtime*13 ); + if (pObject == NULL) + { + //points[2] = m_targetPosition; + trace_t tr; + TraceLine(&tr); + points[2] = tr.endpos; + } + else + { + pObject->EntityToWorldSpace(m_worldPosition, &points[2]); + } + + Vector forward, right, up; + QAngle playerAngles = pOwner->EyeAngles(); + AngleVectors(playerAngles, &forward, &right, &up); + if (pObject == NULL) + { + Vector vecDir = points[2] - points[0]; + VectorNormalize(vecDir); + points[1] = points[0] + 0.5f * (vecDir * points[2].DistTo(points[0])); + } + else + { + Vector vecSrc = pOwner->Weapon_ShootPosition(); + points[1] = vecSrc + 0.5f * (forward * points[2].DistTo(points[0])); + } + + IMaterial* pMat = materials->FindMaterial("sprites/physbeam1", TEXTURE_GROUP_CLIENT_EFFECTS); + if (pObject) + pMat = materials->FindMaterial("sprites/physbeam", TEXTURE_GROUP_CLIENT_EFFECTS); + Vector color; + color.Init(1, 1, 1); + + float scrollOffset = gpGlobals->curtime - (int)gpGlobals->curtime; + CMatRenderContextPtr pRenderContext(materials); + pRenderContext->Bind(pMat); + DrawBeamQuadratic(points[0], points[1], points[2], pObject ? 13 / 3.0f : 13 / 5.0f, color, scrollOffset); + DrawBeamQuadratic(points[0], points[1], points[2], pObject ? 13 / 3.0f : 13 / 5.0f, color, -scrollOffset); + + IMaterial* pMaterial = materials->FindMaterial("sprites/physglow", TEXTURE_GROUP_CLIENT_EFFECTS); + + color32 clr = { 0,64,255,255 }; + if (pObject) + { + clr.r = 186; + clr.g = 253; + clr.b = 247; + clr.a = 255; + } + + float scale = random->RandomFloat(3, 5) * (pObject ? 3 : 2); + + // Draw the sprite + pRenderContext->Bind(pMaterial); + for (int i = 0; i < 3; i++) + { + DrawSprite(points[2], scale, scale, clr); + } + return 1; + } + + // Only do this on the opaque pass + return BaseClass::DrawModel(flags); +} + +//----------------------------------------------------------------------------- +// Purpose: First-person function call after viewmodel has been drawn +//----------------------------------------------------------------------------- +void CWeaponGravityGun::ViewModelDrawn(C_BaseViewModel* pBaseViewModel) +{ + if (!m_active) + return; + + // Render our effects + C_BasePlayer* pOwner = ToBasePlayer(GetOwner()); + + if (!pOwner) + return; + + Vector points[3]; + QAngle tmpAngle; + + C_BaseEntity* pObject = m_hObject; + //if ( pObject == NULL ) + // return; + + pBaseViewModel->GetAttachment(1, points[0], tmpAngle); + + // a little noise 11t & 13t should be somewhat non-periodic looking + //points[1].z += 4*sin( gpGlobals->curtime*11 ) + 5*cos( gpGlobals->curtime*13 ); + if (pObject == NULL) + { + //points[2] = m_targetPosition; + trace_t tr; + TraceLine(&tr); + points[2] = tr.endpos; + } + else + { + pObject->EntityToWorldSpace(m_worldPosition, &points[2]); + } + + Vector forward, right, up; + QAngle playerAngles = pOwner->EyeAngles(); + AngleVectors(playerAngles, &forward, &right, &up); + Vector vecSrc = pOwner->Weapon_ShootPosition(); + points[1] = vecSrc + 0.5f * (forward * points[2].DistTo(points[0])); + + IMaterial* pMat = materials->FindMaterial("sprites/physbeam1", TEXTURE_GROUP_CLIENT_EFFECTS); + if (pObject) + pMat = materials->FindMaterial("sprites/physbeam", TEXTURE_GROUP_CLIENT_EFFECTS); + Vector color; + color.Init(1, 1, 1); + + // Now draw it. + CViewSetup beamView = *view->GetPlayerViewSetup(); + + Frustum dummyFrustum; + render->Push3DView(beamView, 0, NULL, dummyFrustum); + + float scrollOffset = gpGlobals->curtime - (int)gpGlobals->curtime; + CMatRenderContextPtr pRenderContext(materials); + pRenderContext->Bind(pMat); +#if 1 + // HACK HACK: Munge the depth range to prevent view model from poking into walls, etc. + // Force clipped down range + pRenderContext->DepthRange(0.1f, 0.2f); +#endif + DrawBeamQuadratic(points[0], points[1], points[2], pObject ? 13 / 3.0f : 13 / 5.0f, color, scrollOffset); + DrawBeamQuadratic(points[0], points[1], points[2], pObject ? 13 / 3.0f : 13 / 5.0f, color, -scrollOffset); + + IMaterial* pMaterial = materials->FindMaterial("sprites/physglow", TEXTURE_GROUP_CLIENT_EFFECTS); + + color32 clr = { 0,64,255,255 }; + if (pObject) + { + clr.r = 186; + clr.g = 253; + clr.b = 247; + clr.a = 255; + } + + float scale = random->RandomFloat(3, 5) * (pObject ? 3 : 2); + + // Draw the sprite + pRenderContext->Bind(pMaterial); + for (int i = 0; i < 3; i++) + { + DrawSprite(points[2], scale, scale, clr); + } +#if 1 + pRenderContext->DepthRange(0.0f, 1.0f); +#endif + + render->PopView(dummyFrustum); + + // Pass this back up + BaseClass::ViewModelDrawn(pBaseViewModel); +} + +//----------------------------------------------------------------------------- +// Purpose: We are always considered transparent +//----------------------------------------------------------------------------- +bool CWeaponGravityGun::IsTransparent(void) +{ + return true; +} + +#endif + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CWeaponGravityGun::ItemPreFrame() +{ + BaseClass::ItemPreFrame(); + +#ifndef CLIENT_DLL + // Update the object if the weapon is switched on. + if (m_active) + { + UpdateObject(); + } +#endif +} + + +void CWeaponGravityGun::ItemPostFrame(void) +{ + CBasePlayer* pOwner = ToBasePlayer(GetOwner()); + if (!pOwner) + return; + +#ifdef OMOD + // adnan + // this is where we check if we're orbiting the object + + // if we're holding something and pressing use, + // then set us in the orbiting state + // - this will indicate to OverrideMouseInput that we should zero the input and update our delta angles + // UPDATE: not anymore. now this just sets our state variables. + CBaseEntity* pObject = m_hObject; + if (pObject) { + + if ((pOwner->m_nButtons & IN_ATTACK) && (pOwner->m_nButtons & IN_USE)) { + m_gravCallback.m_bHasRotatedCarryAngles = true; + + // did we JUST hit use? + // if so, grab the current angles to begin with as the rotated angles + if (!(pOwner->m_afButtonLast & IN_USE)) { + m_gravCallback.m_vecRotatedCarryAngles = pObject->GetAbsAngles(); + } + + m_bIsCurrentlyRotating = true; + } + else { + m_gravCallback.m_bHasRotatedCarryAngles = false; + + m_bIsCurrentlyRotating = false; + } + } + else { + m_bIsCurrentlyRotating = false; + + m_gravCallback.m_bHasRotatedCarryAngles = false; + } + // end adnan +#endif + + if (pOwner->m_nButtons & IN_ATTACK) + { +#if defined( OMOD ) + if ((pOwner->m_nButtons & IN_USE)) { + pOwner->m_vecUseAngles = pOwner->pl.v_angle; + } +#endif + if (pOwner->m_afButtonPressed & IN_ATTACK2) + { + SecondaryAttack(); + } + else if (pOwner->m_nButtons & IN_ATTACK2) + { + if (m_active) + { + EffectDestroy(); + SoundDestroy(); + } + WeaponIdle(); + return; + } + PrimaryAttack(); + } + else + { + if (m_active) + { + EffectDestroy(); + SoundDestroy(); + } + WeaponIdle(); + return; + } + if (pOwner->m_afButtonPressed & IN_RELOAD) + { + Reload(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CWeaponGravityGun::HasAnyAmmo(void) +{ + //Always report that we have ammo + return true; +} + +//========================================================= +//========================================================= +bool CWeaponGravityGun::Reload(void) +{ + return false; +} \ No newline at end of file From be62e9908aa7f9de9b5433068ff1c3bd2e278089 Mon Sep 17 00:00:00 2001 From: nuv3x Date: Tue, 8 Jul 2025 16:29:15 +0400 Subject: [PATCH 2/2] ifdef --- src/game/client/c_baseplayer.cpp | 9 ++++++++- src/game/client/c_baseplayer.h | 3 ++- src/game/client/clientmode_shared.cpp | 5 +++++ src/game/client/hud.cpp | 3 +++ src/game/client/hud.h | 2 ++ src/game/client/in_mouse.cpp | 2 ++ src/game/server/player.cpp | 6 ++++-- src/game/server/player.h | 3 ++- src/game/shared/basecombatweapon_shared.h | 4 +++- 9 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/game/client/c_baseplayer.cpp b/src/game/client/c_baseplayer.cpp index 7409e1db3..b28ceb2b5 100644 --- a/src/game/client/c_baseplayer.cpp +++ b/src/game/client/c_baseplayer.cpp @@ -244,7 +244,11 @@ END_RECV_TABLE() RecvPropFloat ( RECVINFO(m_vecVelocity[2]), 0, RecvProxy_LocalVelocityZ ), RecvPropVector ( RECVINFO( m_vecBaseVelocity ) ), + +#ifdef OPENMOD RecvPropVector(RECVINFO(m_vecUseAngles)), +#endif // OPENMOD + RecvPropEHandle ( RECVINFO( m_hConstraintEntity)), RecvPropVector ( RECVINFO( m_vecConstraintCenter) ), RecvPropFloat ( RECVINFO( m_flConstraintRadius )), @@ -295,8 +299,9 @@ END_RECV_TABLE() RecvPropFloat (RECVINFO(m_flMaxspeed)), RecvPropInt (RECVINFO(m_fFlags)), +#if defined OPENMOD RecvPropVector(RECVINFO(m_vecUseAngles)), - +#endif RecvPropInt (RECVINFO(m_iObserverMode), 0, RecvProxy_ObserverMode ), RecvPropEHandle (RECVINFO(m_hObserverTarget), RecvProxy_ObserverTarget ), @@ -1419,6 +1424,7 @@ void C_BasePlayer::CreateWaterEffects( void ) //----------------------------------------------------------------------------- void C_BasePlayer::OverrideView( CViewSetup *pSetup ) { +#ifdef OPENMOD C_BaseCombatWeapon* pWeapon = GetActiveWeapon(); if (pWeapon) { @@ -1430,6 +1436,7 @@ void C_BasePlayer::OverrideView( CViewSetup *pSetup ) pSetup->angles = m_vecUseAngles; } } +#endif // OPENMOD } bool C_BasePlayer::ShouldInterpolate() diff --git a/src/game/client/c_baseplayer.h b/src/game/client/c_baseplayer.h index 0eab06daa..361a29a9b 100644 --- a/src/game/client/c_baseplayer.h +++ b/src/game/client/c_baseplayer.h @@ -440,8 +440,9 @@ class C_BasePlayer : public C_BaseCombatCharacter, public CGameEventListener CUserCmd *m_pCurrentCommand; +#if defined OPENMOD QAngle m_vecUseAngles; - +#endif // Movement constraints EHANDLE m_hConstraintEntity; Vector m_vecConstraintCenter; diff --git a/src/game/client/clientmode_shared.cpp b/src/game/client/clientmode_shared.cpp index ca569a037..30d984f97 100644 --- a/src/game/client/clientmode_shared.cpp +++ b/src/game/client/clientmode_shared.cpp @@ -519,6 +519,8 @@ void ClientModeShared::OverrideMouseInput( float *x, float *y ) } } +#ifdef OPENMOD + bool ClientModeShared::OverrideViewAngles(void) { C_BaseCombatWeapon* pWeapon = GetActiveWeapon(); @@ -529,6 +531,9 @@ bool ClientModeShared::OverrideViewAngles(void) return false; } +#endif // OPENMOD + + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- diff --git a/src/game/client/hud.cpp b/src/game/client/hud.cpp index 6858397d9..c72bdefd7 100644 --- a/src/game/client/hud.cpp +++ b/src/game/client/hud.cpp @@ -388,7 +388,10 @@ CHud::CHud() m_flScreenShotTime = -1; +#ifdef OPENMOD m_bSkipClear = false; +#endif // OPENMOD + } //----------------------------------------------------------------------------- diff --git a/src/game/client/hud.h b/src/game/client/hud.h index bbb8f11e4..763b110eb 100644 --- a/src/game/client/hud.h +++ b/src/game/client/hud.h @@ -173,7 +173,9 @@ class CHud public: int m_iKeyBits; +#ifdef OPENMOD bool m_bSkipClear; +#endif // OPENMOD #ifndef _XBOX float m_flMouseSensitivity; float m_flMouseSensitivityFactor; diff --git a/src/game/client/in_mouse.cpp b/src/game/client/in_mouse.cpp index 6cdac16d5..123ca6461 100644 --- a/src/game/client/in_mouse.cpp +++ b/src/game/client/in_mouse.cpp @@ -740,6 +740,7 @@ void CInput::MouseMove( CUserCmd *cmd ) ResetMouse(); } +#if defined(OPENMOD) // adnan // only set the new viewangles if we're not supposed to override them if (!(g_pClientMode->OverrideViewAngles())) @@ -749,6 +750,7 @@ void CInput::MouseMove( CUserCmd *cmd ) engine->SetViewAngles(viewangles); } // end adnan +#endif } //----------------------------------------------------------------------------- diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index 80ba477fd..e100ff8c8 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -425,8 +425,9 @@ BEGIN_DATADESC( CBasePlayer ) DEFINE_FIELD( m_flOldPlayerViewOffsetZ, FIELD_FLOAT ), DEFINE_FIELD( m_bPlayerUnderwater, FIELD_BOOLEAN ), DEFINE_FIELD( m_hViewEntity, FIELD_EHANDLE ), +#if defined(OPENMOD) DEFINE_FIELD(m_vecUseAngles, FIELD_VECTOR), - +#endif DEFINE_FIELD( m_hConstraintEntity, FIELD_EHANDLE ), DEFINE_FIELD( m_vecConstraintCenter, FIELD_VECTOR ), DEFINE_FIELD( m_flConstraintRadius, FIELD_FLOAT ), @@ -8144,8 +8145,9 @@ void CMovementSpeedMod::InputSpeedMod(inputdata_t &data) SendPropVector ( SENDINFO( m_vecBaseVelocity ), 32, SPROP_NOSCALE ), +#if defined(OPENMOD) SendPropVector(SENDINFO(m_vecUseAngles), 0, SPROP_NOSCALE), - +#endif SendPropEHandle ( SENDINFO( m_hConstraintEntity)), SendPropVector ( SENDINFO( m_vecConstraintCenter), 0, SPROP_NOSCALE ), SendPropFloat ( SENDINFO( m_flConstraintRadius ), 0, SPROP_NOSCALE ), diff --git a/src/game/server/player.h b/src/game/server/player.h index 937bc9602..9912cd0a2 100644 --- a/src/game/server/player.h +++ b/src/game/server/player.h @@ -1150,8 +1150,9 @@ class CBasePlayer : public CBaseCombatCharacter EHANDLE m_hViewEntity; +#if defined(OPENMOD) CNetworkQAngle(m_vecUseAngles); - +#endif // Movement constraints CNetworkHandle( CBaseEntity, m_hConstraintEntity ); CNetworkVector( m_vecConstraintCenter ); diff --git a/src/game/shared/basecombatweapon_shared.h b/src/game/shared/basecombatweapon_shared.h index 693d1264a..5e2409857 100644 --- a/src/game/shared/basecombatweapon_shared.h +++ b/src/game/shared/basecombatweapon_shared.h @@ -497,7 +497,9 @@ class CBaseCombatWeapon : public BASECOMBATWEAPON_DERIVED_FROM virtual bool ShouldDraw( void ); virtual bool ShouldDrawPickup( void ); virtual void HandleInput( void ) { return; }; - virtual bool OverrideViewAngles(void) { return false; };s +#ifdef OPENMOD + virtual bool OverrideViewAngles(void) { return false; }; +#endif // OPENMOD virtual void OverrideMouseInput( float *x, float *y ) { return; }; virtual int KeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ) { return 1; } virtual bool AddLookShift( void ) { return true; };