mirror of
https://github.com/s1lentq/ReGameDLL_CS.git
synced 2025-01-14 23:58:06 +03:00
Add an extended player's DeathMsg message (#858)
* Implemented rarity of kill and assist for extended user message DeathMsg * Add hookchain CGameRules::SendDeathMessage * Add domination and revenge
This commit is contained in:
parent
67e7d87423
commit
108db28143
@ -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_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_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_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>
|
</details>
|
||||||
|
|
||||||
## How to install zBot for CS 1.6?
|
## How to install zBot for CS 1.6?
|
||||||
|
16
dist/game.cfg
vendored
16
dist/game.cfg
vendored
@ -537,3 +537,19 @@ mp_legacy_vehicle_block "1"
|
|||||||
//
|
//
|
||||||
// Default value: "3.0"
|
// Default value: "3.0"
|
||||||
mp_dying_time "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"
|
||||||
|
@ -331,6 +331,7 @@ GAMEHOOK_REGISTRY(CBasePlayer_EntSelectSpawnPoint);
|
|||||||
GAMEHOOK_REGISTRY(CBasePlayerWeapon_ItemPostFrame);
|
GAMEHOOK_REGISTRY(CBasePlayerWeapon_ItemPostFrame);
|
||||||
GAMEHOOK_REGISTRY(CBasePlayerWeapon_KickBack);
|
GAMEHOOK_REGISTRY(CBasePlayerWeapon_KickBack);
|
||||||
GAMEHOOK_REGISTRY(CBasePlayerWeapon_SendWeaponAnim);
|
GAMEHOOK_REGISTRY(CBasePlayerWeapon_SendWeaponAnim);
|
||||||
|
GAMEHOOK_REGISTRY(CSGameRules_SendDeathMessage);
|
||||||
|
|
||||||
int CReGameApi::GetMajorVersion() {
|
int CReGameApi::GetMajorVersion() {
|
||||||
return REGAMEDLL_API_VERSION_MAJOR;
|
return REGAMEDLL_API_VERSION_MAJOR;
|
||||||
|
@ -709,6 +709,10 @@ typedef IHookChainRegistryClassEmptyImpl<BOOL, class CHalfLifeMultiplay, int, in
|
|||||||
typedef IHookChainClassImpl<void, class CHalfLifeMultiplay, CBasePlayer *, CBasePlayerItem *> CReGameHook_CSGameRules_PlayerGotWeapon;
|
typedef IHookChainClassImpl<void, class CHalfLifeMultiplay, CBasePlayer *, CBasePlayerItem *> CReGameHook_CSGameRules_PlayerGotWeapon;
|
||||||
typedef IHookChainRegistryClassEmptyImpl<void, class CHalfLifeMultiplay, CBasePlayer *, CBasePlayerItem *> CReGameHookRegistry_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
|
// CBotManager::OnEvent hook
|
||||||
typedef IHookChainClassImpl<void, CBotManager, GameEventType, CBaseEntity *, CBaseEntity *> CReGameHook_CBotManager_OnEvent;
|
typedef IHookChainClassImpl<void, CBotManager, GameEventType, CBaseEntity *, CBaseEntity *> CReGameHook_CBotManager_OnEvent;
|
||||||
typedef IHookChainRegistryClassEmptyImpl<void, CBotManager, GameEventType, CBaseEntity*, CBaseEntity*> CReGameHookRegistry_CBotManager_OnEvent;
|
typedef IHookChainRegistryClassEmptyImpl<void, CBotManager, GameEventType, CBaseEntity*, CBaseEntity*> CReGameHookRegistry_CBotManager_OnEvent;
|
||||||
@ -889,6 +893,7 @@ public:
|
|||||||
CReGameHookRegistry_CBasePlayerWeapon_ItemPostFrame m_CBasePlayerWeapon_ItemPostFrame;
|
CReGameHookRegistry_CBasePlayerWeapon_ItemPostFrame m_CBasePlayerWeapon_ItemPostFrame;
|
||||||
CReGameHookRegistry_CBasePlayerWeapon_KickBack m_CBasePlayerWeapon_KickBack;
|
CReGameHookRegistry_CBasePlayerWeapon_KickBack m_CBasePlayerWeapon_KickBack;
|
||||||
CReGameHookRegistry_CBasePlayerWeapon_SendWeaponAnim m_CBasePlayerWeapon_SendWeaponAnim;
|
CReGameHookRegistry_CBasePlayerWeapon_SendWeaponAnim m_CBasePlayerWeapon_SendWeaponAnim;
|
||||||
|
CReGameHookRegistry_CSGameRules_SendDeathMessage m_CSGameRules_SendDeathMessage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual IReGameHookRegistry_CBasePlayer_Spawn *CBasePlayer_Spawn();
|
virtual IReGameHookRegistry_CBasePlayer_Spawn *CBasePlayer_Spawn();
|
||||||
@ -1044,6 +1049,7 @@ public:
|
|||||||
virtual IReGameHookRegistry_CBasePlayerWeapon_ItemPostFrame *CBasePlayerWeapon_ItemPostFrame();
|
virtual IReGameHookRegistry_CBasePlayerWeapon_ItemPostFrame *CBasePlayerWeapon_ItemPostFrame();
|
||||||
virtual IReGameHookRegistry_CBasePlayerWeapon_KickBack *CBasePlayerWeapon_KickBack();
|
virtual IReGameHookRegistry_CBasePlayerWeapon_KickBack *CBasePlayerWeapon_KickBack();
|
||||||
virtual IReGameHookRegistry_CBasePlayerWeapon_SendWeaponAnim *CBasePlayerWeapon_SendWeaponAnim();
|
virtual IReGameHookRegistry_CBasePlayerWeapon_SendWeaponAnim *CBasePlayerWeapon_SendWeaponAnim();
|
||||||
|
virtual IReGameHookRegistry_CSGameRules_SendDeathMessage *CSGameRules_SendDeathMessage();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CReGameHookchains g_ReGameHookchains;
|
extern CReGameHookchains g_ReGameHookchains;
|
||||||
|
@ -550,10 +550,22 @@ void CCSPlayer::ResetVars()
|
|||||||
m_bSpawnProtectionEffects = false;
|
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()
|
void CCSPlayer::OnSpawn()
|
||||||
{
|
{
|
||||||
m_bGameForcingRespawn = false;
|
m_bGameForcingRespawn = false;
|
||||||
m_flRespawnPending = 0.0f;
|
m_flRespawnPending = 0.0f;
|
||||||
|
m_DamageList.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCSPlayer::OnKilled()
|
void CCSPlayer::OnKilled()
|
||||||
@ -571,3 +583,33 @@ void CCSPlayer::OnKilled()
|
|||||||
}
|
}
|
||||||
#endif
|
#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;
|
||||||
|
}
|
||||||
|
@ -1340,6 +1340,7 @@ VectorRef CBaseEntity::__API_HOOK(FireBullets3)(VectorRef vecSrc, VectorRef vecD
|
|||||||
|
|
||||||
float flDamageModifier = 0.5;
|
float flDamageModifier = 0.5;
|
||||||
|
|
||||||
|
int iStartPenetration = iPenetration;
|
||||||
while (iPenetration != 0)
|
while (iPenetration != 0)
|
||||||
{
|
{
|
||||||
ClearMultiDamage();
|
ClearMultiDamage();
|
||||||
@ -1400,9 +1401,11 @@ VectorRef CBaseEntity::__API_HOOK(FireBullets3)(VectorRef vecSrc, VectorRef vecD
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tr.flFraction != 1.0f)
|
if (tr.flFraction != 1.0f)
|
||||||
{
|
{
|
||||||
CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit);
|
CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit);
|
||||||
|
int iPenetrationCur = iPenetration;
|
||||||
iPenetration--;
|
iPenetration--;
|
||||||
|
|
||||||
flCurrentDistance = tr.flFraction * flDistance;
|
flCurrentDistance = tr.flFraction * flDistance;
|
||||||
@ -1459,6 +1462,7 @@ VectorRef CBaseEntity::__API_HOOK(FireBullets3)(VectorRef vecSrc, VectorRef vecD
|
|||||||
flDistance = (flDistance - flCurrentDistance) * flDistanceModifier;
|
flDistance = (flDistance - flCurrentDistance) * flDistanceModifier;
|
||||||
vecEnd = vecSrc + (vecDir * flDistance);
|
vecEnd = vecSrc + (vecDir * flDistance);
|
||||||
|
|
||||||
|
pEntity->SetDmgPenetrationLevel(iStartPenetration - iPenetrationCur);
|
||||||
pEntity->TraceAttack(pevAttacker, iCurrentDamage, vecDir, &tr, (DMG_BULLET | DMG_NEVERGIB));
|
pEntity->TraceAttack(pevAttacker, iCurrentDamage, vecDir, &tr, (DMG_BULLET | DMG_NEVERGIB));
|
||||||
iCurrentDamage *= flDamageModifier;
|
iCurrentDamage *= flDamageModifier;
|
||||||
}
|
}
|
||||||
|
@ -242,6 +242,10 @@ public:
|
|||||||
void SetBlocked(void (T::*pfn)(CBaseEntity *pOther));
|
void SetBlocked(void (T::*pfn)(CBaseEntity *pOther));
|
||||||
void SetBlocked(std::nullptr_t);
|
void SetBlocked(std::nullptr_t);
|
||||||
|
|
||||||
|
void SetDmgPenetrationLevel(int iPenetrationLevel);
|
||||||
|
void ResetDmgPenetrationLevel();
|
||||||
|
int GetDmgPenetrationLevel() const;
|
||||||
|
|
||||||
#ifdef REGAMEDLL_API
|
#ifdef REGAMEDLL_API
|
||||||
CCSEntity *m_pEntity;
|
CCSEntity *m_pEntity;
|
||||||
CCSEntity *CSEntity() const;
|
CCSEntity *CSEntity() const;
|
||||||
|
@ -730,7 +730,7 @@ void EXT_FUNC ClientPutInServer(edict_t *pEntity)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef REGAMEDLL_API
|
#ifdef REGAMEDLL_API
|
||||||
pPlayer->CSPlayer()->ResetVars();
|
pPlayer->CSPlayer()->OnConnect();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
UTIL_ClientPrintAll(HUD_PRINTNOTIFY, "#Game_connected", (sName[0] != '\0') ? sName : "<unconnected>");
|
UTIL_ClientPrintAll(HUD_PRINTNOTIFY, "#Game_connected", (sName[0] != '\0') ? sName : "<unconnected>");
|
||||||
|
@ -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)
|
if (TheBots)
|
||||||
{
|
{
|
||||||
TheBots->OnEvent(EVENT_PLAYER_BLINDED_BY_FLASHBANG, pPlayer);
|
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)
|
void RadiusFlash_TraceLine_hook(CBasePlayer *pPlayer, entvars_t *pevInflictor, entvars_t *pevAttacker, Vector &vecSrc, Vector &vecSpot, TraceResult *tr)
|
||||||
@ -110,7 +121,6 @@ void RadiusFlash(Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker,
|
|||||||
}
|
}
|
||||||
|
|
||||||
flAdjustedDamage = flDamage - (vecSrc - tr.vecEndPos).Length() * falloff;
|
flAdjustedDamage = flDamage - (vecSrc - tr.vecEndPos).Length() * falloff;
|
||||||
|
|
||||||
if (flAdjustedDamage < 0)
|
if (flAdjustedDamage < 0)
|
||||||
flAdjustedDamage = 0;
|
flAdjustedDamage = 0;
|
||||||
|
|
||||||
@ -303,6 +313,8 @@ void RadiusDamage(Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker
|
|||||||
|
|
||||||
if (tr.flFraction != 1.0f)
|
if (tr.flFraction != 1.0f)
|
||||||
flAdjustedDamage = 0.0f;
|
flAdjustedDamage = 0.0f;
|
||||||
|
else
|
||||||
|
pEntity->SetDmgPenetrationLevel(1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -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 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 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 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 };
|
cvar_t hostages_rescued_ratio = { "mp_hostages_rescued_ratio", "1.0", 0, 1.0f, nullptr };
|
||||||
|
|
||||||
@ -423,6 +425,8 @@ void EXT_FUNC GameDLLInit()
|
|||||||
CVAR_REGISTER(&legacy_vehicle_block);
|
CVAR_REGISTER(&legacy_vehicle_block);
|
||||||
|
|
||||||
CVAR_REGISTER(&dying_time);
|
CVAR_REGISTER(&dying_time);
|
||||||
|
CVAR_REGISTER(&deathmsg_flags);
|
||||||
|
CVAR_REGISTER(&assist_damage_threshold);
|
||||||
|
|
||||||
// print version
|
// print version
|
||||||
CONSOLE_ECHO("ReGameDLL version: " APP_VERSION "\n");
|
CONSOLE_ECHO("ReGameDLL version: " APP_VERSION "\n");
|
||||||
|
@ -195,6 +195,8 @@ extern cvar_t give_c4_frags;
|
|||||||
extern cvar_t hostages_rescued_ratio;
|
extern cvar_t hostages_rescued_ratio;
|
||||||
extern cvar_t legacy_vehicle_block;
|
extern cvar_t legacy_vehicle_block;
|
||||||
extern cvar_t dying_time;
|
extern cvar_t dying_time;
|
||||||
|
extern cvar_t deathmsg_flags;
|
||||||
|
extern cvar_t assist_damage_threshold;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -220,6 +220,40 @@ enum
|
|||||||
GR_NEUTRAL,
|
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 CItem;
|
||||||
|
|
||||||
class CGameRules
|
class CGameRules
|
||||||
@ -574,6 +608,7 @@ public:
|
|||||||
BOOL TeamFull_OrigFunc(int team_id);
|
BOOL TeamFull_OrigFunc(int team_id);
|
||||||
BOOL TeamStacked_OrigFunc(int newTeam_id, int curTeam_id);
|
BOOL TeamStacked_OrigFunc(int newTeam_id, int curTeam_id);
|
||||||
void PlayerGotWeapon_OrigFunc(CBasePlayer *pPlayer, CBasePlayerItem *pWeapon);
|
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
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -698,6 +733,10 @@ public:
|
|||||||
VFUNC bool HasRoundTimeExpired();
|
VFUNC bool HasRoundTimeExpired();
|
||||||
VFUNC bool IsBombPlanted();
|
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:
|
private:
|
||||||
void MarkLivingPlayersOnTeamAsNotReceivingMoneyNextRound(int iTeam);
|
void MarkLivingPlayersOnTeamAsNotReceivingMoneyNextRound(int iTeam);
|
||||||
|
|
||||||
|
@ -4079,102 +4079,69 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(PlayerKilled)(CBasePlayer *pVictim,
|
|||||||
|
|
||||||
LINK_HOOK_CLASS_VOID_CUSTOM_CHAIN(CHalfLifeMultiplay, CSGameRules, DeathNotice, (CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pevInflictor), pVictim, pKiller, pevInflictor)
|
LINK_HOOK_CLASS_VOID_CUSTOM_CHAIN(CHalfLifeMultiplay, CSGameRules, DeathNotice, (CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pevInflictor), pVictim, pKiller, pevInflictor)
|
||||||
|
|
||||||
void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(DeathNotice)(CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pevInflictor)
|
void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(DeathNotice)(CBasePlayer *pVictim, entvars_t *pevKiller, entvars_t *pevInflictor)
|
||||||
{
|
{
|
||||||
// by default, the player is killed by the world
|
// by default, the player is killed by the world
|
||||||
const char *killer_weapon_name = "world";
|
CBasePlayer *pKiller = (pevKiller->flags & FL_CLIENT) ? CBasePlayer::Instance(pevKiller) : nullptr;
|
||||||
int killer_index = 0;
|
const char *killer_weapon_name = pVictim->GetKillerWeaponName(pevInflictor, pevKiller);
|
||||||
|
|
||||||
#ifndef REGAMEDLL_FIXES
|
|
||||||
// Hack to fix name change
|
|
||||||
char *tau = "tau_cannon";
|
|
||||||
char *gluon = "gluon gun";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Is the killer a client?
|
|
||||||
if (pKiller->flags & FL_CLIENT)
|
|
||||||
{
|
|
||||||
killer_index = ENTINDEX(ENT(pKiller));
|
|
||||||
|
|
||||||
if (pevInflictor)
|
|
||||||
{
|
|
||||||
if (pevInflictor == pKiller)
|
|
||||||
{
|
|
||||||
// If the inflictor is the killer, then it must be their current weapon doing the damage
|
|
||||||
CBasePlayer *pAttacker = CBasePlayer::Instance(pKiller);
|
|
||||||
if (pAttacker && pAttacker->IsPlayer())
|
|
||||||
{
|
|
||||||
if (pAttacker->m_pActiveItem)
|
|
||||||
{
|
|
||||||
killer_weapon_name = pAttacker->m_pActiveItem->pszName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// it's just that easy
|
|
||||||
killer_weapon_name = STRING(pevInflictor->classname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#ifdef REGAMEDLL_FIXES
|
|
||||||
if (pevInflictor)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
killer_weapon_name = STRING(pevInflictor->classname);
|
|
||||||
}
|
|
||||||
|
|
||||||
// strip the monster_* or weapon_* from the inflictor's classname
|
|
||||||
const char cut_weapon[] = "weapon_";
|
|
||||||
const char cut_monster[] = "monster_";
|
|
||||||
const char cut_func[] = "func_";
|
|
||||||
|
|
||||||
// replace the code names with the 'real' names
|
|
||||||
if (!Q_strncmp(killer_weapon_name, cut_weapon, sizeof(cut_weapon) - 1))
|
|
||||||
killer_weapon_name += sizeof(cut_weapon) - 1;
|
|
||||||
|
|
||||||
else if (!Q_strncmp(killer_weapon_name, cut_monster, sizeof(cut_monster) - 1))
|
|
||||||
killer_weapon_name += sizeof(cut_monster) - 1;
|
|
||||||
|
|
||||||
else if (!Q_strncmp(killer_weapon_name, cut_func, sizeof(cut_func) - 1))
|
|
||||||
killer_weapon_name += sizeof(cut_func) - 1;
|
|
||||||
|
|
||||||
if (!TheTutor)
|
if (!TheTutor)
|
||||||
{
|
{
|
||||||
|
#ifdef REGAMEDLL_ADD
|
||||||
|
int iRarityOfKill = 0;
|
||||||
|
int iDeathMessageFlags = PLAYERDEATH_POSITION; // set default bit
|
||||||
|
|
||||||
|
CBasePlayer *pAssister = nullptr;
|
||||||
|
|
||||||
|
bool bFlashAssist = false;
|
||||||
|
if ((pAssister = CheckAssistsToKill(pKiller, pVictim, bFlashAssist)))
|
||||||
|
{
|
||||||
|
// Add a flag indicating the presence of an assistant who assisted in the kill
|
||||||
|
iDeathMessageFlags |= PLAYERDEATH_ASSISTANT;
|
||||||
|
}
|
||||||
|
|
||||||
|
iRarityOfKill = GetRarityOfKill(pKiller, pVictim, pAssister, killer_weapon_name, bFlashAssist);
|
||||||
|
if (iRarityOfKill != 0)
|
||||||
|
{
|
||||||
|
// Add a flag indicating that the attacker killed the victim in a rare way
|
||||||
|
iDeathMessageFlags |= PLAYERDEATH_KILLRARITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
SendDeathMessage(pKiller, pVictim, pAssister, pevInflictor, killer_weapon_name, iDeathMessageFlags, iRarityOfKill);
|
||||||
|
|
||||||
|
// Updates the stats of who has killed whom
|
||||||
|
if (pKiller && pKiller->IsPlayer() && PlayerRelationship(pVictim, pKiller) != GR_TEAMMATE)
|
||||||
|
{
|
||||||
|
int iPlayerIndexKiller = pKiller->entindex();
|
||||||
|
int iPlayerIndexVictim = pVictim->entindex();
|
||||||
|
|
||||||
|
pKiller->CSPlayer()->m_iNumKilledByUnanswered[iPlayerIndexVictim - 1] = 0;
|
||||||
|
pVictim->CSPlayer()->m_iNumKilledByUnanswered[iPlayerIndexKiller - 1]++;
|
||||||
|
}
|
||||||
|
#else
|
||||||
MESSAGE_BEGIN(MSG_ALL, gmsgDeathMsg);
|
MESSAGE_BEGIN(MSG_ALL, gmsgDeathMsg);
|
||||||
WRITE_BYTE(killer_index); // the killer
|
WRITE_BYTE(pKiller ? pKiller->entindex() : 0); // the killer
|
||||||
WRITE_BYTE(ENTINDEX(pVictim->edict())); // the victim
|
WRITE_BYTE(ENTINDEX(pVictim->edict())); // the victim
|
||||||
WRITE_BYTE(pVictim->m_bHeadshotKilled); // is killed headshot
|
WRITE_BYTE(pVictim->m_bHeadshotKilled); // is killed headshot
|
||||||
WRITE_STRING(killer_weapon_name); // what they were killed by (should this be a string?)
|
WRITE_STRING(killer_weapon_name); // what they were killed by (should this be a string?)
|
||||||
MESSAGE_END();
|
MESSAGE_END();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// This weapons from HL isn't it?
|
|
||||||
#ifndef REGAMEDLL_FIXES
|
|
||||||
if (!Q_strcmp(killer_weapon_name, "egon"))
|
|
||||||
killer_weapon_name = gluon;
|
|
||||||
|
|
||||||
else if (!Q_strcmp(killer_weapon_name, "gauss"))
|
|
||||||
killer_weapon_name = tau;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Did he kill himself?
|
// Did he kill himself?
|
||||||
if (pVictim->pev == pKiller)
|
if (pVictim->pev == pevKiller)
|
||||||
{
|
{
|
||||||
// killed self
|
// killed self
|
||||||
char *team = GetTeam(pVictim->m_iTeam);
|
char *team = GetTeam(pVictim->m_iTeam);
|
||||||
UTIL_LogPrintf("\"%s<%i><%s><%s>\" committed suicide with \"%s\"\n", STRING(pVictim->pev->netname), GETPLAYERUSERID(pVictim->edict()),
|
UTIL_LogPrintf("\"%s<%i><%s><%s>\" committed suicide with \"%s\"\n", STRING(pVictim->pev->netname), GETPLAYERUSERID(pVictim->edict()),
|
||||||
GETPLAYERAUTHID(pVictim->edict()), team, killer_weapon_name);
|
GETPLAYERAUTHID(pVictim->edict()), team, killer_weapon_name);
|
||||||
}
|
}
|
||||||
else if (pKiller->flags & FL_CLIENT)
|
else if (pevKiller->flags & FL_CLIENT)
|
||||||
{
|
{
|
||||||
CBasePlayer *pAttacker = CBasePlayer::Instance(pKiller);
|
|
||||||
|
|
||||||
const char *VictimTeam = GetTeam(pVictim->m_iTeam);
|
const char *VictimTeam = GetTeam(pVictim->m_iTeam);
|
||||||
const char *KillerTeam = (pAttacker && pAttacker->IsPlayer()) ? GetTeam(pAttacker->m_iTeam) : "";
|
const char *KillerTeam = (pKiller && pKiller->IsPlayer()) ? GetTeam(pKiller->m_iTeam) : "";
|
||||||
|
|
||||||
UTIL_LogPrintf("\"%s<%i><%s><%s>\" killed \"%s<%i><%s><%s>\" with \"%s\"\n", STRING(pKiller->netname), GETPLAYERUSERID(ENT(pKiller)), GETPLAYERAUTHID(ENT(pKiller)),
|
UTIL_LogPrintf("\"%s<%i><%s><%s>\" killed \"%s<%i><%s><%s>\" with \"%s\"\n", STRING(pevKiller->netname), GETPLAYERUSERID(ENT(pevKiller)), GETPLAYERAUTHID(ENT(pevKiller)),
|
||||||
KillerTeam, STRING(pVictim->pev->netname), GETPLAYERUSERID(pVictim->edict()), GETPLAYERAUTHID(pVictim->edict()), VictimTeam, killer_weapon_name);
|
KillerTeam, STRING(pVictim->pev->netname), GETPLAYERUSERID(pVictim->edict()), GETPLAYERAUTHID(pVictim->edict()), VictimTeam, killer_weapon_name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -4197,7 +4164,7 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(DeathNotice)(CBasePlayer *pVictim,
|
|||||||
if (pevInflictor)
|
if (pevInflictor)
|
||||||
WRITE_SHORT(ENTINDEX(ENT(pevInflictor))); // index number of secondary entity
|
WRITE_SHORT(ENTINDEX(ENT(pevInflictor))); // index number of secondary entity
|
||||||
else
|
else
|
||||||
WRITE_SHORT(ENTINDEX(ENT(pKiller))); // index number of secondary entity
|
WRITE_SHORT(ENTINDEX(ENT(pevKiller))); // index number of secondary entity
|
||||||
|
|
||||||
if (pVictim->m_bHeadshotKilled)
|
if (pVictim->m_bHeadshotKilled)
|
||||||
WRITE_LONG(9 | DRC_FLAG_DRAMATIC | DRC_FLAG_SLOWMOTION);
|
WRITE_LONG(9 | DRC_FLAG_DRAMATIC | DRC_FLAG_SLOWMOTION);
|
||||||
@ -5204,3 +5171,226 @@ bool CHalfLifeMultiplay::CanPlayerBuy(CBasePlayer *pPlayer) const
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Checks for assists in a kill situation
|
||||||
|
//
|
||||||
|
// This function analyzes damage records and player actions to determine the player who contributed the most to a kill,
|
||||||
|
// considering factors such as damage dealt and the use of flashbang grenades
|
||||||
|
//
|
||||||
|
// pKiller - The killer entity (Note: The killer may be a non-player)
|
||||||
|
// pVictim - The victim player
|
||||||
|
// bFlashAssist - A flag indicating whether a flashbang was used in the assist
|
||||||
|
// Returns - A pointer to the player who gave the most assistance, or NULL if appropriate assistant is not found
|
||||||
|
//
|
||||||
|
CBasePlayer *CHalfLifeMultiplay::CheckAssistsToKill(CBaseEntity *pKiller, CBasePlayer *pVictim, bool &bFlashAssist)
|
||||||
|
{
|
||||||
|
#ifdef REGAMEDLL_ADD
|
||||||
|
CCSPlayer::DamageList_t &victimDamageTakenList = pVictim->CSPlayer()->GetDamageList();
|
||||||
|
|
||||||
|
float maxDamage = 0.0f;
|
||||||
|
int maxDamageIndex = -1;
|
||||||
|
CBasePlayer *maxDamagePlayer = nullptr;
|
||||||
|
|
||||||
|
// Find the best assistant
|
||||||
|
for (int i = 1; i <= gpGlobals->maxClients; i++)
|
||||||
|
{
|
||||||
|
const CCSPlayer::CDamageRecord_t &record = victimDamageTakenList[i - 1];
|
||||||
|
if (record.flDamage == 0)
|
||||||
|
continue; // dealt no damage
|
||||||
|
|
||||||
|
CBasePlayer *pAttackerPlayer = UTIL_PlayerByIndex(i);
|
||||||
|
if (!pAttackerPlayer || pAttackerPlayer->IsDormant())
|
||||||
|
continue; // ignore idle clients
|
||||||
|
|
||||||
|
CCSPlayer *pCSAttackerPlayer = pAttackerPlayer->CSPlayer();
|
||||||
|
if (record.userId != pCSAttackerPlayer->m_iUserID)
|
||||||
|
continue; // another client?
|
||||||
|
|
||||||
|
if (pAttackerPlayer == pKiller || pAttackerPlayer == pVictim)
|
||||||
|
continue; // ignore involved as killer or victim
|
||||||
|
|
||||||
|
if (record.flDamage > maxDamage)
|
||||||
|
{
|
||||||
|
// If the assistant used a flash grenade to aid in the kill,
|
||||||
|
// make sure that the victim was blinded, and that the duration of the flash effect is still preserved
|
||||||
|
if (record.flFlashDurationTime > 0 && (!pVictim->IsBlind() || record.flFlashDurationTime <= gpGlobals->time))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
maxDamage = record.flDamage;
|
||||||
|
maxDamagePlayer = pAttackerPlayer;
|
||||||
|
maxDamageIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: Only the highest damaging player can be an assistant
|
||||||
|
// The condition checks if the damage dealt by the player exceeds a certain percentage of the victim's max health
|
||||||
|
// Default threshold is 40%, meaning the assistant must deal at least 40% of the victim's max health as damage
|
||||||
|
if (maxDamagePlayer && maxDamage > (assist_damage_threshold.value / 100.0f) * pVictim->pev->max_health)
|
||||||
|
{
|
||||||
|
bFlashAssist = victimDamageTakenList[maxDamageIndex - 1].flFlashDurationTime > 0; // if performed the flash assist
|
||||||
|
return maxDamagePlayer;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check the rarity estimation for a kill
|
||||||
|
//
|
||||||
|
// Estimation to represent the rarity of a kill based on various factors, including assists with flashbang grenades,
|
||||||
|
// headshot kills, kills through walls, the killer's blindness, no-scope sniper rifle kills, and kills through smoke
|
||||||
|
//
|
||||||
|
// pKiller - The entity who committed the kill (Note: The killer may be a non-player)
|
||||||
|
// pVictim - The player who was killed
|
||||||
|
// pAssister - The assisting player (if any)
|
||||||
|
// killerWeaponName - The name of the weapon used by the killer
|
||||||
|
// bFlashAssist - A flag indicating whether an assist was made with a flashbang
|
||||||
|
// Returns an integer estimation representing the rarity of the kill
|
||||||
|
// Use with PLAYERDEATH_KILLRARITY flag to indicate a rare kill in death messages
|
||||||
|
//
|
||||||
|
int CHalfLifeMultiplay::GetRarityOfKill(CBaseEntity *pKiller, CBasePlayer *pVictim, CBasePlayer *pAssister, const char *killerWeaponName, bool bFlashAssist)
|
||||||
|
{
|
||||||
|
int iRarity = 0;
|
||||||
|
|
||||||
|
// The killer player kills the victim with an assistant flashbang grenade
|
||||||
|
if (pAssister && bFlashAssist)
|
||||||
|
iRarity |= KILLRARITY_ASSIST_FLASH;
|
||||||
|
|
||||||
|
// The killer player kills the victim with a headshot
|
||||||
|
if (pVictim->m_bHeadshotKilled)
|
||||||
|
iRarity |= KILLRARITY_HEADSHOT;
|
||||||
|
|
||||||
|
// The killer player kills the victim through the walls
|
||||||
|
if (pVictim->GetDmgPenetrationLevel() > 0)
|
||||||
|
iRarity |= KILLRARITY_PENETRATED;
|
||||||
|
|
||||||
|
// The killer player was blind
|
||||||
|
if (pKiller && pKiller->IsPlayer())
|
||||||
|
{
|
||||||
|
CBasePlayer *pKillerPlayer = static_cast<CBasePlayer *>(pKiller);
|
||||||
|
if (pKillerPlayer->IsBlind())
|
||||||
|
iRarity |= KILLRARITY_KILLER_BLIND;
|
||||||
|
|
||||||
|
// The killer player kills the victim with a sniper rifle with no scope
|
||||||
|
WeaponClassType weaponClass = AliasToWeaponClass(killerWeaponName);
|
||||||
|
if (weaponClass == WEAPONCLASS_SNIPERRIFLE && pKillerPlayer->m_iClientFOV == DEFAULT_FOV)
|
||||||
|
iRarity |= KILLRARITY_NOSCOPE;
|
||||||
|
|
||||||
|
// The killer player kills the victim through smoke
|
||||||
|
const Vector inEyePos = pKillerPlayer->EyePosition();
|
||||||
|
if (TheCSBots()->IsLineBlockedBySmoke(&inEyePos, &pVictim->pev->origin))
|
||||||
|
iRarity |= KILLRARITY_THROUGH_SMOKE;
|
||||||
|
|
||||||
|
// Calculate # of unanswered kills between killer & victim
|
||||||
|
// This is plus 1 as this function gets called before the stat is updated
|
||||||
|
// That is done so that the domination and revenge will be calculated prior
|
||||||
|
// to the death message being sent to the clients
|
||||||
|
int iAttackerEntityIndex = pKillerPlayer->entindex();
|
||||||
|
assert(iAttackerEntityIndex >= 0 && iAttackerEntityIndex < MAX_CLIENTS);
|
||||||
|
|
||||||
|
int iKillsUnanswered = pVictim->CSPlayer()->m_iNumKilledByUnanswered[iAttackerEntityIndex - 1] + 1;
|
||||||
|
if (iKillsUnanswered == CS_KILLS_FOR_DOMINATION || pKillerPlayer->CSPlayer()->IsPlayerDominated(pVictim->entindex() - 1))
|
||||||
|
{
|
||||||
|
// this is the Nth unanswered kill between killer and victim, killer is now dominating victim
|
||||||
|
iRarity |= KILLRARITY_DOMINATION;
|
||||||
|
|
||||||
|
// set victim to be dominated by killer
|
||||||
|
pKillerPlayer->CSPlayer()->SetPlayerDominated(pVictim, true);
|
||||||
|
}
|
||||||
|
else if (pVictim->CSPlayer()->IsPlayerDominated(pKillerPlayer->entindex() - 1))
|
||||||
|
{
|
||||||
|
// the killer killed someone who was dominating him, gains revenge
|
||||||
|
iRarity |= KILLRARITY_REVENGE;
|
||||||
|
|
||||||
|
// set victim to no longer be dominating the killer
|
||||||
|
pVictim->CSPlayer()->SetPlayerDominated(pKillerPlayer, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return iRarity;
|
||||||
|
}
|
||||||
|
|
||||||
|
LINK_HOOK_CLASS_VOID_CUSTOM_CHAIN(CHalfLifeMultiplay, CSGameRules, SendDeathMessage, (CBaseEntity *pKiller, CBasePlayer *pVictim, CBasePlayer *pAssister, entvars_t *pevInflictor, const char *killerWeaponName, int iDeathMessageFlags, int iRarityOfKill), pKiller, pVictim, pAssister, pevInflictor, killerWeaponName, iDeathMessageFlags, iRarityOfKill)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Sends death messages to all players, including info about the killer, victim, weapon used,
|
||||||
|
// extra death flags, death position, assistant, and kill rarity
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// pKiller - The entity who performed the kill (Note: The killer may be a non-player)
|
||||||
|
// pVictim - The player who was killed
|
||||||
|
// pAssister - The assisting player (if any)
|
||||||
|
// killerWeaponName - The name of the weapon used by the killer
|
||||||
|
// iDeathMessageFlags - Flags indicating extra death message info
|
||||||
|
// iRarityOfKill - An bitsums representing the rarity classification of the kill
|
||||||
|
//
|
||||||
|
void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(SendDeathMessage)(CBaseEntity *pKiller, CBasePlayer *pVictim, CBasePlayer *pAssister, entvars_t *pevInflictor, const char *killerWeaponName, int iDeathMessageFlags, int iRarityOfKill)
|
||||||
|
{
|
||||||
|
#ifdef REGAMEDLL_ADD
|
||||||
|
iDeathMessageFlags &= (int)deathmsg_flags.value; // leave only allowed bitsums for extra info
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CBasePlayer *pKillerPlayer = (pKiller && pKiller->IsPlayer()) ? static_cast<CBasePlayer *>(pKiller) : nullptr;
|
||||||
|
|
||||||
|
for (int i = 1; i <= gpGlobals->maxClients; i++)
|
||||||
|
{
|
||||||
|
CBasePlayer *pPlayer = UTIL_PlayerByIndex(i);
|
||||||
|
if (!pPlayer || FNullEnt(pPlayer->edict()))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (pPlayer->IsBot() || pPlayer->IsDormant())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int iSendDeathMessageFlags = iDeathMessageFlags;
|
||||||
|
|
||||||
|
// Send the victim's death position only
|
||||||
|
// if the attacker or victim is a teammate of the recipient player
|
||||||
|
if (pPlayer == pVictim || (
|
||||||
|
PlayerRelationship(pVictim, pPlayer) != GR_TEAMMATE &&
|
||||||
|
PlayerRelationship(pKillerPlayer, pPlayer) != GR_TEAMMATE))
|
||||||
|
{
|
||||||
|
iSendDeathMessageFlags &= ~PLAYERDEATH_POSITION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An recipient a client is a victim that involved in this kill
|
||||||
|
if (pPlayer == pVictim && pVictim != pKillerPlayer)
|
||||||
|
{
|
||||||
|
// Sets a domination kill for recipient of the victim once until revenge
|
||||||
|
int iKillsUnanswered = pVictim->CSPlayer()->m_iNumKilledByUnanswered[pKillerPlayer->entindex() - 1];
|
||||||
|
if (iKillsUnanswered >= CS_KILLS_FOR_DOMINATION)
|
||||||
|
iRarityOfKill &= ~KILLRARITY_DOMINATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
MESSAGE_BEGIN(MSG_ONE, gmsgDeathMsg, nullptr, pPlayer->pev);
|
||||||
|
WRITE_BYTE((pKiller && pKiller->IsPlayer()) ? pKiller->entindex() : 0); // the killer
|
||||||
|
WRITE_BYTE(pVictim->entindex()); // the victim
|
||||||
|
WRITE_BYTE(pVictim->m_bHeadshotKilled); // is killed headshot
|
||||||
|
WRITE_STRING(killerWeaponName); // what they were killed by (should this be a string?)
|
||||||
|
|
||||||
|
if (iSendDeathMessageFlags > 0)
|
||||||
|
{
|
||||||
|
WRITE_LONG(iSendDeathMessageFlags);
|
||||||
|
|
||||||
|
// Writes the coordinates of the place where the victim died
|
||||||
|
// The victim has just been killed, so this usefully display 'X' dead icon on the HUD radar
|
||||||
|
if (iSendDeathMessageFlags & PLAYERDEATH_POSITION)
|
||||||
|
{
|
||||||
|
WRITE_COORD(pVictim->pev->origin.x);
|
||||||
|
WRITE_COORD(pVictim->pev->origin.y);
|
||||||
|
WRITE_COORD(pVictim->pev->origin.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes the index of the teammate who assisted in the kill
|
||||||
|
if (iSendDeathMessageFlags & PLAYERDEATH_ASSISTANT)
|
||||||
|
WRITE_BYTE(pAssister->entindex());
|
||||||
|
|
||||||
|
// Writes the rarity classification of the kill
|
||||||
|
if (iSendDeathMessageFlags & PLAYERDEATH_KILLRARITY)
|
||||||
|
WRITE_LONG(iRarityOfKill);
|
||||||
|
}
|
||||||
|
|
||||||
|
MESSAGE_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -745,24 +745,30 @@ void EXT_FUNC CBasePlayer::__API_HOOK(TraceAttack)(entvars_t *pevAttacker, float
|
|||||||
AddMultiDamage(pevAttacker, this, flDamage, bitsDamageType);
|
AddMultiDamage(pevAttacker, this, flDamage, bitsDamageType);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *GetWeaponName(entvars_t *pevInflictor, entvars_t *pKiller)
|
const char *CBasePlayer::GetKillerWeaponName(entvars_t *pevInflictor, entvars_t *pevKiller) const
|
||||||
{
|
{
|
||||||
// by default, the player is killed by the world
|
// by default, the player is killed by the world
|
||||||
const char *killer_weapon_name = "world";
|
const char *killer_weapon_name = "world";
|
||||||
|
|
||||||
// Is the killer a client?
|
// Is the killer a client?
|
||||||
if (pKiller->flags & FL_CLIENT)
|
if (pevKiller->flags & FL_CLIENT)
|
||||||
{
|
{
|
||||||
if (pevInflictor)
|
if (pevInflictor)
|
||||||
{
|
{
|
||||||
if (pevInflictor == pKiller)
|
if (pevInflictor == pevKiller)
|
||||||
{
|
{
|
||||||
// If the inflictor is the killer, then it must be their current weapon doing the damage
|
#ifdef REGAMEDLL_FIXES
|
||||||
CBasePlayer *pAttacker = CBasePlayer::Instance(pKiller);
|
// Ignore the inflictor's weapon if victim killed self
|
||||||
if (pAttacker && pAttacker->IsPlayer())
|
if (pevKiller != pev)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
if (pAttacker->m_pActiveItem)
|
// If the inflictor is the killer, then it must be their current weapon doing the damage
|
||||||
killer_weapon_name = pAttacker->m_pActiveItem->pszName();
|
CBasePlayer *pAttacker = CBasePlayer::Instance(pevKiller);
|
||||||
|
if (pAttacker && pAttacker->IsPlayer())
|
||||||
|
{
|
||||||
|
if (pAttacker->m_pActiveItem)
|
||||||
|
killer_weapon_name = pAttacker->m_pActiveItem->pszName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -781,10 +787,11 @@ const char *GetWeaponName(entvars_t *pevInflictor, entvars_t *pKiller)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// strip the monster_* or weapon_* from the inflictor's classname
|
// strip the monster_* or weapon_* from the inflictor's classname
|
||||||
const char cut_weapon[] = "weapon_";
|
const char cut_weapon[] = "weapon_";
|
||||||
const char cut_monster[] = "monster_";
|
const char cut_monster[] = "monster_";
|
||||||
const char cut_func[] = "func_";
|
const char cut_func[] = "func_";
|
||||||
|
|
||||||
|
// replace the code names with the 'real' names
|
||||||
if (!Q_strncmp(killer_weapon_name, cut_weapon, sizeof(cut_weapon) - 1))
|
if (!Q_strncmp(killer_weapon_name, cut_weapon, sizeof(cut_weapon) - 1))
|
||||||
killer_weapon_name += sizeof(cut_weapon) - 1;
|
killer_weapon_name += sizeof(cut_weapon) - 1;
|
||||||
|
|
||||||
@ -955,7 +962,7 @@ BOOL EXT_FUNC CBasePlayer::__API_HOOK(TakeDamage)(entvars_t *pevInflictor, entva
|
|||||||
m_bKilledByGrenade = true;
|
m_bKilledByGrenade = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogAttack(pAttack, this, bTeamAttack, int(flDamage), armorHit, pev->health - flDamage, pev->armorvalue, GetWeaponName(pevInflictor, pevAttacker));
|
LogAttack(pAttack, this, bTeamAttack, int(flDamage), armorHit, pev->health - flDamage, pev->armorvalue, GetKillerWeaponName(pevInflictor, pevAttacker));
|
||||||
bTookDamage = CBaseMonster::TakeDamage(pevInflictor, pevAttacker, int(flDamage), bitsDamageType);
|
bTookDamage = CBaseMonster::TakeDamage(pevInflictor, pevAttacker, int(flDamage), bitsDamageType);
|
||||||
|
|
||||||
if (bTookDamage)
|
if (bTookDamage)
|
||||||
@ -970,9 +977,13 @@ BOOL EXT_FUNC CBasePlayer::__API_HOOK(TakeDamage)(entvars_t *pevInflictor, entva
|
|||||||
CBasePlayer *pPlayerAttacker = CBasePlayer::Instance(pevAttacker);
|
CBasePlayer *pPlayerAttacker = CBasePlayer::Instance(pevAttacker);
|
||||||
if (pPlayerAttacker && !pPlayerAttacker->IsBot() && pPlayerAttacker->m_iTeam != m_iTeam)
|
if (pPlayerAttacker && !pPlayerAttacker->IsBot() && pPlayerAttacker->m_iTeam != m_iTeam)
|
||||||
{
|
{
|
||||||
TheCareerTasks->HandleEnemyInjury(GetWeaponName(pevInflictor, pevAttacker), pPlayerAttacker->HasShield(), pPlayerAttacker);
|
TheCareerTasks->HandleEnemyInjury(GetKillerWeaponName(pevInflictor, pevAttacker), pPlayerAttacker->HasShield(), pPlayerAttacker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef REGAMEDLL_API
|
||||||
|
CSPlayer()->RecordDamage(pAttack, flDamage);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -1195,7 +1206,7 @@ BOOL EXT_FUNC CBasePlayer::__API_HOOK(TakeDamage)(entvars_t *pevInflictor, entva
|
|||||||
// keep track of amount of damage last sustained
|
// keep track of amount of damage last sustained
|
||||||
m_lastDamageAmount = flDamage;
|
m_lastDamageAmount = flDamage;
|
||||||
|
|
||||||
LogAttack(pAttack, this, bTeamAttack, flDamage, armorHit, pev->health - flDamage, pev->armorvalue, GetWeaponName(pevInflictor, pevAttacker));
|
LogAttack(pAttack, this, bTeamAttack, flDamage, armorHit, pev->health - flDamage, pev->armorvalue, GetKillerWeaponName(pevInflictor, pevAttacker));
|
||||||
|
|
||||||
// this cast to INT is critical!!! If a player ends up with 0.5 health, the engine will get that
|
// this cast to INT is critical!!! If a player ends up with 0.5 health, the engine will get that
|
||||||
// as an int (zero) and think the player is dead! (this will incite a clientside screentilt, etc)
|
// as an int (zero) and think the player is dead! (this will incite a clientside screentilt, etc)
|
||||||
@ -1213,9 +1224,13 @@ BOOL EXT_FUNC CBasePlayer::__API_HOOK(TakeDamage)(entvars_t *pevInflictor, entva
|
|||||||
CBasePlayer *pPlayerAttacker = CBasePlayer::Instance(pevAttacker);
|
CBasePlayer *pPlayerAttacker = CBasePlayer::Instance(pevAttacker);
|
||||||
if (pPlayerAttacker && !pPlayerAttacker->IsBot() && pPlayerAttacker->m_iTeam != m_iTeam)
|
if (pPlayerAttacker && !pPlayerAttacker->IsBot() && pPlayerAttacker->m_iTeam != m_iTeam)
|
||||||
{
|
{
|
||||||
TheCareerTasks->HandleEnemyInjury(GetWeaponName(pevInflictor, pevAttacker), pPlayerAttacker->HasShield(), pPlayerAttacker);
|
TheCareerTasks->HandleEnemyInjury(GetKillerWeaponName(pevInflictor, pevAttacker), pPlayerAttacker->HasShield(), pPlayerAttacker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef REGAMEDLL_API
|
||||||
|
CSPlayer()->RecordDamage(pAttack, flDamage);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -2113,7 +2128,7 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib)
|
|||||||
if (IsBot() && IsBlind()) // dystopm: shouldn't be !IsBot() ?
|
if (IsBot() && IsBlind()) // dystopm: shouldn't be !IsBot() ?
|
||||||
wasBlind = true;
|
wasBlind = true;
|
||||||
|
|
||||||
TheCareerTasks->HandleEnemyKill(wasBlind, GetWeaponName(g_pevLastInflictor, pevAttacker), m_bHeadshotKilled, killerHasShield, pAttacker, this); // last 2 param swapped to match function definition
|
TheCareerTasks->HandleEnemyKill(wasBlind, GetKillerWeaponName(g_pevLastInflictor, pevAttacker), m_bHeadshotKilled, killerHasShield, pAttacker, this); // last 2 param swapped to match function definition
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -2144,7 +2159,7 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib)
|
|||||||
{
|
{
|
||||||
if (TheCareerTasks)
|
if (TheCareerTasks)
|
||||||
{
|
{
|
||||||
TheCareerTasks->HandleEnemyKill(wasBlind, GetWeaponName(g_pevLastInflictor, pevAttacker), m_bHeadshotKilled, killerHasShield, this, pPlayer);
|
TheCareerTasks->HandleEnemyKill(wasBlind, GetKillerWeaponName(g_pevLastInflictor, pevAttacker), m_bHeadshotKilled, killerHasShield, this, pPlayer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5154,7 +5169,17 @@ void EXT_FUNC CBasePlayer::__API_HOOK(PostThink)()
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
m_LastHitGroup = HITGROUP_GENERIC;
|
m_LastHitGroup = HITGROUP_GENERIC;
|
||||||
TakeDamage(VARS(eoNullEntity), VARS(eoNullEntity), flFallDamage, DMG_FALL);
|
|
||||||
|
// FIXED: The player falling to the ground,
|
||||||
|
// the damage caused by the fall is initiated by himself (and not by the world)
|
||||||
|
entvars_t *pevAttacker =
|
||||||
|
#ifdef REGAMEDLL_FIXES
|
||||||
|
pev;
|
||||||
|
#else
|
||||||
|
VARS(eoNullEntity);
|
||||||
|
#endif
|
||||||
|
TakeDamage(pevAttacker, pevAttacker, flFallDamage, DMG_FALL);
|
||||||
|
|
||||||
pev->punchangle.x = 0;
|
pev->punchangle.x = 0;
|
||||||
if (TheBots)
|
if (TheBots)
|
||||||
{
|
{
|
||||||
@ -5983,6 +6008,8 @@ void CBasePlayer::Reset()
|
|||||||
if (CSPlayer()->GetProtectionState() == CCSPlayer::ProtectionSt_Active) {
|
if (CSPlayer()->GetProtectionState() == CCSPlayer::ProtectionSt_Active) {
|
||||||
RemoveSpawnProtection();
|
RemoveSpawnProtection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSPlayer()->ResetAllStats();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -637,6 +637,7 @@ public:
|
|||||||
bool GetIntoGame();
|
bool GetIntoGame();
|
||||||
bool ShouldToShowAccount(CBasePlayer *pReceiver) const;
|
bool ShouldToShowAccount(CBasePlayer *pReceiver) const;
|
||||||
bool ShouldToShowHealthInfo(CBasePlayer *pReceiver) const;
|
bool ShouldToShowHealthInfo(CBasePlayer *pReceiver) const;
|
||||||
|
const char *GetKillerWeaponName(entvars_t *pevInflictor, entvars_t *pevKiller) const;
|
||||||
|
|
||||||
CBasePlayerItem *GetItemByName(const char *itemName);
|
CBasePlayerItem *GetItemByName(const char *itemName);
|
||||||
CBasePlayerItem *GetItemById(WeaponIdType weaponID);
|
CBasePlayerItem *GetItemById(WeaponIdType weaponID);
|
||||||
@ -1000,7 +1001,6 @@ void SendItemStatus(CBasePlayer *pPlayer);
|
|||||||
const char *GetCSModelName(int item_id);
|
const char *GetCSModelName(int item_id);
|
||||||
Vector VecVelocityForDamage(float flDamage);
|
Vector VecVelocityForDamage(float flDamage);
|
||||||
int TrainSpeed(int iSpeed, int iMax);
|
int TrainSpeed(int iSpeed, int iMax);
|
||||||
const char *GetWeaponName(entvars_t *pevInflictor, entvars_t *pKiller);
|
|
||||||
void LogAttack(CBasePlayer *pAttacker, CBasePlayer *pVictim, int teamAttack, int healthHit, int armorHit, int newHealth, int newArmor, const char *killer_weapon_name);
|
void LogAttack(CBasePlayer *pAttacker, CBasePlayer *pVictim, int teamAttack, int healthHit, int armorHit, int newHealth, int newArmor, const char *killer_weapon_name);
|
||||||
bool CanSeeUseable(CBasePlayer *me, CBaseEntity *pEntity);
|
bool CanSeeUseable(CBasePlayer *me, CBaseEntity *pEntity);
|
||||||
void FixPlayerCrouchStuck(edict_t *pPlayer);
|
void FixPlayerCrouchStuck(edict_t *pPlayer);
|
||||||
|
@ -93,7 +93,7 @@ void EXT_FUNC __API_HOOK(ApplyMultiDamage)(entvars_t *pevInflictor, entvars_t *p
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
gMultiDamage.pEntity->TakeDamage(pevInflictor, pevAttacker, gMultiDamage.amount, gMultiDamage.type);
|
gMultiDamage.pEntity->TakeDamage(pevInflictor, pevAttacker, gMultiDamage.amount, gMultiDamage.type);
|
||||||
|
gMultiDamage.pEntity->ResetDmgPenetrationLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
LINK_HOOK_VOID_CHAIN(AddMultiDamage, (entvars_t *pevInflictor, CBaseEntity *pEntity, float flDamage, int bitsDamageType), pevInflictor, pEntity, flDamage, bitsDamageType)
|
LINK_HOOK_VOID_CHAIN(AddMultiDamage, (entvars_t *pevInflictor, CBaseEntity *pEntity, float flDamage, int bitsDamageType), pevInflictor, pEntity, flDamage, bitsDamageType)
|
||||||
|
@ -787,6 +787,7 @@
|
|||||||
<ClInclude Include="..\public\regamedll\regamedll_api.h" />
|
<ClInclude Include="..\public\regamedll\regamedll_api.h" />
|
||||||
<ClInclude Include="..\public\tier0\dbg.h" />
|
<ClInclude Include="..\public\tier0\dbg.h" />
|
||||||
<ClInclude Include="..\public\tier0\platform.h" />
|
<ClInclude Include="..\public\tier0\platform.h" />
|
||||||
|
<ClInclude Include="..\public\utlarray.h" />
|
||||||
<ClInclude Include="..\public\utlmemory.h" />
|
<ClInclude Include="..\public\utlmemory.h" />
|
||||||
<ClInclude Include="..\public\utlrbtree.h" />
|
<ClInclude Include="..\public\utlrbtree.h" />
|
||||||
<ClInclude Include="..\public\utlsymbol.h" />
|
<ClInclude Include="..\public\utlsymbol.h" />
|
||||||
|
@ -1052,5 +1052,8 @@
|
|||||||
<ClInclude Include="..\dlls\addons\point_command.h">
|
<ClInclude Include="..\dlls\addons\point_command.h">
|
||||||
<Filter>dlls\addons</Filter>
|
<Filter>dlls\addons</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\public\utlarray.h">
|
||||||
|
<Filter>public</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -35,6 +35,7 @@ public:
|
|||||||
CCSEntity() :
|
CCSEntity() :
|
||||||
m_pContainingEntity(nullptr)
|
m_pContainingEntity(nullptr)
|
||||||
{
|
{
|
||||||
|
m_ucDmgPenetrationLevel = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~CCSEntity() {}
|
virtual ~CCSEntity() {}
|
||||||
@ -44,12 +45,14 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
CBaseEntity *m_pContainingEntity;
|
CBaseEntity *m_pContainingEntity;
|
||||||
|
unsigned char m_ucDmgPenetrationLevel; // penetration level of the damage caused by the inflictor
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#pragma region reserve_data_Region
|
#pragma region reserve_data_Region
|
||||||
#endif
|
#endif
|
||||||
int CCSEntity_Reserve[0x1000];
|
char CCSEntity_Reserve[0x3FFF];
|
||||||
|
|
||||||
virtual void func_reserve1() {};
|
virtual void func_reserve1() {};
|
||||||
virtual void func_reserve2() {};
|
virtual void func_reserve2() {};
|
||||||
virtual void func_reserve3() {};
|
virtual void func_reserve3() {};
|
||||||
@ -85,6 +88,29 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline void CBaseEntity::SetDmgPenetrationLevel(int iPenetrationLevel)
|
||||||
|
{
|
||||||
|
#ifdef REGAMEDLL_API
|
||||||
|
m_pEntity->m_ucDmgPenetrationLevel = iPenetrationLevel;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CBaseEntity::ResetDmgPenetrationLevel()
|
||||||
|
{
|
||||||
|
#ifdef REGAMEDLL_API
|
||||||
|
m_pEntity->m_ucDmgPenetrationLevel = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int CBaseEntity::GetDmgPenetrationLevel() const
|
||||||
|
{
|
||||||
|
#ifdef REGAMEDLL_API
|
||||||
|
return m_pEntity->m_ucDmgPenetrationLevel;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
class CCSDelay: public CCSEntity
|
class CCSDelay: public CCSEntity
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include <API/CSPlayerItem.h>
|
#include <API/CSPlayerItem.h>
|
||||||
#include <API/CSPlayerWeapon.h>
|
#include <API/CSPlayerWeapon.h>
|
||||||
|
#include <utlarray.h>
|
||||||
|
|
||||||
enum WeaponInfiniteAmmoMode
|
enum WeaponInfiniteAmmoMode
|
||||||
{
|
{
|
||||||
@ -54,9 +55,17 @@ public:
|
|||||||
m_flJumpHeight(0),
|
m_flJumpHeight(0),
|
||||||
m_flLongJumpHeight(0),
|
m_flLongJumpHeight(0),
|
||||||
m_flLongJumpForce(0),
|
m_flLongJumpForce(0),
|
||||||
m_flDuckSpeedMultiplier(0)
|
m_flDuckSpeedMultiplier(0),
|
||||||
|
m_iUserID(-1)
|
||||||
{
|
{
|
||||||
m_szModel[0] = '\0';
|
m_szModel[0] = '\0';
|
||||||
|
|
||||||
|
// Resets the kill history for this player
|
||||||
|
for (int i = 0; i < MAX_CLIENTS; i++)
|
||||||
|
{
|
||||||
|
m_iNumKilledByUnanswered[i] = 0;
|
||||||
|
m_bPlayerDominated[i] = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool IsConnected() const;
|
virtual bool IsConnected() const;
|
||||||
@ -108,10 +117,15 @@ public:
|
|||||||
virtual void OnSpawnEquip(bool addDefault = true, bool equipGame = true);
|
virtual void OnSpawnEquip(bool addDefault = true, bool equipGame = true);
|
||||||
virtual void SetScoreboardAttributes(CBasePlayer *destination = nullptr);
|
virtual void SetScoreboardAttributes(CBasePlayer *destination = nullptr);
|
||||||
|
|
||||||
|
bool IsPlayerDominated(int iPlayerIndex) const;
|
||||||
|
void SetPlayerDominated(CBasePlayer *pPlayer, bool bDominated);
|
||||||
|
|
||||||
void ResetVars();
|
void ResetVars();
|
||||||
|
void ResetAllStats();
|
||||||
|
|
||||||
void OnSpawn();
|
void OnSpawn();
|
||||||
void OnKilled();
|
void OnKilled();
|
||||||
|
void OnConnect();
|
||||||
|
|
||||||
CBasePlayer *BasePlayer() const;
|
CBasePlayer *BasePlayer() const;
|
||||||
|
|
||||||
@ -144,6 +158,20 @@ public:
|
|||||||
double m_flLongJumpHeight;
|
double m_flLongJumpHeight;
|
||||||
double m_flLongJumpForce;
|
double m_flLongJumpForce;
|
||||||
double m_flDuckSpeedMultiplier;
|
double m_flDuckSpeedMultiplier;
|
||||||
|
|
||||||
|
int m_iUserID;
|
||||||
|
struct CDamageRecord_t
|
||||||
|
{
|
||||||
|
float flDamage = 0.0f;
|
||||||
|
float flFlashDurationTime = 0.0f;
|
||||||
|
int userId = -1;
|
||||||
|
};
|
||||||
|
using DamageList_t = CUtlArray<CDamageRecord_t, MAX_CLIENTS>;
|
||||||
|
DamageList_t m_DamageList; // A unified array of recorded damage that includes giver and taker in each entry
|
||||||
|
DamageList_t &GetDamageList() { return m_DamageList; }
|
||||||
|
void RecordDamage(CBasePlayer *pAttacker, float flDamage, float flFlashDurationTime = -1);
|
||||||
|
int m_iNumKilledByUnanswered[MAX_CLIENTS]; // [0-31] how many unanswered kills this player has been dealt by each other player
|
||||||
|
bool m_bPlayerDominated[MAX_CLIENTS]; // [0-31] array of state per other player whether player is dominating other players
|
||||||
};
|
};
|
||||||
|
|
||||||
// Inlines
|
// Inlines
|
||||||
@ -165,3 +193,20 @@ inline CCSPlayer::EProtectionState CCSPlayer::GetProtectionState() const
|
|||||||
// has expired
|
// has expired
|
||||||
return ProtectionSt_Expired;
|
return ProtectionSt_Expired;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns whether this player is dominating the specified other player
|
||||||
|
inline bool CCSPlayer::IsPlayerDominated(int iPlayerIndex) const
|
||||||
|
{
|
||||||
|
if (iPlayerIndex < 0 || iPlayerIndex >= MAX_CLIENTS)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return m_bPlayerDominated[iPlayerIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets whether this player is dominating the specified other player
|
||||||
|
inline void CCSPlayer::SetPlayerDominated(CBasePlayer *pPlayer, bool bDominated)
|
||||||
|
{
|
||||||
|
int iPlayerIndex = pPlayer->entindex();
|
||||||
|
assert(iPlayerIndex >= 0 && iPlayerIndex < MAX_CLIENTS);
|
||||||
|
m_bPlayerDominated[iPlayerIndex - 1] = bDominated;
|
||||||
|
}
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
#include <API/CSInterfaces.h>
|
#include <API/CSInterfaces.h>
|
||||||
|
|
||||||
#define REGAMEDLL_API_VERSION_MAJOR 5
|
#define REGAMEDLL_API_VERSION_MAJOR 5
|
||||||
#define REGAMEDLL_API_VERSION_MINOR 23
|
#define REGAMEDLL_API_VERSION_MINOR 24
|
||||||
|
|
||||||
// CBasePlayer::Spawn hook
|
// CBasePlayer::Spawn hook
|
||||||
typedef IHookChainClass<void, class CBasePlayer> IReGameHook_CBasePlayer_Spawn;
|
typedef IHookChainClass<void, class CBasePlayer> IReGameHook_CBasePlayer_Spawn;
|
||||||
@ -588,6 +588,10 @@ typedef IHookChainRegistry<BOOL, int, int> IReGameHookRegistry_CSGameRules_TeamS
|
|||||||
typedef IHookChain<void, CBasePlayer *, CBasePlayerItem *> IReGameHook_CSGameRules_PlayerGotWeapon;
|
typedef IHookChain<void, CBasePlayer *, CBasePlayerItem *> IReGameHook_CSGameRules_PlayerGotWeapon;
|
||||||
typedef IHookChainRegistry<void, CBasePlayer *, CBasePlayerItem *> IReGameHookRegistry_CSGameRules_PlayerGotWeapon;
|
typedef IHookChainRegistry<void, CBasePlayer *, CBasePlayerItem *> IReGameHookRegistry_CSGameRules_PlayerGotWeapon;
|
||||||
|
|
||||||
|
// CHalfLifeMultiplay::SendDeathMessage hook
|
||||||
|
typedef IHookChain<void, class CBaseEntity *, class CBasePlayer *, class CBasePlayer *, struct entvars_s *, const char *, int, int> IReGameHook_CSGameRules_SendDeathMessage;
|
||||||
|
typedef IHookChainRegistry<void, class CBaseEntity *, class CBasePlayer *, class CBasePlayer *, struct entvars_s *, const char *, int, int> IReGameHookRegistry_CSGameRules_SendDeathMessage;
|
||||||
|
|
||||||
// CBotManager::OnEvent hook
|
// CBotManager::OnEvent hook
|
||||||
typedef IHookChain<void, GameEventType, CBaseEntity *, CBaseEntity *> IReGameHook_CBotManager_OnEvent;
|
typedef IHookChain<void, GameEventType, CBaseEntity *, CBaseEntity *> IReGameHook_CBotManager_OnEvent;
|
||||||
typedef IHookChainRegistry<void, GameEventType, CBaseEntity*, CBaseEntity*> IReGameHookRegistry_CBotManager_OnEvent;
|
typedef IHookChainRegistry<void, GameEventType, CBaseEntity*, CBaseEntity*> IReGameHookRegistry_CBotManager_OnEvent;
|
||||||
@ -769,6 +773,7 @@ public:
|
|||||||
virtual IReGameHookRegistry_CBasePlayerWeapon_ItemPostFrame *CBasePlayerWeapon_ItemPostFrame() = 0;
|
virtual IReGameHookRegistry_CBasePlayerWeapon_ItemPostFrame *CBasePlayerWeapon_ItemPostFrame() = 0;
|
||||||
virtual IReGameHookRegistry_CBasePlayerWeapon_KickBack *CBasePlayerWeapon_KickBack() = 0;
|
virtual IReGameHookRegistry_CBasePlayerWeapon_KickBack *CBasePlayerWeapon_KickBack() = 0;
|
||||||
virtual IReGameHookRegistry_CBasePlayerWeapon_SendWeaponAnim *CBasePlayerWeapon_SendWeaponAnim() = 0;
|
virtual IReGameHookRegistry_CBasePlayerWeapon_SendWeaponAnim *CBasePlayerWeapon_SendWeaponAnim() = 0;
|
||||||
|
virtual IReGameHookRegistry_CSGameRules_SendDeathMessage *CSGameRules_SendDeathMessage() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ReGameFuncs_t {
|
struct ReGameFuncs_t {
|
||||||
|
235
regamedll/public/utlarray.h
Normal file
235
regamedll/public/utlarray.h
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||||
|
*
|
||||||
|
* This product contains software technology licensed from Id
|
||||||
|
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use, distribution, and modification of this source code and/or resulting
|
||||||
|
* object code is restricted to non-commercial enhancements to products from
|
||||||
|
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||||
|
* without written permission from Valve LLC.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// A growable array class that maintains a free list and keeps elements
|
||||||
|
// in the same location
|
||||||
|
#include "tier0/platform.h"
|
||||||
|
#include "tier0/dbg.h"
|
||||||
|
|
||||||
|
#define FOR_EACH_ARRAY(vecName, iteratorName)\
|
||||||
|
for (int iteratorName = 0; (vecName).IsUtlArray && iteratorName < (vecName).Count(); iteratorName++)
|
||||||
|
|
||||||
|
#define FOR_EACH_ARRAY_BACK(vecName, iteratorName)\
|
||||||
|
for (int iteratorName = (vecName).Count() - 1; (vecName).IsUtlArray && iteratorName >= 0; iteratorName--)
|
||||||
|
|
||||||
|
template <class T, size_t MAX_SIZE>
|
||||||
|
class CUtlArray
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef T ElemType_t;
|
||||||
|
enum { IsUtlArray = true }; // Used to match this at compiletime
|
||||||
|
|
||||||
|
CUtlArray();
|
||||||
|
CUtlArray(T *pMemory, size_t count);
|
||||||
|
~CUtlArray();
|
||||||
|
|
||||||
|
CUtlArray<T, MAX_SIZE> &operator=(const CUtlArray<T, MAX_SIZE> &other);
|
||||||
|
CUtlArray(CUtlArray const &vec);
|
||||||
|
|
||||||
|
// element access
|
||||||
|
T &operator[](int i);
|
||||||
|
const T &operator[](int i) const;
|
||||||
|
T &Element(int i);
|
||||||
|
const T &Element(int i) const;
|
||||||
|
T &Random();
|
||||||
|
const T &Random() const;
|
||||||
|
|
||||||
|
T *Base();
|
||||||
|
const T *Base() const;
|
||||||
|
|
||||||
|
// Returns the number of elements in the array, NumAllocated() is included for consistency with UtlVector
|
||||||
|
int Count() const;
|
||||||
|
int NumAllocated() const;
|
||||||
|
|
||||||
|
// Is element index valid?
|
||||||
|
bool IsValidIndex(int i) const;
|
||||||
|
static int InvalidIndex();
|
||||||
|
|
||||||
|
void CopyArray(const T *pArray, size_t count);
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
void RemoveAll();
|
||||||
|
void Swap(CUtlArray< T, MAX_SIZE> &vec);
|
||||||
|
|
||||||
|
// Finds an element (element needs operator== defined)
|
||||||
|
int Find(const T &src) const;
|
||||||
|
void FillWithValue(const T &src);
|
||||||
|
|
||||||
|
bool HasElement(const T &src) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
T m_Memory[MAX_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
inline CUtlArray<T, MAX_SIZE>::CUtlArray()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
inline CUtlArray<T, MAX_SIZE>::CUtlArray(T *pMemory, size_t count)
|
||||||
|
{
|
||||||
|
CopyArray(pMemory, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
inline CUtlArray<T, MAX_SIZE>::~CUtlArray()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
inline CUtlArray<T, MAX_SIZE> &CUtlArray<T, MAX_SIZE>::operator=(const CUtlArray<T, MAX_SIZE> &other)
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
for (size_t n = 0; n < MAX_SIZE; n++)
|
||||||
|
m_Memory[n] = other.m_Memory[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
inline CUtlArray<T, MAX_SIZE>::CUtlArray(CUtlArray const &vec)
|
||||||
|
{
|
||||||
|
for (size_t n = 0; n < MAX_SIZE; n++)
|
||||||
|
m_Memory[n] = vec.m_Memory[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
inline T *CUtlArray<T, MAX_SIZE>::Base()
|
||||||
|
{
|
||||||
|
return &m_Memory[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
inline const T *CUtlArray<T, MAX_SIZE>::Base() const
|
||||||
|
{
|
||||||
|
return &m_Memory[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Element access
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
inline T &CUtlArray<T, MAX_SIZE>::operator[](int i)
|
||||||
|
{
|
||||||
|
Assert(IsValidIndex(i));
|
||||||
|
return m_Memory[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
inline const T &CUtlArray<T, MAX_SIZE>::operator[](int i) const
|
||||||
|
{
|
||||||
|
Assert(IsValidIndex(i));
|
||||||
|
return m_Memory[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
inline T &CUtlArray<T, MAX_SIZE>::Element(int i)
|
||||||
|
{
|
||||||
|
Assert(IsValidIndex(i));
|
||||||
|
return m_Memory[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
inline const T &CUtlArray<T, MAX_SIZE>::Element(int i) const
|
||||||
|
{
|
||||||
|
Assert(IsValidIndex(i));
|
||||||
|
return m_Memory[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
inline int CUtlArray<T, MAX_SIZE>::Count() const
|
||||||
|
{
|
||||||
|
return (int)MAX_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
inline int CUtlArray<T, MAX_SIZE>::NumAllocated() const
|
||||||
|
{
|
||||||
|
return (int)MAX_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is element index valid?
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
inline bool CUtlArray<T, MAX_SIZE>::IsValidIndex(int i) const
|
||||||
|
{
|
||||||
|
return (i >= 0) && (i < MAX_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns in invalid index
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
inline int CUtlArray<T, MAX_SIZE>::InvalidIndex()
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
void CUtlArray<T, MAX_SIZE>::CopyArray(const T *pArray, size_t count)
|
||||||
|
{
|
||||||
|
Assert(count < MAX_SIZE);
|
||||||
|
|
||||||
|
for (size_t n = 0; n < count; n++)
|
||||||
|
m_Memory[n] = pArray[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
void CUtlArray<T, MAX_SIZE>::Clear()
|
||||||
|
{
|
||||||
|
Q_memset(m_Memory, 0, MAX_SIZE * sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
void CUtlArray<T, MAX_SIZE>::RemoveAll()
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
void CUtlArray<T, MAX_SIZE>::Swap(CUtlArray< T, MAX_SIZE> &vec)
|
||||||
|
{
|
||||||
|
for (size_t n = 0; n < MAX_SIZE; n++)
|
||||||
|
SWAP(m_Memory[n], vec.m_Memory[n]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finds an element (element needs operator== defined)
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
int CUtlArray<T, MAX_SIZE>::Find(const T &src) const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Count(); i++)
|
||||||
|
{
|
||||||
|
if (Element(i) == src)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
void CUtlArray<T, MAX_SIZE>::FillWithValue(const T &src)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Count(); i++)
|
||||||
|
Element(i) = src;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t MAX_SIZE>
|
||||||
|
bool CUtlArray<T, MAX_SIZE>::HasElement(const T &src) const
|
||||||
|
{
|
||||||
|
return (Find(src) >= 0);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user