diff --git a/reapi/extra/amxmodx/scripting/include/cssdk_const.inc b/reapi/extra/amxmodx/scripting/include/cssdk_const.inc index 0f91158..821bbe9 100644 --- a/reapi/extra/amxmodx/scripting/include/cssdk_const.inc +++ b/reapi/extra/amxmodx/scripting/include/cssdk_const.inc @@ -1550,4 +1550,36 @@ enum GR_ENEMY, GR_ALLY, GR_NEUTRAL, -}; \ No newline at end of file +}; + +// Flags for specifying extra info about player death +enum DeathMessageFlags +{ + // float[3] + // Position where the victim was killed by the enemy + PLAYERDEATH_POSITION = 0x001, + + // byte + // Index of the assistant who helped the attacker kill the victim + PLAYERDEATH_ASSISTANT = 0x002, + + // short + // Bitsum classification for the rarity of the kill + // See enum KillRarity for details + PLAYERDEATH_KILLRARITY = 0x004 +}; + +// Classifying various player kill methods in the game +enum KillRarity +{ + KILLRARITY_HEADSHOT = 0x001, // Headshot + KILLRARITY_KILLER_BLIND = 0x002, // Killer was blind + KILLRARITY_NOSCOPE = 0x004, // No-scope sniper rifle kill + KILLRARITY_PENETRATED = 0x008, // Penetrated kill (through walls) + KILLRARITY_THRUSMOKE = 0x010, // Smoke grenade penetration kill (bullets went through smoke) + KILLRARITY_ASSISTEDFLASH = 0x020, // Assister helped with a flash + KILLRARITY_DOMINATION_BEGAN = 0x040, // Killer player began dominating the victim (NOTE: this flag is set once) + KILLRARITY_DOMINATION = 0x080, // Continues domination by the killer + KILLRARITY_REVENGE = 0x100, // Revenge by the killer + KILLRARITY_INAIR = 0x200 // Killer was in the air (skill to deal with high inaccuracy) +}; diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc index 454ff8c..013eb5e 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc @@ -1204,4 +1204,20 @@ native rg_death_notice(const pVictim, const pKiller, const pevInflictor); * * @return Match player relationship, see GR_* constants in cssdk_const.inc */ -native rg_player_relationship(const player, const target); \ No newline at end of file +native rg_player_relationship(const player, const target); + +/* +* Sends death messages to all players, including info about the killer, victim, weapon used, +* extra death flags, death position, assistant, and kill rarity using the CHalfLifeMultiplay::SendDeathMessage function. +* +* @param pKiller Killer index (if any). +* @param pVictim Victim index. +* @param pAssister Assisting player index (if any). +* @param pevInflictor Inflictor entity. 0 = world +* @param killerWeaponName The name of the weapon used by the killer. +* @param iDeathMessageFlags Flags indicating extra death message info, see DeathMessageFlags enum in cssdk_const.inc +* @param iRarityOfKill An bitsums representing the rarity classification of the kill, see KillRarity enum in cssdk_const.inc +* +* @noreturn +*/ +native rg_send_death_message(const pKiller, const pVictim, const pAssister, const pevInflictor, const killerWeaponName[], const DeathMessageFlags:iDeathMessageFlags, const KillRarity:iRarityOfKill); diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc index b623062..30c0f55 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc @@ -1252,6 +1252,14 @@ enum GamedllFunc_CSGameRules * Params: (const pPlayer, const pWeapon) */ RG_CSGameRules_PlayerGotWeapon, + + /* + * Description: Called when a player is killed, sends death messages to all players, including info about the killer, victim, weapon used, + * extra death flags, death position, assistant, and kill rarity + * Return type: void + * Params: (const pKiller, const pVictim, const pAssister, const pevInflictor, const killerWeaponName[], const DeathMessageFlags:iDeathMessageFlags, const KillRarity:iRarityOfKill) + */ + RG_CSGameRules_SendDeathMessage, }; /** diff --git a/reapi/include/cssdk/dlls/gamerules.h b/reapi/include/cssdk/dlls/gamerules.h index d0781be..5bb125d 100644 --- a/reapi/include/cssdk/dlls/gamerules.h +++ b/reapi/include/cssdk/dlls/gamerules.h @@ -553,6 +553,8 @@ public: virtual bool HasRoundTimeExpired() = 0; virtual bool IsBombPlanted() = 0; + virtual void SendDeathMessage(CBaseEntity *pKiller, CBasePlayer *pVictim, CBasePlayer *pAssister, entvars_t *pevInflictor, const char *killerWeaponName, int iDeathMessageFlags, int iRarityOfKill) = 0; + public: bool ShouldSkipShowMenu() const { return m_bSkipShowMenu; } void MarkShowMenuSkipped() { m_bSkipShowMenu = false; } diff --git a/reapi/src/hook_callback.cpp b/reapi/src/hook_callback.cpp index 217990e..06e0900 100644 --- a/reapi/src/hook_callback.cpp +++ b/reapi/src/hook_callback.cpp @@ -1740,6 +1740,16 @@ void CBasePlayer_RemoveAllItems(IReGameHook_CBasePlayer_RemoveAllItems *chain, C callVoidForward(RG_CBasePlayer_RemoveAllItems, original, indexOfEdict(pthis->pev), removeSuit); } +void CSGameRules_SendDeathMessage(IReGameHook_CSGameRules_SendDeathMessage *chain, CBaseEntity *pKiller, CBasePlayer *pVictim, CBasePlayer *pAssister, entvars_t *pevInflictor, const char *killerWeaponName, int iDeathMessageFlags, int iRarityOfKill) +{ + auto original = [chain](int _pKiller, int _pVictim, int _pAssister, int _pevInflictor, const char *_killerWeaponName, int _iDeathMessageFlags, int _iRarityOfKill) + { + chain->callNext(getPrivate(_pKiller), getPrivate(_pVictim), getPrivate(_pAssister), PEV(_pevInflictor), _killerWeaponName, _iDeathMessageFlags, _iRarityOfKill); + }; + + callVoidForward(RG_CSGameRules_SendDeathMessage, original, indexOfPDataAmx(pKiller), indexOfEdict(pVictim->pev), indexOfPDataAmx(pAssister), indexOfEdictAmx(pevInflictor), killerWeaponName, iDeathMessageFlags, iRarityOfKill); +} + /* * VTC functions */ diff --git a/reapi/src/hook_callback.h b/reapi/src/hook_callback.h index 3c64071..8bdc9c7 100644 --- a/reapi/src/hook_callback.h +++ b/reapi/src/hook_callback.h @@ -561,6 +561,7 @@ void CBasePlayerWeapon_SendWeaponAnim(IReGameHook_CBasePlayerWeapon_SendWeaponAn void CBasePlayer_PlayerDeathThink(IReGameHook_CBasePlayer_PlayerDeathThink *chain, CBasePlayer *pthis); void CBasePlayer_Observer_Think(IReGameHook_CBasePlayer_Observer_Think *chain, CBasePlayer *pthis); void CBasePlayer_RemoveAllItems(IReGameHook_CBasePlayer_RemoveAllItems *chain, CBasePlayer *pthis, BOOL removeSuit); +void CSGameRules_SendDeathMessage(IReGameHook_CSGameRules_SendDeathMessage *chain, CBaseEntity *pKiller, CBasePlayer *pVictim, CBasePlayer *pAssister, entvars_t *pevInflictor, const char *killerWeaponName, int iDeathMessageFlags, int iRarityOfKill); /* * VTC functions diff --git a/reapi/src/hook_list.cpp b/reapi/src/hook_list.cpp index cf38ad9..26e054d 100644 --- a/reapi/src/hook_list.cpp +++ b/reapi/src/hook_list.cpp @@ -247,6 +247,7 @@ hook_t hooklist_gamerules[] = { DLL(CSGameRules_TeamFull), DLL(CSGameRules_TeamStacked), DLL(CSGameRules_PlayerGotWeapon), + DLL(CSGameRules_SendDeathMessage), }; hook_t hooklist_grenade[] = { diff --git a/reapi/src/hook_list.h b/reapi/src/hook_list.h index cbd2f7d..02cabe3 100644 --- a/reapi/src/hook_list.h +++ b/reapi/src/hook_list.h @@ -306,6 +306,7 @@ enum GamedllFunc_CSGameRules RG_CSGameRules_TeamFull, RG_CSGameRules_TeamStacked, RG_CSGameRules_PlayerGotWeapon, + RG_CSGameRules_SendDeathMessage, // [...] }; diff --git a/reapi/src/natives/natives_misc.cpp b/reapi/src/natives/natives_misc.cpp index 609695c..8c1ef8a 100644 --- a/reapi/src/natives/natives_misc.cpp +++ b/reapi/src/natives/natives_misc.cpp @@ -3293,6 +3293,58 @@ cell AMX_NATIVE_CALL rg_player_relationship(AMX *amx, cell *params) return CSGameRules()->PlayerRelationship(pPlayer, pTarget); } +/* +* Sends death messages to all players, including info about the killer, victim, weapon used, +* extra death flags, death position, assistant, and kill rarity using the CHalfLifeMultiplay::SendDeathMessage function. +* +* @param pKiller The entity who performed the kill (Note: The killer may be a non-player) +* @param pVictim The player who was killed +* @param pAssister The assisting player (if any) +* @param pevInflictor Inflictor entity. 0 = world +* @param killerWeaponName The name of the weapon used by the killer +* @param iDeathMessageFlags Flags indicating extra death message info +* @param iRarityOfKill An bitsums representing the rarity classification of the kill +* +* @noreturn +*/ +cell AMX_NATIVE_CALL rg_send_death_message(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_killer, arg_victim, arg_assister, arg_inflictor, arg_weaponname, arg_deathmsgflags, arg_rarityofkill }; + + CHECK_GAMERULES(); + + CHECK_ISPLAYER(arg_victim); + CBasePlayer *pVictim = UTIL_PlayerByIndex(params[arg_victim]); + CHECK_CONNECTED(pVictim, arg_victim); + + CBasePlayer *pKiller = nullptr; + CBasePlayer *pAssister = nullptr; + + // Check if the killer is a player + if (params[arg_killer]) + { + CHECK_ISPLAYER(arg_killer); + pKiller = UTIL_PlayerByIndex(params[arg_killer]); + CHECK_CONNECTED(pKiller, arg_killer); + } + + // Check if the assister is a player + if (params[arg_assister]) + { + CHECK_ISPLAYER(arg_assister); + pAssister = UTIL_PlayerByIndex(params[arg_assister]); + CHECK_CONNECTED(pAssister, arg_assister); + } + + CAmxArgs args(amx, params); + + char weaponStr[32]; + const char *weaponName = getAmxString(amx, params[arg_weaponname], weaponStr); + + CSGameRules()->SendDeathMessage(pKiller, pVictim, pAssister, args[arg_inflictor], weaponName, args[arg_deathmsgflags], args[arg_rarityofkill]); + return TRUE; +} + AMX_NATIVE_INFO Misc_Natives_RG[] = { { "rg_set_animation", rg_set_animation }, @@ -3406,6 +3458,8 @@ AMX_NATIVE_INFO Misc_Natives_RG[] = { "rg_death_notice", rg_death_notice }, { "rg_player_relationship", rg_player_relationship }, + { "rg_send_death_message", rg_send_death_message }, + { nullptr, nullptr } };