Skip to content

Commit

Permalink
Add domination and revenge
Browse files Browse the repository at this point in the history
  • Loading branch information
s1lentq committed Sep 13, 2023
1 parent 8ec281c commit ca49352
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 3 deletions.
11 changes: 11 additions & 0 deletions regamedll/dlls/API/CSPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,17 @@ 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;
Expand Down
8 changes: 7 additions & 1 deletion regamedll/dlls/gamerules.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ 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]
Expand All @@ -245,7 +249,9 @@ enum KillRarity
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_ASSIST_FLASH = 0x020, // The killer player kills the victim with an assistant flashbang grenade
KILLRARITY_DOMINATION = 0x040, // The killer player kills is dominating victim
KILLRARITY_REVENGE = 0x080 // The killer player kills got revenge on victim
};

class CItem;
Expand Down
48 changes: 46 additions & 2 deletions regamedll/dlls/multiplay_gamerules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4082,7 +4082,7 @@ LINK_HOOK_CLASS_VOID_CUSTOM_CHAIN(CHalfLifeMultiplay, CSGameRules, DeathNotice,
void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(DeathNotice)(CBasePlayer *pVictim, entvars_t *pevKiller, entvars_t *pevInflictor)
{
// by default, the player is killed by the world
CBaseEntity *pKiller = (pevKiller->flags & FL_CLIENT) ? CBaseEntity::Instance(pevKiller) : nullptr;
CBasePlayer *pKiller = (pevKiller->flags & FL_CLIENT) ? CBasePlayer::Instance(pevKiller) : nullptr;
const char *killer_weapon_name = pVictim->GetKillerWeaponName(pevInflictor, pevKiller);

if (!TheTutor)
Expand All @@ -4108,6 +4108,16 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(DeathNotice)(CBasePlayer *pVictim,
}

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(pKiller ? pKiller->entindex() : 0); // the killer
Expand All @@ -4129,7 +4139,7 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(DeathNotice)(CBasePlayer *pVictim,
else if (pevKiller->flags & FL_CLIENT)
{
const char *VictimTeam = GetTeam(pVictim->m_iTeam);
const char *KillerTeam = (pKiller && pKiller->IsPlayer()) ? GetTeam(((CBasePlayer *)pKiller)->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(pevKiller->netname), GETPLAYERUSERID(ENT(pevKiller)), GETPLAYERAUTHID(ENT(pevKiller)),
KillerTeam, STRING(pVictim->pev->netname), GETPLAYERUSERID(pVictim->edict()), GETPLAYERAUTHID(pVictim->edict()), VictimTeam, killer_weapon_name);
Expand Down Expand Up @@ -5272,6 +5282,31 @@ int CHalfLifeMultiplay::GetRarityOfKill(CBaseEntity *pKiller, CBasePlayer *pVict
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;
Expand Down Expand Up @@ -5319,6 +5354,15 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(SendDeathMessage)(CBaseEntity *pKil
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
Expand Down
2 changes: 2 additions & 0 deletions regamedll/dlls/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6008,6 +6008,8 @@ void CBasePlayer::Reset()
if (CSPlayer()->GetProtectionState() == CCSPlayer::ProtectionSt_Active) {
RemoveSpawnProtection();
}

CSPlayer()->ResetAllStats();
#endif
}

Expand Down
31 changes: 31 additions & 0 deletions regamedll/public/regamedll/API/CSPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ class CCSPlayer: public CCSMonster {
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;
Expand Down Expand Up @@ -110,11 +117,16 @@ class CCSPlayer: public CCSMonster {
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;

public:
Expand Down Expand Up @@ -158,6 +170,8 @@ class CCSPlayer: public CCSMonster {
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
Expand All @@ -179,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;
}

0 comments on commit ca49352

Please sign in to comment.