From 04a42672beea625d75cc1fcd3950e252fe19c6cc Mon Sep 17 00:00:00 2001 From: Roman Chistokhodov Date: Fri, 30 Jun 2023 17:47:13 +0300 Subject: [PATCH] Add player_speed and player_capabilities --- cl_dll/hl/hl_weapons.cpp | 2 + dlls/client.cpp | 1 + dlls/player.cpp | 158 +++++++++++++++++++++++++++++++++++++++ dlls/player.h | 9 +++ dlls/weapons_shared.cpp | 6 +- fgd/halflife.fgd | 41 ++++++++++ pm_shared/pm_shared.c | 4 + 7 files changed, 219 insertions(+), 2 deletions(-) diff --git a/cl_dll/hl/hl_weapons.cpp b/cl_dll/hl/hl_weapons.cpp index 568158e887..6928dd7d48 100644 --- a/cl_dll/hl/hl_weapons.cpp +++ b/cl_dll/hl/hl_weapons.cpp @@ -799,6 +799,8 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm player.m_pActiveItem = g_pWpns[from->client.m_iId]; } + player.m_suppressedCapabilities = from->client.vuser2[0]; + // Don't go firing anything if we have died. // Or if we don't have a weapon model deployed if( ( player.pev->deadflag != ( DEAD_DISCARDBODY + 1 ) ) && diff --git a/dlls/client.cpp b/dlls/client.cpp index 4b76458418..4314a0def4 100644 --- a/dlls/client.cpp +++ b/dlls/client.cpp @@ -1841,6 +1841,7 @@ void UpdateClientData( const struct edict_s *ent, int sendweapons, struct client } } } + cd->vuser2.x = pl->m_suppressedCapabilities; #endif } diff --git a/dlls/player.cpp b/dlls/player.cpp index b6a123db2d..f1a6df5990 100644 --- a/dlls/player.cpp +++ b/dlls/player.cpp @@ -128,6 +128,8 @@ TYPEDESCRIPTION CBasePlayer::m_playerSaveData[] = DEFINE_ARRAY(CBasePlayer, m_timeBasedDmgModifiers, FIELD_CHARACTER, CDMG_TIMEBASED), DEFINE_FIELD(CBasePlayer, m_settingsLoaded, FIELD_BOOLEAN), DEFINE_FIELD(CBasePlayer, m_buddha, FIELD_BOOLEAN), + DEFINE_FIELD(CBasePlayer, m_suppressedCapabilities, FIELD_INTEGER), + DEFINE_FIELD(CBasePlayer, m_maxSpeedFraction, FIELD_FLOAT), DEFINE_FIELD(CBasePlayer, m_loopedMp3, FIELD_STRING), @@ -1724,6 +1726,9 @@ void CBasePlayer::PlayerUse( void ) if( !( ( pev->button | m_afButtonPressed | m_afButtonReleased) & IN_USE ) ) return; + if (FBitSet(m_suppressedCapabilities, PLAYER_SUPRESS_USE)) + return; + // Hit Use on a train? if( m_afButtonPressed & IN_USE ) { @@ -2341,6 +2346,7 @@ void CBasePlayer::PreThink( void ) m_afButtonReleased = buttonsChanged & ( ~pev->button ); // The ones not down are "released" g_pGameRules->PlayerThink( this ); + pev->maxspeed = m_maxSpeedFraction * g_psv_maxspeed->value; if( g_fGameOver ) return; // intermission or finale @@ -3753,6 +3759,7 @@ int CBasePlayer::Restore( CRestore &restore ) g_engfuncs.pfnSetPhysicsKeyValue( edict(), "slj", "0" ); } + SetPhysicsKeyValues(); RenewItems(); #if CLIENT_WEAPONS @@ -3769,6 +3776,26 @@ int CBasePlayer::Restore( CRestore &restore ) return status; } +void CBasePlayer::SetPhysicsKeyValues() +{ + if( FBitSet(m_suppressedCapabilities, PLAYER_SUPRESS_JUMP) ) + { + g_engfuncs.pfnSetPhysicsKeyValue( edict(), "noj", "1" ); + } + else + { + g_engfuncs.pfnSetPhysicsKeyValue( edict(), "noj", "0" ); + } + if( FBitSet(m_suppressedCapabilities, PLAYER_SUPRESS_DUCK) ) + { + pev->iuser3 = 1; + } + else + { + pev->iuser3 = 0; + } +} + void CBasePlayer::SelectItem( const char *pstr ) { if( !pstr ) @@ -6128,6 +6155,137 @@ IMPLEMENT_SAVERESTORE( CPlayerHasWeapon, CPointEntity ) LINK_ENTITY_TO_CLASS( player_hasweapon, CPlayerHasWeapon ) + +enum +{ + PLAYER_ABILITY_DISABLE = -1, + PLAYER_ABILITY_NOCHANGE = 0, + PLAYER_ABILITY_ENABLE = 1, + PLAYER_ABILITY_TOGGLE = 2, + PLAYER_ABILITY_COPYINPUT = 3, +}; + +class CPlayerCapabilities : public CPointEntity +{ +public: + void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) + { + CBasePlayer* pPlayer = g_pGameRules->EffectivePlayer(pActivator); + if (!pPlayer) + return; + ConfigurePlayerCapability(pPlayer, PLAYER_SUPRESS_ATTACK, m_attackCapability, useType); + ConfigurePlayerCapability(pPlayer, PLAYER_SUPRESS_JUMP, m_jumpCapability, useType); + ConfigurePlayerCapability(pPlayer, PLAYER_SUPRESS_DUCK, m_duckCapability, useType); + ConfigurePlayerCapability(pPlayer, PLAYER_SUPRESS_USE, m_useCapability, useType); + + pPlayer->SetPhysicsKeyValues(); + } + + void KeyValue( KeyValueData *pkvd ) + { + if( FStrEq( pkvd->szKeyName, "attack_capability" ) ) + { + m_attackCapability = atoi( pkvd->szValue ); + pkvd->fHandled = TRUE; + } + else if( FStrEq( pkvd->szKeyName, "jump_capability" ) ) + { + m_jumpCapability = atoi( pkvd->szValue ); + pkvd->fHandled = TRUE; + } + else if( FStrEq( pkvd->szKeyName, "duck_capability" ) ) + { + m_duckCapability = atoi( pkvd->szValue ); + pkvd->fHandled = TRUE; + } + else if( FStrEq( pkvd->szKeyName, "use_capability" ) ) + { + m_useCapability = atoi( pkvd->szValue ); + pkvd->fHandled = TRUE; + } + else + CPointEntity::KeyValue(pkvd); + } + + virtual int Save( CSave &save ); + virtual int Restore( CRestore &restore ); + static TYPEDESCRIPTION m_SaveData[]; + +private: + void ConfigurePlayerCapability(CBasePlayer* pPlayer, int suppressCapability, short setting, USE_TYPE useType) + { + if (setting == PLAYER_ABILITY_COPYINPUT) + { + if (useType == USE_OFF) + setting = PLAYER_ABILITY_DISABLE; + else if (useType == USE_ON) + setting = PLAYER_ABILITY_ENABLE; + else + setting = PLAYER_ABILITY_TOGGLE; + } + + if (setting == PLAYER_ABILITY_DISABLE) + { + SetBits(pPlayer->m_suppressedCapabilities, suppressCapability); + } + else if (setting == PLAYER_ABILITY_ENABLE) + { + ClearBits(pPlayer->m_suppressedCapabilities, suppressCapability); + } + else if (setting == PLAYER_ABILITY_TOGGLE) + { + if (FBitSet(pPlayer->m_suppressedCapabilities, suppressCapability)) + ClearBits(pPlayer->m_suppressedCapabilities, suppressCapability); + else + SetBits(pPlayer->m_suppressedCapabilities, suppressCapability); + } + } + + short m_attackCapability; + short m_jumpCapability; + short m_duckCapability; + short m_useCapability; +}; + +LINK_ENTITY_TO_CLASS( player_capabilities, CPlayerCapabilities ) + +TYPEDESCRIPTION CPlayerCapabilities::m_SaveData[] = +{ + DEFINE_FIELD( CPlayerCapabilities, m_attackCapability, FIELD_SHORT ), + DEFINE_FIELD( CPlayerCapabilities, m_jumpCapability, FIELD_SHORT ), + DEFINE_FIELD( CPlayerCapabilities, m_duckCapability, FIELD_SHORT ), + DEFINE_FIELD( CPlayerCapabilities, m_useCapability, FIELD_SHORT ), +}; + +IMPLEMENT_SAVERESTORE( CPlayerCapabilities, CPointEntity ) + +class CPlayerSpeed : public CPointEntity +{ +public: + void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) + { + CBasePlayer* pPlayer = g_pGameRules->EffectivePlayer(pActivator); + if (!pPlayer) + return; + + pPlayer->m_maxSpeedFraction = pev->health; + } + + void KeyValue( KeyValueData *pkvd ) + { + if( FStrEq( pkvd->szKeyName, "maxspeed" ) ) + { + // pev->maxspeed is not saved by default. Use some other float variable + pev->health = atof( pkvd->szValue ); + pkvd->fHandled = TRUE; + } + else + CPointEntity::KeyValue(pkvd); + } +}; + +LINK_ENTITY_TO_CLASS( player_speed, CPlayerSpeed ) + #define SF_PLAYER_LOAD_SAVED_FREEZE 1 #define SF_PLAYER_LOAD_SAVED_WEAPONSTRIP 2 #define SF_PLAYER_LOAD_SAVED_RETURN_TO_MENU 128 diff --git a/dlls/player.h b/dlls/player.h index 91d31b8c4d..9430f9ef2d 100644 --- a/dlls/player.h +++ b/dlls/player.h @@ -107,6 +107,11 @@ enum sbar_data #define ARMOR_RATIO 0.2 // Armor Takes 80% of the damage #define ARMOR_BONUS 0.5 // Each Point of Armor is work 1/x points of health +#define PLAYER_SUPRESS_ATTACK (1<<0) +#define PLAYER_SUPRESS_JUMP (1<<1) +#define PLAYER_SUPRESS_DUCK (1<<2) +#define PLAYER_SUPRESS_USE (1<<5) + class CBasePlayer : public CBaseMonster { public: @@ -251,6 +256,7 @@ class CBasePlayer : public CBaseMonster virtual int Save( CSave &save ); virtual int Restore( CRestore &restore ); + void SetPhysicsKeyValues(); void RenewItems(void); void PackDeadPlayerItems( void ); void RemoveAllItems( int stripFlags ); @@ -474,6 +480,9 @@ class CBasePlayer : public CBaseMonster short m_iSatchelControl; short m_iPreferNewGrenadePhysics; + int m_suppressedCapabilities; + float m_maxSpeedFraction; + void SetLoopedMp3(string_t loopedMp3); string_t m_loopedMp3; }; diff --git a/dlls/weapons_shared.cpp b/dlls/weapons_shared.cpp index e629e7e790..4429dbe9bd 100644 --- a/dlls/weapons_shared.cpp +++ b/dlls/weapons_shared.cpp @@ -110,7 +110,8 @@ void CBasePlayerWeapon::ItemPostFrame( void ) m_fFireOnEmpty = TRUE; } - SecondaryAttack(); + if (!FBitSet(m_pPlayer->m_suppressedCapabilities, PLAYER_SUPRESS_ATTACK)) + SecondaryAttack(); m_pPlayer->pev->button &= ~IN_ATTACK2; } else if( ( m_pPlayer->pev->button & IN_ATTACK ) && CanAttack( m_flNextPrimaryAttack, gpGlobals->time, UseDecrement() ) ) @@ -120,7 +121,8 @@ void CBasePlayerWeapon::ItemPostFrame( void ) m_fFireOnEmpty = TRUE; } - PrimaryAttack(); + if (!FBitSet(m_pPlayer->m_suppressedCapabilities, PLAYER_SUPRESS_ATTACK)) + PrimaryAttack(); } else if( m_pPlayer->pev->button & IN_RELOAD && iMaxClip() != WEAPON_NOCLIP && !m_fInReload ) { diff --git a/fgd/halflife.fgd b/fgd/halflife.fgd index 2b5248871e..efa568384c 100644 --- a/fgd/halflife.fgd +++ b/fgd/halflife.fgd @@ -7158,6 +7158,42 @@ ] ] +@PointClass base(Targetname) = player_capabilities : "Enable/disable certain player's capabilities" +[ + attack_capability(choices) : "Attack capability" = + [ + -1 : "Off" + 0 : "No change" + 1 : "On" + 2 : "Toggle" + 3 : "Copy use input" + ] + jump_capability(choices) : "Jump capability" = + [ + -1 : "Off" + 0 : "No change" + 1 : "On" + 2 : "Toggle" + 3 : "Copy use input" + ] + duck_capability(choices) : "Duck capability" = + [ + -1 : "Off" + 0 : "No change" + 1 : "On" + 2 : "Toggle" + 3 : "Copy use input" + ] + use_capability(choices) : "Use capability" = + [ + -1 : "Off" + 0 : "No change" + 1 : "On" + 2 : "Toggle" + 3 : "Copy use input" + ] +] + @PointClass base(Targetname) color(72 96 128) = player_hasitem : "Check if player has a specific item" [ item_type(choices) : "Item Type" : 0 = @@ -7196,6 +7232,11 @@ ] ] +@PointClass base(Targetname) = player_speed : "Configure player's speed" +[ + maxspeed(string) : "Maxspeed multiplier [0=reset]" : 0 +] + @PointClass base(Targetname) size(-16 -16 -16, 16 16 16) = player_weaponstrip : "Strips player's weapons and items" [ spawnflags(Flags) = diff --git a/pm_shared/pm_shared.c b/pm_shared/pm_shared.c index c0c8d67e0e..44bd4323f9 100644 --- a/pm_shared/pm_shared.c +++ b/pm_shared/pm_shared.c @@ -2525,6 +2525,10 @@ void PM_Jump( void ) return; } + // check if jump is disabled + if (atoi( pmove->PM_Info_ValueForKey( pmove->physinfo, "noj" ) ) == 1) + return; + if( pmove->flags & FL_FROZEN ) return;