mirror of
https://github.com/s1lentq/ReGameDLL_CS.git
synced 2025-01-13 23:28:04 +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_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?
|
||||
|
16
dist/game.cfg
vendored
16
dist/game.cfg
vendored
@ -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"
|
||||
|
@ -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();
|
||||
}
|
||||
@ -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);
|
||||
@ -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;
|
||||
|
@ -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;
|
||||
@ -865,7 +869,7 @@ public:
|
||||
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;
|
||||
@ -889,6 +893,7 @@ public:
|
||||
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();
|
||||
@ -1044,6 +1049,7 @@ public:
|
||||
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;
|
||||
|
@ -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()
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
@ -1340,6 +1340,7 @@ VectorRef CBaseEntity::__API_HOOK(FireBullets3)(VectorRef vecSrc, VectorRef vecD
|
||||
|
||||
float flDamageModifier = 0.5;
|
||||
|
||||
int iStartPenetration = iPenetration;
|
||||
while (iPenetration != 0)
|
||||
{
|
||||
ClearMultiDamage();
|
||||
@ -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;
|
||||
@ -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;
|
||||
}
|
||||
|
@ -242,6 +242,10 @@ public:
|
||||
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;
|
||||
|
@ -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>");
|
||||
|
@ -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)
|
||||
@ -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)
|
||||
{
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
@ -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 };
|
||||
|
||||
@ -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");
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
@ -574,6 +608,7 @@ public:
|
||||
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:
|
||||
@ -698,6 +733,10 @@ public:
|
||||
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);
|
||||
|
||||
|
@ -2035,7 +2035,7 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(RestartRound)()
|
||||
#endif
|
||||
|
||||
pPlayer->RoundRespawn();
|
||||
|
||||
|
||||
#ifdef REGAMEDLL_ADD
|
||||
FireTargets("game_entity_restart", pPlayer, nullptr, USE_TOGGLE, 0.0);
|
||||
#endif
|
||||
@ -3922,7 +3922,7 @@ LINK_HOOK_CLASS_VOID_CUSTOM_CHAIN(CHalfLifeMultiplay, CSGameRules, PlayerKilled,
|
||||
void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(PlayerKilled)(CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor)
|
||||
{
|
||||
DeathNotice(pVictim, pKiller, pInflictor);
|
||||
#ifdef REGAMEDLL_FIXES
|
||||
#ifdef REGAMEDLL_FIXES
|
||||
pVictim->pev->flags &= ~FL_FROZEN;
|
||||
#endif
|
||||
pVictim->m_afPhysicsFlags &= ~PFLAG_ONTRAIN;
|
||||
@ -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)
|
||||
|
||||
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
|
||||
const char *killer_weapon_name = "world";
|
||||
int killer_index = 0;
|
||||
|
||||
#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;
|
||||
CBasePlayer *pKiller = (pevKiller->flags & FL_CLIENT) ? CBasePlayer::Instance(pevKiller) : nullptr;
|
||||
const char *killer_weapon_name = pVictim->GetKillerWeaponName(pevInflictor, pevKiller);
|
||||
|
||||
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);
|
||||
WRITE_BYTE(killer_index); // the killer
|
||||
WRITE_BYTE(ENTINDEX(pVictim->edict())); // the victim
|
||||
WRITE_BYTE(pVictim->m_bHeadshotKilled); // is killed headshot
|
||||
WRITE_STRING(killer_weapon_name); // what they were killed by (should this be a string?)
|
||||
WRITE_BYTE(pKiller ? pKiller->entindex() : 0); // the killer
|
||||
WRITE_BYTE(ENTINDEX(pVictim->edict())); // the victim
|
||||
WRITE_BYTE(pVictim->m_bHeadshotKilled); // is killed headshot
|
||||
WRITE_STRING(killer_weapon_name); // what they were killed by (should this be a string?)
|
||||
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?
|
||||
if (pVictim->pev == pKiller)
|
||||
if (pVictim->pev == pevKiller)
|
||||
{
|
||||
// killed self
|
||||
char *team = GetTeam(pVictim->m_iTeam);
|
||||
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);
|
||||
}
|
||||
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 *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);
|
||||
}
|
||||
else
|
||||
@ -4197,7 +4164,7 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(DeathNotice)(CBasePlayer *pVictim,
|
||||
if (pevInflictor)
|
||||
WRITE_SHORT(ENTINDEX(ENT(pevInflictor))); // index number of secondary entity
|
||||
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)
|
||||
WRITE_LONG(9 | DRC_FLAG_DRAMATIC | DRC_FLAG_SLOWMOTION);
|
||||
@ -4345,11 +4312,11 @@ int EXT_FUNC CHalfLifeMultiplay::__API_HOOK(DeadPlayerWeapons)(CBasePlayer *pPla
|
||||
{
|
||||
case 3:
|
||||
return GR_PLR_DROP_GUN_ALL;
|
||||
case 2:
|
||||
case 2:
|
||||
break;
|
||||
case 1:
|
||||
return GR_PLR_DROP_GUN_BEST;
|
||||
default:
|
||||
default:
|
||||
return GR_PLR_DROP_GUN_NO;
|
||||
}
|
||||
#endif
|
||||
@ -5204,3 +5171,226 @@ bool CHalfLifeMultiplay::CanPlayerBuy(CBasePlayer *pPlayer) const
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
const char *killer_weapon_name = "world";
|
||||
|
||||
// Is the killer a client?
|
||||
if (pKiller->flags & FL_CLIENT)
|
||||
if (pevKiller->flags & FL_CLIENT)
|
||||
{
|
||||
if (pevInflictor)
|
||||
{
|
||||
if (pevInflictor == pKiller)
|
||||
if (pevInflictor == pevKiller)
|
||||
{
|
||||
// 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())
|
||||
#ifdef REGAMEDLL_FIXES
|
||||
// Ignore the inflictor's weapon if victim killed self
|
||||
if (pevKiller != pev)
|
||||
#endif
|
||||
{
|
||||
if (pAttacker->m_pActiveItem)
|
||||
killer_weapon_name = pAttacker->m_pActiveItem->pszName();
|
||||
// If the inflictor is the killer, then it must be their current weapon doing the damage
|
||||
CBasePlayer *pAttacker = CBasePlayer::Instance(pevKiller);
|
||||
if (pAttacker && pAttacker->IsPlayer())
|
||||
{
|
||||
if (pAttacker->m_pActiveItem)
|
||||
killer_weapon_name = pAttacker->m_pActiveItem->pszName();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -781,10 +787,11 @@ const char *GetWeaponName(entvars_t *pevInflictor, entvars_t *pKiller)
|
||||
}
|
||||
|
||||
// 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_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))
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (bTookDamage)
|
||||
@ -970,9 +977,13 @@ BOOL EXT_FUNC CBasePlayer::__API_HOOK(TakeDamage)(entvars_t *pevInflictor, entva
|
||||
CBasePlayer *pPlayerAttacker = CBasePlayer::Instance(pevAttacker);
|
||||
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
|
||||
}
|
||||
|
||||
{
|
||||
@ -1191,11 +1202,11 @@ BOOL EXT_FUNC CBasePlayer::__API_HOOK(TakeDamage)(entvars_t *pevInflictor, entva
|
||||
{
|
||||
Pain(m_LastHitGroup, false);
|
||||
}
|
||||
|
||||
|
||||
// keep track of amount of damage last sustained
|
||||
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
|
||||
// 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);
|
||||
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
|
||||
}
|
||||
|
||||
{
|
||||
@ -1415,12 +1430,12 @@ void CBasePlayer::PackDeadPlayerItems()
|
||||
int nBestWeight = 0;
|
||||
CBasePlayerItem *pBestItem = nullptr;
|
||||
|
||||
#ifdef REGAMEDLL_ADD
|
||||
#ifdef REGAMEDLL_ADD
|
||||
int iGunsPacked = 0;
|
||||
|
||||
if (iPackGun == GR_PLR_DROP_GUN_ACTIVE)
|
||||
if (iPackGun == GR_PLR_DROP_GUN_ACTIVE)
|
||||
{
|
||||
// check if we've just already dropped our active gun
|
||||
// check if we've just already dropped our active gun
|
||||
if (!bSkipPrimSec && m_pActiveItem && m_pActiveItem->CanDrop() && m_pActiveItem->iItemSlot() < KNIFE_SLOT)
|
||||
{
|
||||
pBestItem = m_pActiveItem;
|
||||
@ -1429,7 +1444,7 @@ void CBasePlayer::PackDeadPlayerItems()
|
||||
}
|
||||
|
||||
// are we allowing nade drop?
|
||||
if ((int)nadedrops.value >= 1)
|
||||
if ((int)nadedrops.value >= 1)
|
||||
{
|
||||
// goto item loop but skip guns
|
||||
iPackGun = GR_PLR_DROP_GUN_ALL;
|
||||
@ -1460,7 +1475,7 @@ void CBasePlayer::PackDeadPlayerItems()
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#ifdef REGAMEDLL_ADD
|
||||
#ifdef REGAMEDLL_ADD
|
||||
if (iPackGun == GR_PLR_DROP_GUN_ALL)
|
||||
{
|
||||
CBasePlayerItem *pNext = pPlayerItem->m_pNext;
|
||||
@ -1469,10 +1484,10 @@ void CBasePlayer::PackDeadPlayerItems()
|
||||
if (pWeaponBox)
|
||||
{
|
||||
// just push a few units in forward to separate them
|
||||
pWeaponBox->pev->velocity = pWeaponBox->pev->velocity * (1.0 + (iGunsPacked * 0.2));
|
||||
pWeaponBox->pev->velocity = pWeaponBox->pev->velocity * (1.0 + (iGunsPacked * 0.2));
|
||||
iGunsPacked++;
|
||||
}
|
||||
|
||||
|
||||
pPlayerItem = pNext;
|
||||
continue;
|
||||
}
|
||||
@ -2113,7 +2128,7 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib)
|
||||
if (IsBot() && IsBlind()) // dystopm: shouldn't be !IsBot() ?
|
||||
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
|
||||
@ -2144,7 +2159,7 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2426,7 +2441,7 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib)
|
||||
|
||||
#ifndef REGAMEDLL_FIXES
|
||||
// NOTE: moved to RemoveDefuser
|
||||
m_bIsDefusing = false;
|
||||
m_bIsDefusing = false;
|
||||
#endif
|
||||
|
||||
BuyZoneIcon_Clear(this);
|
||||
@ -3621,7 +3636,7 @@ void EXT_FUNC CBasePlayer::__API_HOOK(JoiningThink)()
|
||||
|
||||
#ifndef REGAMEDLL_FIXES
|
||||
// NOTE: client already clears StatusIcon on join
|
||||
MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, nullptr, pev);
|
||||
MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, nullptr, pev);
|
||||
WRITE_BYTE(STATUSICON_HIDE);
|
||||
WRITE_STRING("defuser");
|
||||
MESSAGE_END();
|
||||
@ -4629,7 +4644,7 @@ void EXT_FUNC CBasePlayer::__API_HOOK(PreThink)()
|
||||
m_afPhysicsFlags &= ~PFLAG_ONTRAIN;
|
||||
m_iTrain = (TRAIN_NEW | TRAIN_OFF);
|
||||
|
||||
#ifdef REGAMEDLL_FIXES
|
||||
#ifdef REGAMEDLL_FIXES
|
||||
if (pTrain && pTrain->Classify() == CLASS_VEHICLE) // ensure func_vehicle's m_pDriver assignation
|
||||
#endif
|
||||
{
|
||||
@ -4648,7 +4663,7 @@ void EXT_FUNC CBasePlayer::__API_HOOK(PreThink)()
|
||||
m_afPhysicsFlags &= ~PFLAG_ONTRAIN;
|
||||
m_iTrain = (TRAIN_NEW | TRAIN_OFF);
|
||||
|
||||
#ifdef REGAMEDLL_FIXES
|
||||
#ifdef REGAMEDLL_FIXES
|
||||
if (pTrain->Classify() == CLASS_VEHICLE) // ensure func_vehicle's m_pDriver assignation
|
||||
#endif
|
||||
{
|
||||
@ -5154,7 +5169,17 @@ void EXT_FUNC CBasePlayer::__API_HOOK(PostThink)()
|
||||
#endif
|
||||
{
|
||||
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;
|
||||
if (TheBots)
|
||||
{
|
||||
@ -5983,6 +6008,8 @@ void CBasePlayer::Reset()
|
||||
if (CSPlayer()->GetProtectionState() == CCSPlayer::ProtectionSt_Active) {
|
||||
RemoveSpawnProtection();
|
||||
}
|
||||
|
||||
CSPlayer()->ResetAllStats();
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -8818,22 +8845,22 @@ void CBasePlayer::SpawnClientSideCorpse()
|
||||
char *pModel = GET_KEY_VALUE(infobuffer, "model");
|
||||
float timeDiff = pev->animtime - gpGlobals->time;
|
||||
|
||||
#ifdef REGAMEDLL_ADD
|
||||
#ifdef REGAMEDLL_ADD
|
||||
if (CGameRules::GetDyingTime() < DEATH_ANIMATION_TIME) // a short time, timeDiff estimates to be small
|
||||
{
|
||||
float animDuration = GetDyingAnimationDuration();
|
||||
|
||||
// client receives a negative value
|
||||
animDuration *= -1.0;
|
||||
// client receives a negative value
|
||||
animDuration *= -1.0;
|
||||
|
||||
if (animDuration < timeDiff) // reasonable way to fix client side unfinished sequence bug
|
||||
{
|
||||
// by some reason, if client receives a value less
|
||||
// than "(negative current sequence time) * 100"
|
||||
// by some reason, if client receives a value less
|
||||
// than "(negative current sequence time) * 100"
|
||||
// animation will play visually awkward
|
||||
// at this function call time, player death animation
|
||||
// at this function call time, player death animation
|
||||
// has already finished so we can safely fake it
|
||||
timeDiff = animDuration;
|
||||
timeDiff = animDuration;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -8856,7 +8883,7 @@ void CBasePlayer::SpawnClientSideCorpse()
|
||||
#ifndef REGAMEDLL_FIXES
|
||||
// already defined in StartDeathCam
|
||||
m_canSwitchObserverModes = true;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (TheTutor)
|
||||
{
|
||||
@ -10123,7 +10150,7 @@ void CBasePlayer::RemoveDefuser()
|
||||
SetProgressBarTime(0);
|
||||
m_bIsDefusing = false;
|
||||
}
|
||||
#else
|
||||
#else
|
||||
SetProgressBarTime(0);
|
||||
#endif
|
||||
}
|
||||
@ -10449,10 +10476,10 @@ bool CBasePlayer::Kill()
|
||||
{
|
||||
if (GetObserverMode() != OBS_NONE)
|
||||
return false;
|
||||
|
||||
|
||||
if (m_iJoiningState != JOINED)
|
||||
return false;
|
||||
|
||||
|
||||
m_LastHitGroup = HITGROUP_GENERIC;
|
||||
|
||||
// have the player kill himself
|
||||
@ -10461,6 +10488,6 @@ bool CBasePlayer::Kill()
|
||||
|
||||
if (CSGameRules()->m_pVIP == this)
|
||||
CSGameRules()->m_iConsecutiveVIP = 10;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -637,6 +637,7 @@ public:
|
||||
bool GetIntoGame();
|
||||
bool ShouldToShowAccount(CBasePlayer *pReceiver) const;
|
||||
bool ShouldToShowHealthInfo(CBasePlayer *pReceiver) const;
|
||||
const char *GetKillerWeaponName(entvars_t *pevInflictor, entvars_t *pevKiller) const;
|
||||
|
||||
CBasePlayerItem *GetItemByName(const char *itemName);
|
||||
CBasePlayerItem *GetItemById(WeaponIdType weaponID);
|
||||
@ -1000,7 +1001,6 @@ void SendItemStatus(CBasePlayer *pPlayer);
|
||||
const char *GetCSModelName(int item_id);
|
||||
Vector VecVelocityForDamage(float flDamage);
|
||||
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);
|
||||
bool CanSeeUseable(CBasePlayer *me, CBaseEntity *pEntity);
|
||||
void FixPlayerCrouchStuck(edict_t *pPlayer);
|
||||
|
@ -93,7 +93,7 @@ void EXT_FUNC __API_HOOK(ApplyMultiDamage)(entvars_t *pevInflictor, entvars_t *p
|
||||
return;
|
||||
|
||||
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)
|
||||
|
@ -46,7 +46,7 @@
|
||||
<ClCompile Include="..\dlls\API\CSPlayerItem.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Tests|Win32'">
|
||||
</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\dlls\API\CSPlayerWeapon.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Tests|Win32'">
|
||||
</ExcludedFromBuild>
|
||||
@ -787,6 +787,7 @@
|
||||
<ClInclude Include="..\public\regamedll\regamedll_api.h" />
|
||||
<ClInclude Include="..\public\tier0\dbg.h" />
|
||||
<ClInclude Include="..\public\tier0\platform.h" />
|
||||
<ClInclude Include="..\public\utlarray.h" />
|
||||
<ClInclude Include="..\public\utlmemory.h" />
|
||||
<ClInclude Include="..\public\utlrbtree.h" />
|
||||
<ClInclude Include="..\public\utlsymbol.h" />
|
||||
@ -1124,4 +1125,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
@ -1052,5 +1052,8 @@
|
||||
<ClInclude Include="..\dlls\addons\point_command.h">
|
||||
<Filter>dlls\addons</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\public\utlarray.h">
|
||||
<Filter>public</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -35,6 +35,7 @@ public:
|
||||
CCSEntity() :
|
||||
m_pContainingEntity(nullptr)
|
||||
{
|
||||
m_ucDmgPenetrationLevel = 0;
|
||||
}
|
||||
|
||||
virtual ~CCSEntity() {}
|
||||
@ -44,12 +45,14 @@ public:
|
||||
|
||||
public:
|
||||
CBaseEntity *m_pContainingEntity;
|
||||
unsigned char m_ucDmgPenetrationLevel; // penetration level of the damage caused by the inflictor
|
||||
|
||||
private:
|
||||
#if defined(_MSC_VER)
|
||||
#pragma region reserve_data_Region
|
||||
#endif
|
||||
int CCSEntity_Reserve[0x1000];
|
||||
char CCSEntity_Reserve[0x3FFF];
|
||||
|
||||
virtual void func_reserve1() {};
|
||||
virtual void func_reserve2() {};
|
||||
virtual void func_reserve3() {};
|
||||
@ -85,6 +88,29 @@ private:
|
||||
#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
|
||||
{
|
||||
public:
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include <API/CSPlayerItem.h>
|
||||
#include <API/CSPlayerWeapon.h>
|
||||
#include <utlarray.h>
|
||||
|
||||
enum WeaponInfiniteAmmoMode
|
||||
{
|
||||
@ -54,9 +55,17 @@ public:
|
||||
m_flJumpHeight(0),
|
||||
m_flLongJumpHeight(0),
|
||||
m_flLongJumpForce(0),
|
||||
m_flDuckSpeedMultiplier(0)
|
||||
m_flDuckSpeedMultiplier(0),
|
||||
m_iUserID(-1)
|
||||
{
|
||||
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;
|
||||
@ -108,10 +117,15 @@ public:
|
||||
virtual void OnSpawnEquip(bool addDefault = true, bool equipGame = true);
|
||||
virtual void SetScoreboardAttributes(CBasePlayer *destination = nullptr);
|
||||
|
||||
bool IsPlayerDominated(int iPlayerIndex) const;
|
||||
void SetPlayerDominated(CBasePlayer *pPlayer, bool bDominated);
|
||||
|
||||
void ResetVars();
|
||||
void ResetAllStats();
|
||||
|
||||
void OnSpawn();
|
||||
void OnKilled();
|
||||
void OnConnect();
|
||||
|
||||
CBasePlayer *BasePlayer() const;
|
||||
|
||||
@ -140,10 +154,24 @@ public:
|
||||
bool m_bMegaBunnyJumping;
|
||||
bool m_bPlantC4Anywhere;
|
||||
bool m_bSpawnProtectionEffects;
|
||||
double m_flJumpHeight;
|
||||
double m_flLongJumpHeight;
|
||||
double m_flJumpHeight;
|
||||
double m_flLongJumpHeight;
|
||||
double m_flLongJumpForce;
|
||||
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
|
||||
@ -165,3 +193,20 @@ inline CCSPlayer::EProtectionState CCSPlayer::GetProtectionState() const
|
||||
// has 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>
|
||||
|
||||
#define REGAMEDLL_API_VERSION_MAJOR 5
|
||||
#define REGAMEDLL_API_VERSION_MINOR 23
|
||||
#define REGAMEDLL_API_VERSION_MINOR 24
|
||||
|
||||
// CBasePlayer::Spawn hook
|
||||
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 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
|
||||
typedef IHookChain<void, GameEventType, CBaseEntity *, CBaseEntity *> IReGameHook_CBotManager_OnEvent;
|
||||
typedef IHookChainRegistry<void, GameEventType, CBaseEntity*, CBaseEntity*> IReGameHookRegistry_CBotManager_OnEvent;
|
||||
@ -759,7 +763,7 @@ public:
|
||||
virtual IReGameHookRegistry_AddMultiDamage *AddMultiDamage() = 0;
|
||||
virtual IReGameHookRegistry_ApplyMultiDamage *ApplyMultiDamage() = 0;
|
||||
virtual IReGameHookRegistry_BuyItem *BuyItem() = 0;
|
||||
virtual IReGameHookRegistry_CSGameRules_Think *CSGameRules_Think() = 0;
|
||||
virtual IReGameHookRegistry_CSGameRules_Think *CSGameRules_Think() = 0;
|
||||
virtual IReGameHookRegistry_CSGameRules_TeamFull *CSGameRules_TeamFull() = 0;
|
||||
virtual IReGameHookRegistry_CSGameRules_TeamStacked *CSGameRules_TeamStacked() = 0;
|
||||
virtual IReGameHookRegistry_CSGameRules_PlayerGotWeapon *CSGameRules_PlayerGotWeapon() = 0;
|
||||
@ -769,6 +773,7 @@ public:
|
||||
virtual IReGameHookRegistry_CBasePlayerWeapon_ItemPostFrame *CBasePlayerWeapon_ItemPostFrame() = 0;
|
||||
virtual IReGameHookRegistry_CBasePlayerWeapon_KickBack *CBasePlayerWeapon_KickBack() = 0;
|
||||
virtual IReGameHookRegistry_CBasePlayerWeapon_SendWeaponAnim *CBasePlayerWeapon_SendWeaponAnim() = 0;
|
||||
virtual IReGameHookRegistry_CSGameRules_SendDeathMessage *CSGameRules_SendDeathMessage() = 0;
|
||||
};
|
||||
|
||||
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