New CVars: mp_weapondrop and mp_ammodrop and fixes (#840)

* First implementation

* Update player.cpp

* Apply suggestions from code review

Co-authored-by: Sergey Shorokhov <wopox1337@ya.ru>

* Improve readability

* Improve readability x2

Co-authored-by: Sergey Shorokhov <wopox1337@ya.ru>

* Tabulation tip

* Compile error resolved

* Add mp_weapondrop 3: drop all weapons

---------

Co-authored-by: Sergey Shorokhov <wopox1337@ya.ru>
This commit is contained in:
Francisco Muñoz 2023-07-10 08:45:24 -04:00 committed by GitHub
parent d4deabfe59
commit 8ddda261fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 166 additions and 49 deletions

View File

@ -45,6 +45,8 @@ This means that plugins that do binary code analysis (Orpheu for example) probab
| mp_round_restart_delay | 5 | - | - | Number of seconds to delay before restarting a round after a win. | | mp_round_restart_delay | 5 | - | - | Number of seconds to delay before restarting a round after a win. |
| mp_hegrenade_penetration | 0 | 0 | 1 | Disable grenade damage through walls.<br/>`0` disabled<br/>`1` enabled | | mp_hegrenade_penetration | 0 | 0 | 1 | Disable grenade damage through walls.<br/>`0` disabled<br/>`1` enabled |
| mp_nadedrops | 0 | 0 | 2 | Drop a grenade after player death.<br/>`0` disabled<br/>`1` drop first available grenade<br/>`2` drop all grenades | | mp_nadedrops | 0 | 0 | 2 | Drop a grenade after player death.<br/>`0` disabled<br/>`1` drop first available grenade<br/>`2` drop all grenades |
| mp_weapondrop | 1 | 0 | 3 | Drop player weapon after death.<br/>`0` do not drop weapons after death<br/>`1` drop best/heaviest weapon after death<br/>`2` drop active weapon after death<br/>`3` drop all weapons after death (primary and secondary) |
| mp_ammodrop | 1 | 0 | 2 | Drop ammo on weapon boxes on death or manual drop.<br/>`0` always keep ammo on player<br/>`1` drop all ammo only after death<br/>`2` drop all ammo whenever player drops a weapon |
| mp_roundrespawn_time | 20 | 0 | - | Player cannot respawn until next round if more than N seconds has elapsed since the beginning round.<br />`-1` means no time limit<br /> | | mp_roundrespawn_time | 20 | 0 | - | Player cannot respawn until next round if more than N seconds has elapsed since the beginning round.<br />`-1` means no time limit<br /> |
| mp_auto_reload_weapons | 0 | 0 | 1 | Automatically reload each weapon on player spawn.<br/>`0` disabled<br/>`1` enabled | | mp_auto_reload_weapons | 0 | 0 | 1 | Automatically reload each weapon on player spawn.<br/>`0` disabled<br/>`1` enabled |
| mp_refill_bpammo_weapons | 0 | 0 | 2 | Refill amount of backpack ammo up to the max.<br/>`0` disabled<br/>`1` refill backpack ammo on player spawn<br/>`2` refill backpack ammo on player spawn and on the purchase of the item | | mp_refill_bpammo_weapons | 0 | 0 | 2 | Refill amount of backpack ammo up to the max.<br/>`0` disabled<br/>`1` refill backpack ammo on player spawn<br/>`2` refill backpack ammo on player spawn and on the purchase of the item |

18
dist/game.cfg vendored
View File

@ -78,6 +78,24 @@ mp_hegrenade_penetration "0"
// Default value: "0" // Default value: "0"
mp_nadedrops "0" mp_nadedrops "0"
// Drop player weapon after death
// 0 - do not drop weapons after death
// 1 - drop best/heaviest weapon after death (default behaviour)
// 2 - drop active weapon after death
// 3 - drop all weapons after death (primary and secondary)
// NOTE: Grenades are dropped separately depending on mp_nadedrops value
//
// Default value: "1"
mp_weapondrop "1"
// Drop ammo on weapon boxes on death or manual drop
// 0 - always keep ammo on player
// 1 - drop all ammo only after death (default behaviour)
// 2 - drop all ammo whenever player drops a weapon (NOTE: Other weapons may remain without ammo due to same ammo sharing)
//
// Default value: "1"
mp_ammodrop "1"
// Player cannot respawn until next round // Player cannot respawn until next round
// if more than N seconds has elapsed since the beginning round // if more than N seconds has elapsed since the beginning round
// -1 - means no time limit // -1 - means no time limit

View File

@ -109,6 +109,8 @@ cvar_t maxmoney = { "mp_maxmoney", "16000", FCVAR_SERVER, 0.0f, nul
cvar_t round_infinite = { "mp_round_infinite", "0", FCVAR_SERVER, 0.0f, nullptr }; cvar_t round_infinite = { "mp_round_infinite", "0", FCVAR_SERVER, 0.0f, nullptr };
cvar_t hegrenade_penetration = { "mp_hegrenade_penetration", "0", 0, 0.0f, nullptr }; cvar_t hegrenade_penetration = { "mp_hegrenade_penetration", "0", 0, 0.0f, nullptr };
cvar_t nadedrops = { "mp_nadedrops", "0", 0, 0.0f, nullptr }; cvar_t nadedrops = { "mp_nadedrops", "0", 0, 0.0f, nullptr };
cvar_t weapondrop = { "mp_weapondrop", "1", 0, 1.0f, nullptr };
cvar_t ammodrop = { "mp_ammodrop", "1", 0, 1.0f, nullptr };
cvar_t roundrespawn_time = { "mp_roundrespawn_time", "20", 0, 20.0f, nullptr }; cvar_t roundrespawn_time = { "mp_roundrespawn_time", "20", 0, 20.0f, nullptr };
cvar_t auto_reload_weapons = { "mp_auto_reload_weapons", "0", 0, 0.0f, nullptr }; cvar_t auto_reload_weapons = { "mp_auto_reload_weapons", "0", 0, 0.0f, nullptr };
cvar_t refill_bpammo_weapons = { "mp_refill_bpammo_weapons", "0", 0, 0.0f, nullptr }; // Useful for mods like DeathMatch, GunGame, ZombieMod etc cvar_t refill_bpammo_weapons = { "mp_refill_bpammo_weapons", "0", 0, 0.0f, nullptr }; // Useful for mods like DeathMatch, GunGame, ZombieMod etc
@ -351,6 +353,8 @@ void EXT_FUNC GameDLLInit()
CVAR_REGISTER(&round_infinite); CVAR_REGISTER(&round_infinite);
CVAR_REGISTER(&hegrenade_penetration); CVAR_REGISTER(&hegrenade_penetration);
CVAR_REGISTER(&nadedrops); CVAR_REGISTER(&nadedrops);
CVAR_REGISTER(&weapondrop);
CVAR_REGISTER(&ammodrop);
CVAR_REGISTER(&roundrespawn_time); CVAR_REGISTER(&roundrespawn_time);
CVAR_REGISTER(&auto_reload_weapons); CVAR_REGISTER(&auto_reload_weapons);
CVAR_REGISTER(&refill_bpammo_weapons); CVAR_REGISTER(&refill_bpammo_weapons);

View File

@ -138,6 +138,8 @@ extern cvar_t maxmoney;
extern cvar_t round_infinite; extern cvar_t round_infinite;
extern cvar_t hegrenade_penetration; extern cvar_t hegrenade_penetration;
extern cvar_t nadedrops; extern cvar_t nadedrops;
extern cvar_t weapondrop;
extern cvar_t ammodrop;
extern cvar_t roundrespawn_time; extern cvar_t roundrespawn_time;
extern cvar_t auto_reload_weapons; extern cvar_t auto_reload_weapons;
extern cvar_t refill_bpammo_weapons; extern cvar_t refill_bpammo_weapons;

View File

@ -186,6 +186,10 @@ enum
GR_PLR_DROP_AMMO_ALL, GR_PLR_DROP_AMMO_ALL,
GR_PLR_DROP_AMMO_ACTIVE, GR_PLR_DROP_AMMO_ACTIVE,
GR_PLR_DROP_AMMO_NO, GR_PLR_DROP_AMMO_NO,
#ifdef REGAMEDLL_ADD
GR_PLR_DROP_GUN_BEST,
#endif
}; };
// custom enum // custom enum

View File

@ -4332,11 +4332,29 @@ LINK_HOOK_CLASS_CUSTOM_CHAIN(int, CHalfLifeMultiplay, CSGameRules, DeadPlayerWea
int EXT_FUNC CHalfLifeMultiplay::__API_HOOK(DeadPlayerWeapons)(CBasePlayer *pPlayer) int EXT_FUNC CHalfLifeMultiplay::__API_HOOK(DeadPlayerWeapons)(CBasePlayer *pPlayer)
{ {
return GR_PLR_DROP_GUN_ACTIVE; #ifdef REGAMEDLL_ADD
switch ((int)weapondrop.value)
{
case 3:
return GR_PLR_DROP_GUN_ALL;
case 2:
break;
case 1:
return GR_PLR_DROP_GUN_BEST;
default:
return GR_PLR_DROP_GUN_NO;
}
#endif
return GR_PLR_DROP_GUN_ACTIVE; // keep original value in return
} }
int CHalfLifeMultiplay::DeadPlayerAmmo(CBasePlayer *pPlayer) int CHalfLifeMultiplay::DeadPlayerAmmo(CBasePlayer *pPlayer)
{ {
#ifdef REGAMEDLL_ADD
if (ammodrop.value == 0.0f)
return GR_PLR_DROP_AMMO_NO;
#endif
return GR_PLR_DROP_AMMO_ACTIVE; return GR_PLR_DROP_AMMO_ACTIVE;
} }

View File

@ -1297,7 +1297,14 @@ CWeaponBox *EXT_FUNC __API_HOOK(CreateWeaponBox)(CBasePlayerItem *pItem, CBasePl
#else #else
pWeaponBox->GiveAmmo(pPlayerOwner->m_rgAmmo[pItem->PrimaryAmmoIndex()], (char *)pItem->pszAmmo1(), pItem->iMaxAmmo1()); pWeaponBox->GiveAmmo(pPlayerOwner->m_rgAmmo[pItem->PrimaryAmmoIndex()], (char *)pItem->pszAmmo1(), pItem->iMaxAmmo1());
#endif #endif
#ifndef REGAMEDLL_FIXES
// by removing ammo ONLY on exhaustible weapons (slot 4 and 5)
// you are allowing to duplicate ammo whenever:
// (1) you have 2 weapons sharing the same ammo type (e.g. mp5navy and glock)
// (2) you are dropping a weapon alive and pickup another (with same ammo type) without ammo
// and, logically, you throw your ammo with your gun with packing enabled
if (exhaustibleAmmo) if (exhaustibleAmmo)
#endif
{ {
pPlayerOwner->m_rgAmmo[pItem->PrimaryAmmoIndex()] = 0; pPlayerOwner->m_rgAmmo[pItem->PrimaryAmmoIndex()] = 0;
} }
@ -1309,10 +1316,10 @@ CWeaponBox *EXT_FUNC __API_HOOK(CreateWeaponBox)(CBasePlayerItem *pItem, CBasePl
return pWeaponBox; return pWeaponBox;
} }
void PackPlayerItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo) CWeaponBox *PackPlayerItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo)
{ {
if (!pItem) if (!pItem)
return; return nullptr;
const char *modelName = GetCSModelName(pItem->m_iId); const char *modelName = GetCSModelName(pItem->m_iId);
if (modelName) if (modelName)
@ -1322,7 +1329,7 @@ void PackPlayerItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo)
Vector vecVelocity = pPlayer->pev->velocity * 0.75f; Vector vecVelocity = pPlayer->pev->velocity * 0.75f;
// create a box to pack the stuff into // create a box to pack the stuff into
CreateWeaponBox(pItem, pPlayer, return CreateWeaponBox(pItem, pPlayer,
modelName, modelName,
vecOrigin, vecOrigin,
vecAngles, vecAngles,
@ -1330,6 +1337,8 @@ void PackPlayerItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo)
CGameRules::GetItemKillDelay(), packAmmo CGameRules::GetItemKillDelay(), packAmmo
); );
} }
return nullptr;
} }
#ifdef REGAMEDLL_ADD #ifdef REGAMEDLL_ADD
@ -1386,21 +1395,51 @@ void PackPlayerNade(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo)
void CBasePlayer::PackDeadPlayerItems() void CBasePlayer::PackDeadPlayerItems()
{ {
// get the game rules // get the game rules
bool bPackGun = (g_pGameRules->DeadPlayerWeapons(this) != GR_PLR_DROP_GUN_NO); int iPackGun = g_pGameRules->DeadPlayerWeapons(this);
bool bPackAmmo = (g_pGameRules->DeadPlayerAmmo(this) != GR_PLR_DROP_AMMO_NO); bool bPackAmmo = (g_pGameRules->DeadPlayerAmmo(this) != GR_PLR_DROP_AMMO_NO);
if (bPackGun) if (iPackGun != GR_PLR_DROP_GUN_NO)
{ {
bool bShieldDropped = false; bool bSkipPrimSec = false;
if (HasShield()) if (HasShield())
{ {
DropShield(); DropShield();
bShieldDropped = true; #ifdef REGAMEDLL_ADD
if(iPackGun != GR_PLR_DROP_GUN_ALL)
#endif
{
bSkipPrimSec = true;
}
} }
int nBestWeight = 0; int nBestWeight = 0;
CBasePlayerItem *pBestItem = nullptr; CBasePlayerItem *pBestItem = nullptr;
#ifdef REGAMEDLL_ADD
int iGunsPacked = 0;
if (iPackGun == GR_PLR_DROP_GUN_ACTIVE)
{
// 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;
// if active item is undroppable, then nothing is dropped
}
// are we allowing nade drop?
if ((int)nadedrops.value >= 1)
{
// goto item loop but skip guns
iPackGun = GR_PLR_DROP_GUN_ALL;
bSkipPrimSec = true;
}
}
if (iPackGun == GR_PLR_DROP_GUN_ALL || iPackGun == GR_PLR_DROP_GUN_BEST)
#endif
{
for (int n = 0; n < MAX_ITEM_TYPES; n++) for (int n = 0; n < MAX_ITEM_TYPES; n++)
{ {
// there's a weapon here. Should I pack it? // there's a weapon here. Should I pack it?
@ -1409,14 +1448,35 @@ void CBasePlayer::PackDeadPlayerItems()
while (pPlayerItem) while (pPlayerItem)
{ {
ItemInfo info; ItemInfo info;
if (pPlayerItem->iItemSlot() < KNIFE_SLOT && !bShieldDropped) if (pPlayerItem->iItemSlot() < KNIFE_SLOT && !bSkipPrimSec)
{ {
#ifdef REGAMEDLL_API #ifdef REGAMEDLL_API
if (pPlayerItem->CSPlayerItem()->GetItemInfo(&info)) if (pPlayerItem->CSPlayerItem()->GetItemInfo(&info)
#else #else
if (pPlayerItem->GetItemInfo(&info)) if (pPlayerItem->GetItemInfo(&info)
#endif #endif
#ifdef REGAMEDLL_FIXES
&& pPlayerItem->CanDrop() // needs to be droppable
#endif
)
{ {
#ifdef REGAMEDLL_ADD
if (iPackGun == GR_PLR_DROP_GUN_ALL)
{
CBasePlayerItem *pNext = pPlayerItem->m_pNext;
CWeaponBox *pWeaponBox = PackPlayerItem(this, pPlayerItem, bPackAmmo);
if (pWeaponBox)
{
// just push a few units in forward to separate them
pWeaponBox->pev->velocity = pWeaponBox->pev->velocity * (1.0 + (iGunsPacked * 0.2));
iGunsPacked++;
}
pPlayerItem = pNext;
continue;
}
#endif
if (info.iWeight > nBestWeight) if (info.iWeight > nBestWeight)
{ {
nBestWeight = info.iWeight; nBestWeight = info.iWeight;
@ -1460,6 +1520,7 @@ void CBasePlayer::PackDeadPlayerItems()
pPlayerItem = pPlayerItem->m_pNext; pPlayerItem = pPlayerItem->m_pNext;
} }
} }
}
PackPlayerItem(this, pBestItem, bPackAmmo); PackPlayerItem(this, pBestItem, bPackAmmo);
} }
@ -8033,13 +8094,21 @@ CBaseEntity *EXT_FUNC CBasePlayer::__API_HOOK(DropPlayerItem)(const char *pszIte
Vector vecAngles = pev->angles; Vector vecAngles = pev->angles;
Vector vecVelocity = gpGlobals->v_forward * 300 + gpGlobals->v_forward * 100; Vector vecVelocity = gpGlobals->v_forward * 300 + gpGlobals->v_forward * 100;
bool bPackAmmo = false;
#ifdef REGAMEDLL_ADD
if (ammodrop.value >= 2.0f)
bPackAmmo = true;
#endif
CWeaponBox *pWeaponBox = CreateWeaponBox(pWeapon, this, CWeaponBox *pWeaponBox = CreateWeaponBox(pWeapon, this,
modelname, modelname,
vecOrigin, vecOrigin,
vecAngles, vecAngles,
vecVelocity, vecVelocity,
CGameRules::GetItemKillDelay(), CGameRules::GetItemKillDelay(),
false); bPackAmmo
);
if (!pWeaponBox) if (!pWeaponBox)
{ {