diff --git a/README.md b/README.md
index b39c0f19..a1198f08 100644
--- a/README.md
+++ b/README.md
@@ -132,6 +132,7 @@ This means that plugins that do binary code analysis (Orpheu for example) probab
| mp_randomspawn | 0 | 0 | 1 | Random player spawns
`0` disabled
`1` enabled
`NOTE`: Navigation `maps/.nav` file required |
| mp_playerid_showhealth | 1 | 0 | 2 | Player ID display mode.
`0` don't show health
`1` show health for teammates only (default CS behaviour)
`2` show health for all players |
| mp_playerid_field | 3 | 0 | 3 | Player ID field display mode.
`0` don't show additional information
`1` show team name
`2` show health percentage
`3` show both team name and health percentage |
+| mp_knockback | 170 | - | - | Knockback force applied to the victim when damaged by strong weapons (e.g. `AWP`, `AK47`).
Works only if not crouching, and not hit in the legs.
Set to `0` to disable. |
diff --git a/dist/game.cfg b/dist/game.cfg
index 70bd646b..f566ee9b 100644
--- a/dist/game.cfg
+++ b/dist/game.cfg
@@ -680,3 +680,10 @@ mp_playerid_showhealth "1"
//
// Default value: "3"
mp_playerid_field "3"
+
+// Knockback force applied to the victim when damaged by strong weapons (e.g. AWP, AK47).
+// Works only if not crouching, and not hit in the legs.
+// Set to "0" to disable.
+//
+// Default: "170"
+mp_knockback "170"
diff --git a/regamedll/dlls/API/CAPI_Impl.cpp b/regamedll/dlls/API/CAPI_Impl.cpp
index aebde38a..55da8ae3 100644
--- a/regamedll/dlls/API/CAPI_Impl.cpp
+++ b/regamedll/dlls/API/CAPI_Impl.cpp
@@ -337,6 +337,7 @@ GAMEHOOK_REGISTRY(CBasePlayer_PlayerDeathThink);
GAMEHOOK_REGISTRY(CBasePlayer_Observer_Think);
GAMEHOOK_REGISTRY(CBasePlayer_RemoveAllItems);
GAMEHOOK_REGISTRY(CBasePlayer_UpdateStatusBar);
+GAMEHOOK_REGISTRY(CBasePlayer_TakeDamageImpulse);
int CReGameApi::GetMajorVersion() {
return REGAMEDLL_API_VERSION_MAJOR;
diff --git a/regamedll/dlls/API/CAPI_Impl.h b/regamedll/dlls/API/CAPI_Impl.h
index a9c89e99..727fdf9e 100644
--- a/regamedll/dlls/API/CAPI_Impl.h
+++ b/regamedll/dlls/API/CAPI_Impl.h
@@ -753,6 +753,10 @@ typedef IHookChainRegistryClassImpl CReGameHookRegistry
typedef IHookChainClassImpl CReGameHook_CBasePlayer_UpdateStatusBar;
typedef IHookChainRegistryClassImpl CReGameHookRegistry_CBasePlayer_UpdateStatusBar;
+// CBasePlayer::TakeDamageImpulse hook
+typedef IHookChainClassImpl CReGameHook_CBasePlayer_TakeDamageImpulse;
+typedef IHookChainRegistryClassImpl CReGameHookRegistry_CBasePlayer_TakeDamageImpulse;
+
class CReGameHookchains: public IReGameHookchains {
public:
// CBasePlayer virtual
@@ -915,6 +919,7 @@ public:
CReGameHookRegistry_CBasePlayer_Observer_Think m_CBasePlayer_Observer_Think;
CReGameHookRegistry_CBasePlayer_RemoveAllItems m_CBasePlayer_RemoveAllItems;
CReGameHookRegistry_CBasePlayer_UpdateStatusBar m_CBasePlayer_UpdateStatusBar;
+ CReGameHookRegistry_CBasePlayer_TakeDamageImpulse m_CBasePlayer_TakeDamageImpulse;
public:
virtual IReGameHookRegistry_CBasePlayer_Spawn *CBasePlayer_Spawn();
@@ -1076,6 +1081,7 @@ public:
virtual IReGameHookRegistry_CBasePlayer_Observer_Think *CBasePlayer_Observer_Think();
virtual IReGameHookRegistry_CBasePlayer_RemoveAllItems *CBasePlayer_RemoveAllItems();
virtual IReGameHookRegistry_CBasePlayer_UpdateStatusBar *CBasePlayer_UpdateStatusBar();
+ virtual IReGameHookRegistry_CBasePlayer_TakeDamageImpulse *CBasePlayer_TakeDamageImpulse();
};
extern CReGameHookchains g_ReGameHookchains;
diff --git a/regamedll/dlls/API/CSPlayer.cpp b/regamedll/dlls/API/CSPlayer.cpp
index 2252b416..cab27a47 100644
--- a/regamedll/dlls/API/CSPlayer.cpp
+++ b/regamedll/dlls/API/CSPlayer.cpp
@@ -539,6 +539,11 @@ EXT_FUNC bool CCSPlayer::CheckActivityInGame()
return (fabs(deltaYaw) >= 0.1f && fabs(deltaPitch) >= 0.1f);
}
+EXT_FUNC void CCSPlayer::TakeDamageImpulse(CBasePlayer *pAttacker, float flKnockbackForce, float flVelModifier)
+{
+ BasePlayer()->TakeDamageImpulse(pAttacker, flKnockbackForce, flVelModifier);
+}
+
void CCSPlayer::ResetVars()
{
m_szModel[0] = '\0';
diff --git a/regamedll/dlls/game.cpp b/regamedll/dlls/game.cpp
index a022348e..2c6d9fbf 100644
--- a/regamedll/dlls/game.cpp
+++ b/regamedll/dlls/game.cpp
@@ -199,6 +199,8 @@ cvar_t randomspawn = { "mp_randomspawn", "0", FCVAR_SERVER, 0.0f, nu
cvar_t playerid_showhealth = { "mp_playerid_showhealth", "1", 0, 1.0f, nullptr };
cvar_t playerid_field = { "mp_playerid_field", "3", 0, 3.0f, nullptr };
+cvar_t knockback = { "mp_knockback", "170", 0, 170.0f, nullptr };
+
void GameDLL_Version_f()
{
if (Q_stricmp(CMD_ARGV(1), "version") != 0)
@@ -485,6 +487,8 @@ void EXT_FUNC GameDLLInit()
CVAR_REGISTER(&flymove_method);
+ CVAR_REGISTER(&knockback);
+
// print version
CONSOLE_ECHO("ReGameDLL version: " APP_VERSION "\n");
diff --git a/regamedll/dlls/game.h b/regamedll/dlls/game.h
index 95609f12..ecf1001c 100644
--- a/regamedll/dlls/game.h
+++ b/regamedll/dlls/game.h
@@ -216,6 +216,7 @@ extern cvar_t logkills;
extern cvar_t randomspawn;
extern cvar_t playerid_showhealth;
extern cvar_t playerid_field;
+extern cvar_t knockback;
#endif
diff --git a/regamedll/dlls/player.cpp b/regamedll/dlls/player.cpp
index 34b48223..67aa43e4 100644
--- a/regamedll/dlls/player.cpp
+++ b/regamedll/dlls/player.cpp
@@ -1233,7 +1233,7 @@ BOOL EXT_FUNC CBasePlayer::__API_HOOK(TakeDamage)(entvars_t *pevInflictor, entva
if (!ShouldDoLargeFlinch(m_LastHitGroup, iGunType))
{
- m_flVelocityModifier = 0.5f;
+ TakeDamageImpulse(pAttack, 0.0f, 0.5f);
if (m_LastHitGroup == HITGROUP_HEAD)
m_bHighDamage = (flDamage > 60);
@@ -1246,10 +1246,13 @@ BOOL EXT_FUNC CBasePlayer::__API_HOOK(TakeDamage)(entvars_t *pevInflictor, entva
{
if (pev->velocity.Length() < 300)
{
- Vector attack_velocity = (pev->origin - pAttack->pev->origin).Normalize() * 170;
- pev->velocity = pev->velocity + attack_velocity;
+#ifdef REGAMEDLL_ADD
+ float knockbackValue = knockback.value;
+#else
+ float knockbackValue = 170;
+#endif
- m_flVelocityModifier = 0.65f;
+ TakeDamageImpulse(pAttack, knockbackValue, 0.65f);
}
SetAnimation(PLAYER_LARGE_FLINCH);
@@ -10867,6 +10870,17 @@ bool CBasePlayer::Kill()
return true;
}
+LINK_HOOK_CLASS_VOID_CHAIN(CBasePlayer, TakeDamageImpulse, (CBasePlayer *pAttacker, float flKnockbackForce, float flVelModifier), pAttacker, flKnockbackForce, flVelModifier)
+
+void EXT_FUNC CBasePlayer::__API_HOOK(TakeDamageImpulse)(CBasePlayer *pAttacker, float flKnockbackForce, float flVelModifier)
+{
+ if (flKnockbackForce != 0.0f)
+ pev->velocity += (pev->origin - pAttacker->pev->origin).Normalize() * flKnockbackForce;
+
+ if (flVelModifier != 0.0f)
+ m_flVelocityModifier = flVelModifier;
+}
+
const usercmd_t *CBasePlayer::GetLastUserCommand() const
{
#ifdef REGAMEDLL_API
diff --git a/regamedll/dlls/player.h b/regamedll/dlls/player.h
index 78293ed9..f3ec649c 100644
--- a/regamedll/dlls/player.h
+++ b/regamedll/dlls/player.h
@@ -451,6 +451,7 @@ public:
void Observer_Think_OrigFunc();
void RemoveAllItems_OrigFunc(BOOL removeSuit);
void UpdateStatusBar_OrigFunc();
+ void TakeDamageImpulse_OrigFunc(CBasePlayer *pAttacker, float flKnockbackForce, float flVelModifier);
CCSPlayer *CSPlayer() const;
#endif // REGAMEDLL_API
@@ -659,6 +660,7 @@ public:
void UseEmpty();
void DropIdlePlayer(const char *reason);
bool Kill();
+ void TakeDamageImpulse(CBasePlayer *pAttacker, float flKnockbackForce, float flVelModifier);
// templates
template
diff --git a/regamedll/public/regamedll/API/CSPlayer.h b/regamedll/public/regamedll/API/CSPlayer.h
index 251cd6f5..3ead37a2 100644
--- a/regamedll/public/regamedll/API/CSPlayer.h
+++ b/regamedll/public/regamedll/API/CSPlayer.h
@@ -118,6 +118,7 @@ public:
virtual void OnSpawnEquip(bool addDefault = true, bool equipGame = true);
virtual void SetScoreboardAttributes(CBasePlayer *destination = nullptr);
virtual void Observer_FindNextPlayer(bool bReverse, const char *name = nullptr);
+ virtual void TakeDamageImpulse(CBasePlayer *pAttacker, float flKnockbackForce, float flVelModifier);
bool IsPlayerDominated(int iPlayerIndex) const;
void SetPlayerDominated(CBasePlayer *pPlayer, bool bDominated);
diff --git a/regamedll/public/regamedll/regamedll_api.h b/regamedll/public/regamedll/regamedll_api.h
index 6b9aadd7..fda245bc 100644
--- a/regamedll/public/regamedll/regamedll_api.h
+++ b/regamedll/public/regamedll/regamedll_api.h
@@ -38,7 +38,7 @@
#include
#define REGAMEDLL_API_VERSION_MAJOR 5
-#define REGAMEDLL_API_VERSION_MINOR 29
+#define REGAMEDLL_API_VERSION_MINOR 30
// CBasePlayer::Spawn hook
typedef IHookChainClass IReGameHook_CBasePlayer_Spawn;
@@ -632,6 +632,10 @@ typedef IHookChainRegistryClass IReGameHookRegist
typedef IHookChainClass IReGameHook_CBasePlayer_UpdateStatusBar;
typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayer_UpdateStatusBar;
+// CBasePlayer::TakeDamageImpulse hook
+typedef IHookChainClass IReGameHook_CBasePlayer_TakeDamageImpulse;
+typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayer_TakeDamageImpulse;
+
class IReGameHookchains {
public:
virtual ~IReGameHookchains() {}
@@ -795,6 +799,7 @@ public:
virtual IReGameHookRegistry_CBasePlayer_Observer_Think *CBasePlayer_Observer_Think() = 0;
virtual IReGameHookRegistry_CBasePlayer_RemoveAllItems *CBasePlayer_RemoveAllItems() = 0;
virtual IReGameHookRegistry_CBasePlayer_UpdateStatusBar *CBasePlayer_UpdateStatusBar() = 0;
+ virtual IReGameHookRegistry_CBasePlayer_TakeDamageImpulse *CBasePlayer_TakeDamageImpulse() = 0;
};
struct ReGameFuncs_t {
diff --git a/regamedll/version/version.h b/regamedll/version/version.h
index d3e8b9db..3838a2f8 100644
--- a/regamedll/version/version.h
+++ b/regamedll/version/version.h
@@ -6,5 +6,5 @@
#pragma once
#define VERSION_MAJOR 5
-#define VERSION_MINOR 29
+#define VERSION_MINOR 30
#define VERSION_MAINTENANCE 0