Skip to content

Commit

Permalink
Add an extended player's DeathMsg message (#858)
Browse files Browse the repository at this point in the history
* Implemented rarity of kill and assist for extended user message DeathMsg
* Add hookchain CGameRules::SendDeathMessage
* Add domination and revenge
  • Loading branch information
s1lentq authored Sep 28, 2023
1 parent 67e7d87 commit 108db28
Show file tree
Hide file tree
Showing 22 changed files with 809 additions and 145 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,9 @@ This means that plugins that do binary code analysis (Orpheu for example) probab
| mp_give_c4_frags | 3 | - | - | How many bonuses (frags) will get the player who defused or exploded the bomb. |
| mp_hostages_rescued_ratio | 1.0 | 0.0 | 1.0 | Ratio of hostages rescued to win the round. |
| mp_legacy_vehicle_block | 1 | 0 | 1 | Legacy func_vehicle behavior when blocked by another entity.<br/>`0` New behavior <br/>`1` Legacy behavior |
| mp_dying_time | 3.0 | 0.0 | - | Time for switch to free observing after death.<br/>`0` - disable spectating around death.<br/>`>0.00001` - time delay to start spectate.<br/>`NOTE`: The countdown starts when the player’s death animation is finished.|
| mp_dying_time | 3.0 | 0.0 | - | Time for switch to free observing after death.<br/>`0` - disable spectating around death.<br/>`>0.00001` - time delay to start spectate.<br/>`NOTE`: The countdown starts when the player’s death animation is finished. |
| mp_deathmsg_flags | 7 | 0 | 7 | Sets a bitsum for extra information in the player's death message.<br/>`0` disabled<br/>`1` position where the victim died<br/>`2` index of the assistant who helped the attacker kill the victim<br/>`4` rarity classification bits, e.g., `blinkill`, `noscope`, `penetrated`, etc. |
| mp_assist_damage_threshold | 40 | 0 | 100 | Sets the percentage of damage needed to score an assist. |
</details>

## How to install zBot for CS 1.6?
Expand Down
16 changes: 16 additions & 0 deletions dist/game.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -537,3 +537,19 @@ mp_legacy_vehicle_block "1"
//
// Default value: "3.0"
mp_dying_time "3.0"
// Sets a bitsum for extra information in the player's death message
//
// 1 Position where the victim died
// 2 Index of the assistant who helped the attacker kill the victim
// 4 Rarity classification bits, e.g., blinkill, noscope, penetrated, etc
//
// Set to "0" to send no extra information about death
//
// Default value: "7"
mp_deathmsg_flags "7"

// Sets the percentage of damage needed to score an assist
//
// Default value: "40"
mp_assist_damage_threshold "40"
21 changes: 11 additions & 10 deletions regamedll/dlls/API/CAPI_Impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,37 +61,37 @@ void EXT_FUNC AddMultiDamage_api(entvars_t *pevInflictor, CBaseEntity *pEntity,
AddMultiDamage(pevInflictor, pEntity, flDamage, bitsDamageType);
}

int EXT_FUNC Cmd_Argc_api()
int EXT_FUNC Cmd_Argc_api()
{
return CMD_ARGC_();
}

const char *EXT_FUNC Cmd_Argv_api(int i)
const char *EXT_FUNC Cmd_Argv_api(int i)
{
return CMD_ARGV_(i);
}

CGrenade *EXT_FUNC PlantBomb_api(entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity)
CGrenade *EXT_FUNC PlantBomb_api(entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity)
{
return CGrenade::ShootSatchelCharge(pevOwner, vecStart, vecVelocity);
}

CGib *EXT_FUNC SpawnHeadGib_api(entvars_t *pevVictim)
CGib *EXT_FUNC SpawnHeadGib_api(entvars_t *pevVictim)
{
return CGib::SpawnHeadGib(pevVictim);
}

void EXT_FUNC SpawnRandomGibs_api(entvars_t *pevVictim, int cGibs, int human)
void EXT_FUNC SpawnRandomGibs_api(entvars_t *pevVictim, int cGibs, int human)
{
CGib::SpawnRandomGibs(pevVictim, cGibs, human);
}

void EXT_FUNC UTIL_RestartOther_api(const char *szClassname)
void EXT_FUNC UTIL_RestartOther_api(const char *szClassname)
{
UTIL_RestartOther(szClassname);
}

void EXT_FUNC UTIL_ResetEntities_api()
void EXT_FUNC UTIL_ResetEntities_api()
{
UTIL_ResetEntities();
}
Expand Down Expand Up @@ -130,11 +130,11 @@ CGrenade *EXT_FUNC SpawnGrenade_api(WeaponIdType weaponId, entvars_t *pevOwner,
{
switch (weaponId)
{
case WEAPON_HEGRENADE:
case WEAPON_HEGRENADE:
return CGrenade::ShootTimed2(pevOwner, vecSrc, vecThrow, time, iTeam, usEvent);
case WEAPON_FLASHBANG:
case WEAPON_FLASHBANG:
return CGrenade::ShootTimed(pevOwner, vecSrc, vecThrow, time);
case WEAPON_SMOKEGRENADE:
case WEAPON_SMOKEGRENADE:
return CGrenade::ShootSmokeGrenade(pevOwner, vecSrc, vecThrow, time, usEvent);
case WEAPON_C4:
return CGrenade::ShootSatchelCharge(pevOwner, vecSrc, vecThrow);
Expand Down Expand Up @@ -331,6 +331,7 @@ GAMEHOOK_REGISTRY(CBasePlayer_EntSelectSpawnPoint);
GAMEHOOK_REGISTRY(CBasePlayerWeapon_ItemPostFrame);
GAMEHOOK_REGISTRY(CBasePlayerWeapon_KickBack);
GAMEHOOK_REGISTRY(CBasePlayerWeapon_SendWeaponAnim);
GAMEHOOK_REGISTRY(CSGameRules_SendDeathMessage);

int CReGameApi::GetMajorVersion() {
return REGAMEDLL_API_VERSION_MAJOR;
Expand Down
8 changes: 7 additions & 1 deletion regamedll/dlls/API/CAPI_Impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,10 @@ typedef IHookChainRegistryClassEmptyImpl<BOOL, class CHalfLifeMultiplay, int, in
typedef IHookChainClassImpl<void, class CHalfLifeMultiplay, CBasePlayer *, CBasePlayerItem *> CReGameHook_CSGameRules_PlayerGotWeapon;
typedef IHookChainRegistryClassEmptyImpl<void, class CHalfLifeMultiplay, CBasePlayer *, CBasePlayerItem *> CReGameHookRegistry_CSGameRules_PlayerGotWeapon;

// CHalfLifeMultiplay::SendDeathMessage hook
typedef IHookChainClassImpl<void, class CHalfLifeMultiplay, CBaseEntity *, CBasePlayer *, CBasePlayer *, entvars_t *, const char *, int, int> CReGameHook_CSGameRules_SendDeathMessage;
typedef IHookChainRegistryClassEmptyImpl<void, class CHalfLifeMultiplay, CBaseEntity *, CBasePlayer *, CBasePlayer *, entvars_t *, const char *, int, int> CReGameHookRegistry_CSGameRules_SendDeathMessage;

// CBotManager::OnEvent hook
typedef IHookChainClassImpl<void, CBotManager, GameEventType, CBaseEntity *, CBaseEntity *> CReGameHook_CBotManager_OnEvent;
typedef IHookChainRegistryClassEmptyImpl<void, CBotManager, GameEventType, CBaseEntity*, CBaseEntity*> CReGameHookRegistry_CBotManager_OnEvent;
Expand Down Expand Up @@ -865,7 +869,7 @@ class CReGameHookchains: public IReGameHookchains {
CReGameHookRegistry_CBasePlayer_Pain m_CBasePlayer_Pain;
CReGameHookRegistry_CBasePlayer_DeathSound m_CBasePlayer_DeathSound;
CReGameHookRegistry_CBasePlayer_JoiningThink m_CBasePlayer_JoiningThink;

CReGameHookRegistry_FreeGameRules m_FreeGameRules;
CReGameHookRegistry_PM_LadderMove m_PM_LadderMove;
CReGameHookRegistry_PM_WaterJump m_PM_WaterJump;
Expand All @@ -889,6 +893,7 @@ class CReGameHookchains: public IReGameHookchains {
CReGameHookRegistry_CBasePlayerWeapon_ItemPostFrame m_CBasePlayerWeapon_ItemPostFrame;
CReGameHookRegistry_CBasePlayerWeapon_KickBack m_CBasePlayerWeapon_KickBack;
CReGameHookRegistry_CBasePlayerWeapon_SendWeaponAnim m_CBasePlayerWeapon_SendWeaponAnim;
CReGameHookRegistry_CSGameRules_SendDeathMessage m_CSGameRules_SendDeathMessage;

public:
virtual IReGameHookRegistry_CBasePlayer_Spawn *CBasePlayer_Spawn();
Expand Down Expand Up @@ -1044,6 +1049,7 @@ class CReGameHookchains: public IReGameHookchains {
virtual IReGameHookRegistry_CBasePlayerWeapon_ItemPostFrame *CBasePlayerWeapon_ItemPostFrame();
virtual IReGameHookRegistry_CBasePlayerWeapon_KickBack *CBasePlayerWeapon_KickBack();
virtual IReGameHookRegistry_CBasePlayerWeapon_SendWeaponAnim *CBasePlayerWeapon_SendWeaponAnim();
virtual IReGameHookRegistry_CSGameRules_SendDeathMessage *CSGameRules_SendDeathMessage();
};

extern CReGameHookchains g_ReGameHookchains;
Expand Down
42 changes: 42 additions & 0 deletions regamedll/dlls/API/CSPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -550,10 +550,22 @@ void CCSPlayer::ResetVars()
m_bSpawnProtectionEffects = false;
}

// Resets all stats
void CCSPlayer::ResetAllStats()
{
// Resets the kill history for this player
for (int i = 0; i < MAX_CLIENTS; i++)
{
m_iNumKilledByUnanswered[i] = 0;
m_bPlayerDominated[i] = false;
}
}

void CCSPlayer::OnSpawn()
{
m_bGameForcingRespawn = false;
m_flRespawnPending = 0.0f;
m_DamageList.Clear();
}

void CCSPlayer::OnKilled()
Expand All @@ -571,3 +583,33 @@ void CCSPlayer::OnKilled()
}
#endif
}

void CCSPlayer::OnConnect()
{
ResetVars();
m_iUserID = GETPLAYERUSERID(BasePlayer()->edict());
}

// Remember this amount of damage that we dealt for stats
void CCSPlayer::RecordDamage(CBasePlayer *pAttacker, float flDamage, float flFlashDurationTime)
{
if (!pAttacker || !pAttacker->IsPlayer())
return;

int attackerIndex = pAttacker->entindex() - 1;
if (attackerIndex < 0 || attackerIndex >= MAX_CLIENTS)
return;

CCSPlayer *pCSAttacker = pAttacker->CSPlayer();

// Accumulate damage
CDamageRecord_t &record = m_DamageList[attackerIndex];
if (record.flDamage > 0 && record.userId != pCSAttacker->m_iUserID)
record.flDamage = 0; // reset damage if attacker became another client

record.flDamage += flDamage;
record.userId = pCSAttacker->m_iUserID;

if (flFlashDurationTime > 0)
record.flFlashDurationTime = gpGlobals->time + flFlashDurationTime;
}
6 changes: 5 additions & 1 deletion regamedll/dlls/cbase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1242,7 +1242,7 @@ bool EXT_FUNC IsPenetrableEntity_default(Vector &vecSrc, Vector &vecEnd, entvars


LINK_HOOK_CLASS_CHAIN(VectorRef, CBaseEntity, FireBullets3, (VectorRef vecSrc, VectorRef vecDirShooting, float vecSpread, float flDistance, int iPenetration, int iBulletType, int iDamage, float flRangeModifier, entvars_t *pevAttacker, bool bPistol, int shared_rand), vecSrc, vecDirShooting, vecSpread, flDistance, iPenetration, iBulletType, iDamage, flRangeModifier, pevAttacker, bPistol, shared_rand)

// Go to the trouble of combining multiple pellets into a single damage call.
// This version is used by Players, uses the random seed generator to sync client and server side shots.
VectorRef CBaseEntity::__API_HOOK(FireBullets3)(VectorRef vecSrc, VectorRef vecDirShooting, float vecSpread, float flDistance, int iPenetration, int iBulletType, int iDamage, float flRangeModifier, entvars_t *pevAttacker, bool bPistol, int shared_rand)
Expand Down Expand Up @@ -1340,6 +1340,7 @@ VectorRef CBaseEntity::__API_HOOK(FireBullets3)(VectorRef vecSrc, VectorRef vecD

float flDamageModifier = 0.5;

int iStartPenetration = iPenetration;
while (iPenetration != 0)
{
ClearMultiDamage();
Expand Down Expand Up @@ -1400,9 +1401,11 @@ VectorRef CBaseEntity::__API_HOOK(FireBullets3)(VectorRef vecSrc, VectorRef vecD
default:
break;
}

if (tr.flFraction != 1.0f)
{
CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit);
int iPenetrationCur = iPenetration;
iPenetration--;

flCurrentDistance = tr.flFraction * flDistance;
Expand Down Expand Up @@ -1459,6 +1462,7 @@ VectorRef CBaseEntity::__API_HOOK(FireBullets3)(VectorRef vecSrc, VectorRef vecD
flDistance = (flDistance - flCurrentDistance) * flDistanceModifier;
vecEnd = vecSrc + (vecDir * flDistance);

pEntity->SetDmgPenetrationLevel(iStartPenetration - iPenetrationCur);
pEntity->TraceAttack(pevAttacker, iCurrentDamage, vecDir, &tr, (DMG_BULLET | DMG_NEVERGIB));
iCurrentDamage *= flDamageModifier;
}
Expand Down
4 changes: 4 additions & 0 deletions regamedll/dlls/cbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,10 @@ class CBaseEntity {
void SetBlocked(void (T::*pfn)(CBaseEntity *pOther));
void SetBlocked(std::nullptr_t);

void SetDmgPenetrationLevel(int iPenetrationLevel);
void ResetDmgPenetrationLevel();
int GetDmgPenetrationLevel() const;

#ifdef REGAMEDLL_API
CCSEntity *m_pEntity;
CCSEntity *CSEntity() const;
Expand Down
2 changes: 1 addition & 1 deletion regamedll/dlls/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,7 @@ void EXT_FUNC ClientPutInServer(edict_t *pEntity)
}

#ifdef REGAMEDLL_API
pPlayer->CSPlayer()->ResetVars();
pPlayer->CSPlayer()->OnConnect();
#endif

UTIL_ClientPrintAll(HUD_PRINTNOTIFY, "#Game_connected", (sName[0] != '\0') ? sName : "<unconnected>");
Expand Down
18 changes: 15 additions & 3 deletions regamedll/dlls/combat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,23 @@ void PlayerBlind(CBasePlayer *pPlayer, entvars_t *pevInflictor, entvars_t *pevAt
}
}

pPlayer->Blind(fadeTime * 0.33, fadeHold, fadeTime, alpha);
float flDurationTime = fadeTime * 0.33;
pPlayer->Blind(flDurationTime, fadeHold, fadeTime, alpha);

if (TheBots)
{
TheBots->OnEvent(EVENT_PLAYER_BLINDED_BY_FLASHBANG, pPlayer);
}

#if defined(REGAMEDLL_API) && defined(REGAMEDLL_ADD)
float flAdjustedDamage;
if (alpha > 200)
flAdjustedDamage = fadeTime / 3;
else
flAdjustedDamage = fadeTime / 1.75;

pPlayer->CSPlayer()->RecordDamage(CBasePlayer::Instance(pevAttacker), flAdjustedDamage * 16.0f, flDurationTime);
#endif
}

void RadiusFlash_TraceLine_hook(CBasePlayer *pPlayer, entvars_t *pevInflictor, entvars_t *pevAttacker, Vector &vecSrc, Vector &vecSpot, TraceResult *tr)
Expand Down Expand Up @@ -101,7 +112,7 @@ void RadiusFlash(Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker,
if (pPlayer->pev == pevAttacker || g_pGameRules->PlayerRelationship(pPlayer, CBaseEntity::Instance(pevAttacker)) == GR_TEAMMATE)
continue;
break;
}
}
#endif
if (tr.fStartSolid)
{
Expand All @@ -110,7 +121,6 @@ void RadiusFlash(Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker,
}

flAdjustedDamage = flDamage - (vecSrc - tr.vecEndPos).Length() * falloff;

if (flAdjustedDamage < 0)
flAdjustedDamage = 0;

Expand Down Expand Up @@ -303,6 +313,8 @@ void RadiusDamage(Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker

if (tr.flFraction != 1.0f)
flAdjustedDamage = 0.0f;
else
pEntity->SetDmgPenetrationLevel(1);
}
#endif
}
Expand Down
4 changes: 4 additions & 0 deletions regamedll/dlls/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ cvar_t sv_autobunnyhopping = { "sv_autobunnyhopping", "0", 0, 0.0f
cvar_t sv_enablebunnyhopping = { "sv_enablebunnyhopping", "0", 0, 0.0f, nullptr };
cvar_t plant_c4_anywhere = { "mp_plant_c4_anywhere", "0", 0, 0.0f, nullptr };
cvar_t give_c4_frags = { "mp_give_c4_frags", "3", 0, 3.0f, nullptr };
cvar_t deathmsg_flags = { "mp_deathmsg_flags", "7", 0, 7.0f, nullptr };
cvar_t assist_damage_threshold = { "mp_assist_damage_threshold", "40", 0, 40.0f, nullptr };

cvar_t hostages_rescued_ratio = { "mp_hostages_rescued_ratio", "1.0", 0, 1.0f, nullptr };

Expand Down Expand Up @@ -423,6 +425,8 @@ void EXT_FUNC GameDLLInit()
CVAR_REGISTER(&legacy_vehicle_block);

CVAR_REGISTER(&dying_time);
CVAR_REGISTER(&deathmsg_flags);
CVAR_REGISTER(&assist_damage_threshold);

// print version
CONSOLE_ECHO("ReGameDLL version: " APP_VERSION "\n");
Expand Down
2 changes: 2 additions & 0 deletions regamedll/dlls/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ extern cvar_t give_c4_frags;
extern cvar_t hostages_rescued_ratio;
extern cvar_t legacy_vehicle_block;
extern cvar_t dying_time;
extern cvar_t deathmsg_flags;
extern cvar_t assist_damage_threshold;

#endif

Expand Down
39 changes: 39 additions & 0 deletions regamedll/dlls/gamerules.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,40 @@ enum
GR_NEUTRAL,
};

// The number of times you must kill a given player to be dominating them
// Should always be more than 1
const int CS_KILLS_FOR_DOMINATION = 4;

enum DeathMessageFlags
{
// float[3]
// Position where the victim died
PLAYERDEATH_POSITION = 0x001,

// byte
// Index of the assistant who helped the attacker kill the victim
PLAYERDEATH_ASSISTANT = 0x002,

// short
// Rarity classification bitsums
// 0x001 - Attacker was blind
// 0x002 - Attacker killed victim from sniper rifle without scope
// 0x004 - Attacker killed victim through walls
PLAYERDEATH_KILLRARITY = 0x004
};

enum KillRarity
{
KILLRARITY_HEADSHOT = 0x001, // The killer player kills the victim with a headshot
KILLRARITY_KILLER_BLIND = 0x002, // The killer player was blind
KILLRARITY_NOSCOPE = 0x004, // The killer player kills the victim with a sniper rifle with no scope
KILLRARITY_PENETRATED = 0x008, // The killer player kills the victim through walls
KILLRARITY_THROUGH_SMOKE = 0x010, // The killer player kills the victim through smoke
KILLRARITY_ASSIST_FLASH = 0x020, // The killer player kills the victim with an assistant flashbang grenade
KILLRARITY_DOMINATION = 0x040, // The killer player dominates the victim
KILLRARITY_REVENGE = 0x080 // The killer player got revenge on the victim
};

class CItem;

class CGameRules
Expand Down Expand Up @@ -574,6 +608,7 @@ class CHalfLifeMultiplay: public CGameRules
BOOL TeamFull_OrigFunc(int team_id);
BOOL TeamStacked_OrigFunc(int newTeam_id, int curTeam_id);
void PlayerGotWeapon_OrigFunc(CBasePlayer *pPlayer, CBasePlayerItem *pWeapon);
void SendDeathMessage_OrigFunc(CBaseEntity *pKiller, CBasePlayer *pVictim, CBasePlayer *pAssister, entvars_t *pevInflictor, const char *killerWeaponName, int iDeathMessageFlags, int iRarityOfKill);
#endif

public:
Expand Down Expand Up @@ -698,6 +733,10 @@ class CHalfLifeMultiplay: public CGameRules
VFUNC bool HasRoundTimeExpired();
VFUNC bool IsBombPlanted();

void SendDeathMessage(CBaseEntity *pKiller, CBasePlayer *pVictim, CBasePlayer *pAssister, entvars_t *pevInflictor, const char *killerWeaponName, int iDeathMessageFlags, int iRarityOfKill);
int GetRarityOfKill(CBaseEntity *pKiller, CBasePlayer *pVictim, CBasePlayer *pAssister, const char *killerWeaponName, bool bFlashAssist);
CBasePlayer *CheckAssistsToKill(CBaseEntity *pKiller, CBasePlayer *pVictim, bool &bFlashAssist);

private:
void MarkLivingPlayersOnTeamAsNotReceivingMoneyNextRound(int iTeam);

Expand Down
Loading

0 comments on commit 108db28

Please sign in to comment.