diff --git a/README.md b/README.md
index bf7408dac..6713f49a4 100644
--- a/README.md
+++ b/README.md
@@ -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_hegrenade_penetration | 0 | 0 | 1 | Disable grenade damage through walls.
`0` disabled
`1` enabled |
| mp_nadedrops | 0 | 0 | 2 | Drop a grenade after player death.
`0` disabled
`1` drop first available grenade
`2` drop all grenades |
+| mp_weapondrop | 1 | 0 | 3 | Drop player weapon after death.
`0` do not drop weapons after death
`1` drop best/heaviest weapon after death
`2` drop active weapon after death
`3` drop all weapons after death (primary and secondary) |
+| mp_ammodrop | 1 | 0 | 2 | Drop ammo on weapon boxes on death or manual drop.
`0` always keep ammo on player
`1` drop all ammo only after death
`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.
`-1` means no time limit
|
| mp_auto_reload_weapons | 0 | 0 | 1 | Automatically reload each weapon on player spawn.
`0` disabled
`1` enabled |
| mp_refill_bpammo_weapons | 0 | 0 | 2 | Refill amount of backpack ammo up to the max.
`0` disabled
`1` refill backpack ammo on player spawn
`2` refill backpack ammo on player spawn and on the purchase of the item |
diff --git a/dist/game.cfg b/dist/game.cfg
index efebcba89..25ba9877f 100644
--- a/dist/game.cfg
+++ b/dist/game.cfg
@@ -78,6 +78,24 @@ mp_hegrenade_penetration "0"
// Default value: "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
// if more than N seconds has elapsed since the beginning round
// -1 - means no time limit
diff --git a/regamedll/common/const.h b/regamedll/common/const.h
index d667a6b85..024a2a3d5 100644
--- a/regamedll/common/const.h
+++ b/regamedll/common/const.h
@@ -100,6 +100,7 @@
// Starting from BIT(16) to reserve space for more flags for Engine
#define FTRACE_BULLET BIT(16)
#define FTRACE_FLASH BIT(17)
+#define FTRACE_KNIFE BIT(18)
// walkmove modes
#define WALKMOVE_NORMAL 0 // normal walkmove
diff --git a/regamedll/dlls/API/CSPlayer.cpp b/regamedll/dlls/API/CSPlayer.cpp
index d40cb921f..2a8348cba 100644
--- a/regamedll/dlls/API/CSPlayer.cpp
+++ b/regamedll/dlls/API/CSPlayer.cpp
@@ -211,15 +211,20 @@ EXT_FUNC bool CCSPlayer::RemovePlayerItemEx(const char* pszItemName, bool bRemov
auto pItem = GetItemByName(pszItemName);
if (pItem)
{
- if (FClassnameIs(pItem->pev, "weapon_c4")) {
- pPlayer->m_bHasC4 = false;
- pPlayer->pev->body = 0;
- pPlayer->SetBombIcon(FALSE);
- pPlayer->SetProgressBarTime(0);
- }
-
if (pItem->IsWeapon())
{
+ // These weapons have a unique type of ammo that is used only by them
+ // If a weapon is removed, its ammo is also reduced, unless the ammo can be used by another weapon
+ if (!bRemoveAmmo && (IsGrenadeWeapon(pItem->m_iId) || pItem->m_iId == WEAPON_C4))
+ {
+ if (pPlayer->m_rgAmmo[pItem->PrimaryAmmoIndex()] > 0)
+ pPlayer->m_rgAmmo[pItem->PrimaryAmmoIndex()]--;
+
+ // Hold the weapon until it runs out of ammo
+ if (pPlayer->m_rgAmmo[pItem->PrimaryAmmoIndex()] > 0)
+ return true; // ammo was reduced, this will be considered a successful result
+ }
+
if (pItem == pPlayer->m_pActiveItem) {
((CBasePlayerWeapon *)pItem)->RetireWeapon();
}
@@ -229,7 +234,15 @@ EXT_FUNC bool CCSPlayer::RemovePlayerItemEx(const char* pszItemName, bool bRemov
}
}
- if (pPlayer->RemovePlayerItem(pItem)) {
+ if (pPlayer->RemovePlayerItem(pItem))
+ {
+ if (FClassnameIs(pItem->pev, "weapon_c4")) {
+ pPlayer->m_bHasC4 = false;
+ pPlayer->pev->body = 0;
+ pPlayer->SetBombIcon(FALSE);
+ pPlayer->SetProgressBarTime(0);
+ }
+
pPlayer->pev->weapons &= ~(1 << pItem->m_iId);
// No more weapon
if ((pPlayer->pev->weapons & ~(1 << WEAPON_SUIT)) == 0) {
diff --git a/regamedll/dlls/bot/cs_bot_manager.cpp b/regamedll/dlls/bot/cs_bot_manager.cpp
index 482180120..4a6269ff6 100644
--- a/regamedll/dlls/bot/cs_bot_manager.cpp
+++ b/regamedll/dlls/bot/cs_bot_manager.cpp
@@ -78,7 +78,7 @@ CCSBotManager::CCSBotManager()
char *dataPointer = (char *)LOAD_FILE_FOR_ME((char *)filename, &dataLength);
if (!dataPointer)
{
- TheBotProfiles->Init("BotProfile.db");
+ TheBotProfiles->Init(cv_bot_profile_db.string);
}
else
{
diff --git a/regamedll/dlls/career_tasks.cpp b/regamedll/dlls/career_tasks.cpp
index 0b0c45a56..200c67558 100644
--- a/regamedll/dlls/career_tasks.cpp
+++ b/regamedll/dlls/career_tasks.cpp
@@ -136,10 +136,14 @@ void CCareerTask::OnWeaponKill(int weaponId, int weaponClassId, bool headshot, b
if (!pHostage->IsAlive())
continue;
+#ifndef REGAMEDLL_FIXES
if (!pHostage->IsFollowingSomeone())
continue;
if (pHostage->m_target == pVictim)
+#else
+ if (pHostage->IsFollowing(pVictim))
+#endif
hostagesCount++;
}
@@ -211,11 +215,14 @@ void CCareerTask::OnEvent(GameEventType event, CBasePlayer *pVictim, CBasePlayer
{
if (!pHostage->IsAlive())
continue;
-
+#ifndef REGAMEDLL_FIXES
if (!pHostage->IsFollowingSomeone())
continue;
if (pHostage->m_target == pAttacker)
+#else
+ if (pHostage->IsFollowing(pAttacker))
+#endif
hostagesCount++;
}
diff --git a/regamedll/dlls/effects.cpp b/regamedll/dlls/effects.cpp
index 16cc2e6ab..f934edd4b 100644
--- a/regamedll/dlls/effects.cpp
+++ b/regamedll/dlls/effects.cpp
@@ -1737,10 +1737,12 @@ Vector CBlood::BloodPosition(CBaseEntity *pActivator)
void CBlood::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value)
{
+ const Vector direction = Direction();
+
if (pev->spawnflags & SF_BLOOD_STREAM)
- UTIL_BloodStream(BloodPosition(pActivator), Direction(), (Color() == BLOOD_COLOR_RED) ? 70 : Color(), int(BloodAmount()));
+ UTIL_BloodStream(BloodPosition(pActivator), direction, (Color() == BLOOD_COLOR_RED) ? 70 : Color(), int(BloodAmount()));
else
- UTIL_BloodDrips(BloodPosition(pActivator), Direction(), Color(), int(BloodAmount()));
+ UTIL_BloodDrips(BloodPosition(pActivator), Color(), int(BloodAmount()));
if (pev->spawnflags & SF_BLOOD_DECAL)
{
diff --git a/regamedll/dlls/game.cpp b/regamedll/dlls/game.cpp
index aff22944e..0666c6f88 100644
--- a/regamedll/dlls/game.cpp
+++ b/regamedll/dlls/game.cpp
@@ -110,6 +110,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 hegrenade_penetration = { "mp_hegrenade_penetration", "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 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
@@ -353,6 +355,8 @@ void EXT_FUNC GameDLLInit()
CVAR_REGISTER(&round_infinite);
CVAR_REGISTER(&hegrenade_penetration);
CVAR_REGISTER(&nadedrops);
+ CVAR_REGISTER(&weapondrop);
+ CVAR_REGISTER(&ammodrop);
CVAR_REGISTER(&roundrespawn_time);
CVAR_REGISTER(&auto_reload_weapons);
CVAR_REGISTER(&refill_bpammo_weapons);
diff --git a/regamedll/dlls/game.h b/regamedll/dlls/game.h
index 9f216aae2..a10af801e 100644
--- a/regamedll/dlls/game.h
+++ b/regamedll/dlls/game.h
@@ -139,6 +139,8 @@ extern cvar_t maxmoney;
extern cvar_t round_infinite;
extern cvar_t hegrenade_penetration;
extern cvar_t nadedrops;
+extern cvar_t weapondrop;
+extern cvar_t ammodrop;
extern cvar_t roundrespawn_time;
extern cvar_t auto_reload_weapons;
extern cvar_t refill_bpammo_weapons;
diff --git a/regamedll/dlls/gamerules.h b/regamedll/dlls/gamerules.h
index 5eee3a6dd..d6975df02 100644
--- a/regamedll/dlls/gamerules.h
+++ b/regamedll/dlls/gamerules.h
@@ -186,6 +186,10 @@ enum
GR_PLR_DROP_AMMO_ALL,
GR_PLR_DROP_AMMO_ACTIVE,
GR_PLR_DROP_AMMO_NO,
+
+#ifdef REGAMEDLL_ADD
+ GR_PLR_DROP_GUN_BEST,
+#endif
};
// custom enum
diff --git a/regamedll/dlls/multiplay_gamerules.cpp b/regamedll/dlls/multiplay_gamerules.cpp
index c40af8fb9..baf916589 100644
--- a/regamedll/dlls/multiplay_gamerules.cpp
+++ b/regamedll/dlls/multiplay_gamerules.cpp
@@ -4332,11 +4332,29 @@ LINK_HOOK_CLASS_CUSTOM_CHAIN(int, CHalfLifeMultiplay, CSGameRules, DeadPlayerWea
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)
{
+#ifdef REGAMEDLL_ADD
+ if (ammodrop.value == 0.0f)
+ return GR_PLR_DROP_AMMO_NO;
+#endif
+
return GR_PLR_DROP_AMMO_ACTIVE;
}
diff --git a/regamedll/dlls/player.cpp b/regamedll/dlls/player.cpp
index 38cbba3be..401b1be7e 100644
--- a/regamedll/dlls/player.cpp
+++ b/regamedll/dlls/player.cpp
@@ -1297,7 +1297,14 @@ CWeaponBox *EXT_FUNC __API_HOOK(CreateWeaponBox)(CBasePlayerItem *pItem, CBasePl
#else
pWeaponBox->GiveAmmo(pPlayerOwner->m_rgAmmo[pItem->PrimaryAmmoIndex()], (char *)pItem->pszAmmo1(), pItem->iMaxAmmo1());
#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)
+#endif
{
pPlayerOwner->m_rgAmmo[pItem->PrimaryAmmoIndex()] = 0;
}
@@ -1309,10 +1316,10 @@ CWeaponBox *EXT_FUNC __API_HOOK(CreateWeaponBox)(CBasePlayerItem *pItem, CBasePl
return pWeaponBox;
}
-void PackPlayerItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo)
+CWeaponBox *PackPlayerItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo)
{
if (!pItem)
- return;
+ return nullptr;
const char *modelName = GetCSModelName(pItem->m_iId);
if (modelName)
@@ -1322,7 +1329,7 @@ void PackPlayerItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo)
Vector vecVelocity = pPlayer->pev->velocity * 0.75f;
// create a box to pack the stuff into
- CreateWeaponBox(pItem, pPlayer,
+ return CreateWeaponBox(pItem, pPlayer,
modelName,
vecOrigin,
vecAngles,
@@ -1330,6 +1337,8 @@ void PackPlayerItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo)
CGameRules::GetItemKillDelay(), packAmmo
);
}
+
+ return nullptr;
}
#ifdef REGAMEDLL_ADD
@@ -1386,78 +1395,130 @@ void PackPlayerNade(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo)
void CBasePlayer::PackDeadPlayerItems()
{
// 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);
- if (bPackGun)
+ if (iPackGun != GR_PLR_DROP_GUN_NO)
{
- bool bShieldDropped = false;
+ bool bSkipPrimSec = false;
if (HasShield())
{
DropShield();
- bShieldDropped = true;
+#ifdef REGAMEDLL_ADD
+ if(iPackGun != GR_PLR_DROP_GUN_ALL)
+#endif
+ {
+ bSkipPrimSec = true;
+ }
}
int nBestWeight = 0;
CBasePlayerItem *pBestItem = nullptr;
- for (int n = 0; n < MAX_ITEM_TYPES; n++)
+#ifdef REGAMEDLL_ADD
+ int iGunsPacked = 0;
+
+ if (iPackGun == GR_PLR_DROP_GUN_ACTIVE)
{
- // there's a weapon here. Should I pack it?
- CBasePlayerItem *pPlayerItem = m_rgpPlayerItems[n];
+ // 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;
- while (pPlayerItem)
+ // if active item is undroppable, then nothing is dropped
+ }
+
+ // are we allowing nade drop?
+ if ((int)nadedrops.value >= 1)
{
- ItemInfo info;
- if (pPlayerItem->iItemSlot() < KNIFE_SLOT && !bShieldDropped)
+ // 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++)
+ {
+ // there's a weapon here. Should I pack it?
+ CBasePlayerItem *pPlayerItem = m_rgpPlayerItems[n];
+
+ while (pPlayerItem)
{
+ ItemInfo info;
+ if (pPlayerItem->iItemSlot() < KNIFE_SLOT && !bSkipPrimSec)
+ {
#ifdef REGAMEDLL_API
- if (pPlayerItem->CSPlayerItem()->GetItemInfo(&info))
+ if (pPlayerItem->CSPlayerItem()->GetItemInfo(&info)
#else
- if (pPlayerItem->GetItemInfo(&info))
+ if (pPlayerItem->GetItemInfo(&info)
#endif
- {
- if (info.iWeight > nBestWeight)
+#ifdef REGAMEDLL_FIXES
+ && pPlayerItem->CanDrop() // needs to be droppable
+#endif
+ )
{
- nBestWeight = info.iWeight;
- pBestItem = pPlayerItem;
+#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)
+ {
+ nBestWeight = info.iWeight;
+ pBestItem = pPlayerItem;
+ }
}
}
- }
- // drop a grenade after death
- else if (pPlayerItem->iItemSlot() == GRENADE_SLOT)
- {
- if (AreRunningCZero())
+ // drop a grenade after death
+ else if (pPlayerItem->iItemSlot() == GRENADE_SLOT)
{
+ if (AreRunningCZero())
+ {
#ifdef REGAMEDLL_FIXES
- if (pPlayerItem->m_flStartThrow == 0.0f && m_rgAmmo[pPlayerItem->PrimaryAmmoIndex()] > 0)
+ if (pPlayerItem->m_flStartThrow == 0.0f && m_rgAmmo[pPlayerItem->PrimaryAmmoIndex()] > 0)
#endif
- {
- PackPlayerItem(this, pPlayerItem, true);
+ {
+ PackPlayerItem(this, pPlayerItem, true);
+ }
}
- }
#ifdef REGAMEDLL_ADD
- else
- {
- switch ((int)nadedrops.value)
- {
- case 1:
- PackPlayerNade(this, pPlayerItem, true);
- break;
- case 2:
+ else
{
- CBasePlayerItem *pNext = pPlayerItem->m_pNext;
- PackPlayerNade(this, pPlayerItem, true);
- pPlayerItem = pNext;
- continue;
- }
+ switch ((int)nadedrops.value)
+ {
+ case 1:
+ PackPlayerNade(this, pPlayerItem, true);
+ break;
+ case 2:
+ {
+ CBasePlayerItem *pNext = pPlayerItem->m_pNext;
+ PackPlayerNade(this, pPlayerItem, true);
+ pPlayerItem = pNext;
+ continue;
+ }
+ }
}
- }
#endif
- }
+ }
- pPlayerItem = pPlayerItem->m_pNext;
+ pPlayerItem = pPlayerItem->m_pNext;
+ }
}
}
@@ -2046,8 +2107,27 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib)
}
TheCareerTasks->HandleDeath(m_iTeam, this);
+
+#ifdef REGAMEDLL_FIXES
+ if (!m_bKilledByBomb)
+ {
+ CBasePlayer *pAttacker = CBasePlayer::Instance(pevAttacker);
+
+ if(pAttacker /*safety*/ && !pAttacker->IsBot() && pAttacker->m_iTeam != m_iTeam)
+ {
+ if (pAttacker->HasShield())
+ killerHasShield = true;
+
+ 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
+ }
+ }
+#endif
}
+#ifndef REGAMEDLL_FIXES
if (!m_bKilledByBomb)
{
CBasePlayer *pAttacker = CBasePlayer::Instance(pevAttacker);
@@ -2077,6 +2157,7 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib)
}
}
}
+#endif
}
if (!m_bKilledByBomb)
@@ -6515,7 +6596,7 @@ void CBasePlayer::CheatImpulseCommands(int iImpulse)
TraceResult tr;
Vector dir(0, 0, 1);
- UTIL_BloodDrips(pev->origin, dir, BLOOD_COLOR_RED, 2000);
+ UTIL_BloodDrips(pev->origin, BLOOD_COLOR_RED, 2000);
for (int r = 1; r < 4; r++)
{
@@ -8016,13 +8097,21 @@ CBaseEntity *EXT_FUNC CBasePlayer::__API_HOOK(DropPlayerItem)(const char *pszIte
Vector vecAngles = pev->angles;
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,
modelname,
vecOrigin,
vecAngles,
vecVelocity,
CGameRules::GetItemKillDelay(),
- false);
+ bPackAmmo
+ );
if (!pWeaponBox)
{
diff --git a/regamedll/dlls/util.cpp b/regamedll/dlls/util.cpp
index 34338bbe5..86e468319 100644
--- a/regamedll/dlls/util.cpp
+++ b/regamedll/dlls/util.cpp
@@ -1056,7 +1056,7 @@ void UTIL_BloodStream(const Vector &origin, const Vector &direction, int color,
MESSAGE_END();
}
-void UTIL_BloodDrips(const Vector &origin, const Vector &direction, int color, int amount)
+void UTIL_BloodDrips(const Vector &origin, int color, int amount)
{
if (!UTIL_ShouldShowBlood(color))
return;
diff --git a/regamedll/dlls/util.h b/regamedll/dlls/util.h
index 6c4f411c8..edcf393cc 100644
--- a/regamedll/dlls/util.h
+++ b/regamedll/dlls/util.h
@@ -262,7 +262,7 @@ bool UTIL_IsMasterTriggered(string_t sMaster, CBaseEntity *pActivator);
BOOL UTIL_ShouldShowBlood(int color);
int UTIL_PointContents(const Vector &vec);
void UTIL_BloodStream(const Vector &origin, const Vector &direction, int color, int amount);
-void UTIL_BloodDrips(const Vector &origin, const Vector &direction, int color, int amount);
+void UTIL_BloodDrips(const Vector &origin, int color, int amount);
Vector UTIL_RandomBloodVector();
void UTIL_BloodDecalTrace(TraceResult *pTrace, int bloodColor);
void UTIL_DecalTrace(TraceResult *pTrace, int decalNumber);
diff --git a/regamedll/dlls/weapons.cpp b/regamedll/dlls/weapons.cpp
index b3746dea2..ac9aaea90 100644
--- a/regamedll/dlls/weapons.cpp
+++ b/regamedll/dlls/weapons.cpp
@@ -112,7 +112,7 @@ void AddMultiDamage(entvars_t *pevInflictor, CBaseEntity *pEntity, float flDamag
void SpawnBlood(Vector vecSpot, int bloodColor, float flDamage)
{
- UTIL_BloodDrips(vecSpot, g_vecAttackDir, bloodColor, int(flDamage));
+ UTIL_BloodDrips(vecSpot, bloodColor, int(flDamage));
}
NOXREF int DamageDecal(CBaseEntity *pEntity, int bitsDamageType)
@@ -761,8 +761,9 @@ void CBasePlayerWeapon::FireRemaining(int &shotsFired, float &shootTime, BOOL bI
if (bIsGlock)
{
vecDir = m_pPlayer->FireBullets3(vecSrc, gpGlobals->v_forward, 0.05, 8192, 1, BULLET_PLAYER_9MM, 18, 0.9, m_pPlayer->pev, true, m_pPlayer->random_seed);
+#ifndef REGAMEDLL_FIXES
--m_pPlayer->ammo_9mm;
-
+#endif
PLAYBACK_EVENT_FULL(flag, m_pPlayer->edict(), m_usFireGlock18, 0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y,
int(m_pPlayer->pev->punchangle.x * 10000), int(m_pPlayer->pev->punchangle.y * 10000), m_iClip == 0, FALSE);
}
@@ -770,7 +771,9 @@ void CBasePlayerWeapon::FireRemaining(int &shotsFired, float &shootTime, BOOL bI
{
vecDir = m_pPlayer->FireBullets3(vecSrc, gpGlobals->v_forward, m_fBurstSpread, 8192, 2, BULLET_PLAYER_556MM, 30, 0.96, m_pPlayer->pev, false, m_pPlayer->random_seed);
+#ifndef REGAMEDLL_FIXES
--m_pPlayer->ammo_556nato;
+#endif
#ifdef REGAMEDLL_ADD
// HACKHACK: client-side weapon prediction fix
diff --git a/regamedll/dlls/weapons.h b/regamedll/dlls/weapons.h
index bd22989e3..739d1538c 100644
--- a/regamedll/dlls/weapons.h
+++ b/regamedll/dlls/weapons.h
@@ -1151,15 +1151,16 @@ class CHEGrenade: public CBasePlayerWeapon
};
-const float KNIFE_BODYHIT_VOLUME = 128.0f;
-const float KNIFE_WALLHIT_VOLUME = 512.0f;
-const float KNIFE_MAX_SPEED = 250.0f;
-const float KNIFE_MAX_SPEED_SHIELD = 180.0f;
-const float KNIFE_STAB_DAMAGE = 65.0f;
-const float KNIFE_SWING_DAMAGE = 15.0f;
-const float KNIFE_SWING_DAMAGE_FAST = 20.0f;
-const float KNIFE_STAB_DISTANCE = 32.0f;
-const float KNIFE_SWING_DISTANCE = 48.0f;
+const float KNIFE_BODYHIT_VOLUME = 128.0f;
+const float KNIFE_WALLHIT_VOLUME = 512.0f;
+const float KNIFE_MAX_SPEED = 250.0f;
+const float KNIFE_MAX_SPEED_SHIELD = 180.0f;
+const float KNIFE_STAB_DAMAGE = 65.0f;
+const float KNIFE_SWING_DAMAGE = 15.0f;
+const float KNIFE_SWING_DAMAGE_FAST = 20.0f;
+const float KNIFE_STAB_DISTANCE = 32.0f;
+const float KNIFE_SWING_DISTANCE = 48.0f;
+const float KNIFE_BACKSTAB_MULTIPLIER = 3.0f;
enum knife_e
{
@@ -1220,19 +1221,41 @@ class CKnife: public CBasePlayerWeapon
void SetPlayerShieldAnim();
void ResetPlayerShieldAnim();
+ float KnifeStabDamage() const;
+ float KnifeSwingDamage(bool fast) const;
+ float KnifeStabDistance() const;
+ float KnifeSwingDistance() const;
+ float KnifeBackStabMultiplier() const;
+
private:
TraceResult m_trHit;
unsigned short m_usKnife;
- // Extra RegameDLL features
+#ifdef REGAMEDLL_API
float m_flStabBaseDamage;
float m_flSwingBaseDamage;
float m_flSwingBaseDamage_Fast;
float m_flStabDistance;
float m_flSwingDistance;
+
+ float m_flBackStabMultiplier;
+#endif
};
+#ifdef REGAMEDLL_API
+inline float CKnife::KnifeStabDamage() const { return m_flStabBaseDamage; }
+inline float CKnife::KnifeSwingDamage(bool fast) const { return fast ? m_flSwingBaseDamage_Fast : m_flSwingBaseDamage; }
+inline float CKnife::KnifeStabDistance() const { return m_flStabDistance; }
+inline float CKnife::KnifeSwingDistance() const { return m_flSwingDistance; }
+inline float CKnife::KnifeBackStabMultiplier() const { return m_flBackStabMultiplier; }
+#else
+inline float CKnife::KnifeStabDamage() const { return KNIFE_STAB_DAMAGE; }
+inline float CKnife::KnifeSwingDamage(bool fast) const { return fast ? KNIFE_SWING_DAMAGE_FAST : KNIFE_SWING_DAMAGE; }
+inline float CKnife::KnifeStabDistance() const { return KNIFE_STAB_DISTANCE; }
+inline float CKnife::KnifeSwingDistance() const { return KNIFE_SWING_DISTANCE; }
+inline float CKnife::KnifeBackStabMultiplier() const { return KNIFE_BACKSTAB_MULTIPLIER; }
+#endif // REGAMEDLL_API
const float M249_MAX_SPEED = 220.0f;
const float M249_DAMAGE = 32.0f;
diff --git a/regamedll/dlls/wpn_shared/wpn_knife.cpp b/regamedll/dlls/wpn_shared/wpn_knife.cpp
index 18275c047..fcbf2d949 100644
--- a/regamedll/dlls/wpn_shared/wpn_knife.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_knife.cpp
@@ -12,6 +12,7 @@ void CKnife::Spawn()
m_iWeaponState &= ~WPNSTATE_SHIELD_DRAWN;
m_iClip = WEAPON_NOCLIP;
+#ifdef REGAMEDLL_API
m_flStabBaseDamage = KNIFE_STAB_DAMAGE;
m_flSwingBaseDamage = KNIFE_SWING_DAMAGE;
m_flSwingBaseDamage_Fast = KNIFE_SWING_DAMAGE_FAST;
@@ -19,6 +20,9 @@ void CKnife::Spawn()
m_flStabDistance = KNIFE_STAB_DISTANCE;
m_flSwingDistance = KNIFE_SWING_DISTANCE;
+ m_flBackStabMultiplier = KNIFE_BACKSTAB_MULTIPLIER;
+#endif
+
// Get ready to fall down
FallInit();
@@ -44,12 +48,16 @@ void CKnife::Precache()
m_usKnife = PRECACHE_EVENT(1, "events/knife.sc");
+#ifdef REGAMEDLL_API
m_flStabBaseDamage = KNIFE_STAB_DAMAGE;
m_flSwingBaseDamage = KNIFE_SWING_DAMAGE;
m_flSwingBaseDamage_Fast = KNIFE_SWING_DAMAGE_FAST;
m_flStabDistance = KNIFE_STAB_DISTANCE;
m_flSwingDistance = KNIFE_SWING_DISTANCE;
+
+ m_flBackStabMultiplier = KNIFE_BACKSTAB_MULTIPLIER;
+#endif
}
int CKnife::GetItemInfo(ItemInfo *p)
@@ -121,6 +129,9 @@ void FindHullIntersection(const Vector &vecSrc, TraceResult &tr, float *mins, fl
distance = 1e6f;
vecHullEnd = vecSrc + ((vecHullEnd - vecSrc) * 2);
+#ifdef REGAMEDLL_ADD
+ gpGlobals->trace_flags = FTRACE_KNIFE;
+#endif
UTIL_TraceLine(vecSrc, vecHullEnd, dont_ignore_monsters, pEntity, &tmpTrace);
if (tmpTrace.flFraction < 1.0f)
@@ -139,6 +150,9 @@ void FindHullIntersection(const Vector &vecSrc, TraceResult &tr, float *mins, fl
vecEnd.y = vecHullEnd.y + minmaxs[j][1];
vecEnd.z = vecHullEnd.z + minmaxs[k][2];
+#ifdef REGAMEDLL_ADD
+ gpGlobals->trace_flags = FTRACE_KNIFE;
+#endif
UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, pEntity, &tmpTrace);
if (tmpTrace.flFraction < 1.0f)
@@ -166,14 +180,7 @@ void CKnife::SetPlayerShieldAnim()
if (!m_pPlayer->HasShield())
return;
- if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN)
- {
- Q_strcpy(m_pPlayer->m_szAnimExtention, "shield");
- }
- else
- {
- Q_strcpy(m_pPlayer->m_szAnimExtention, "shieldknife");
- }
+ Q_strcpy(m_pPlayer->m_szAnimExtention, (m_iWeaponState & WPNSTATE_SHIELD_DRAWN) != 0 ? "shield" : "shieldknife");
}
void CKnife::ResetPlayerShieldAnim()
@@ -271,13 +278,23 @@ BOOL CKnife::Swing(BOOL fFirst)
UTIL_MakeVectors(m_pPlayer->pev->v_angle);
vecSrc = m_pPlayer->GetGunPosition();
- vecEnd = vecSrc + gpGlobals->v_forward * m_flSwingDistance;
+ vecEnd = vecSrc + gpGlobals->v_forward * KnifeSwingDistance();
+#ifdef REGAMEDLL_ADD
+ gpGlobals->trace_flags = FTRACE_KNIFE;
+#endif
UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, m_pPlayer->edict(), &tr);
if (tr.flFraction >= 1.0f)
{
+#ifdef REGAMEDLL_ADD
+ gpGlobals->trace_flags = FTRACE_KNIFE;
+#endif
UTIL_TraceHull(vecSrc, vecEnd, dont_ignore_monsters, head_hull, m_pPlayer->edict(), &tr);
+#ifdef REGAMEDLL_ADD
+ // We manually reset it because Engine doesn't unlike TraceLine
+ gpGlobals->trace_flags = 0;
+#endif
if (tr.flFraction < 1.0f)
{
@@ -303,8 +320,8 @@ BOOL CKnife::Swing(BOOL fFirst)
{
switch ((m_iSwing++) % 2)
{
- case 0: SendWeaponAnim(KNIFE_MIDATTACK1HIT, UseDecrement() != FALSE); break;
- case 1: SendWeaponAnim(KNIFE_MIDATTACK2HIT, UseDecrement() != FALSE); break;
+ case 0: SendWeaponAnim(KNIFE_MIDATTACK1HIT, UseDecrement() != FALSE); break;
+ case 1: SendWeaponAnim(KNIFE_MIDATTACK2HIT, UseDecrement() != FALSE); break;
}
// miss
@@ -322,10 +339,15 @@ BOOL CKnife::Swing(BOOL fFirst)
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.0f;
// play wiff or swish sound
- if (RANDOM_LONG(0, 1))
- EMIT_SOUND_DYN(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_slash1.wav", VOL_NORM, ATTN_NORM, 0, 94);
- else
- EMIT_SOUND_DYN(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_slash2.wav", VOL_NORM, ATTN_NORM, 0, 94);
+ EMIT_SOUND_DYN(m_pPlayer->edict(),
+ CHAN_WEAPON,
+ RANDOM_LONG(0, 1) ?
+ "weapons/knife_slash1.wav" :
+ "weapons/knife_slash2.wav",
+ VOL_NORM,
+ ATTN_NORM,
+ 0,
+ 94);
// player "shoot" animation
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
@@ -340,8 +362,8 @@ BOOL CKnife::Swing(BOOL fFirst)
{
switch ((m_iSwing++) % 2)
{
- case 0: SendWeaponAnim(KNIFE_MIDATTACK1HIT, UseDecrement() != FALSE); break;
- case 1: SendWeaponAnim(KNIFE_MIDATTACK2HIT, UseDecrement() != FALSE); break;
+ case 0: SendWeaponAnim(KNIFE_MIDATTACK1HIT, UseDecrement() != FALSE); break;
+ case 1: SendWeaponAnim(KNIFE_MIDATTACK2HIT, UseDecrement() != FALSE); break;
}
m_flNextPrimaryAttack = GetNextAttackDelay(0.4);
@@ -368,10 +390,11 @@ BOOL CKnife::Swing(BOOL fFirst)
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
ClearMultiDamage();
- if (m_flNextPrimaryAttack + 0.4f < UTIL_WeaponTimeBase())
- pEntity->TraceAttack(m_pPlayer->pev, m_flSwingBaseDamage_Fast, gpGlobals->v_forward, &tr, (DMG_NEVERGIB | DMG_BULLET));
- else
- pEntity->TraceAttack(m_pPlayer->pev, m_flSwingBaseDamage, gpGlobals->v_forward, &tr, (DMG_NEVERGIB | DMG_BULLET));
+ pEntity->TraceAttack(m_pPlayer->pev,
+ KnifeSwingDamage(m_flNextPrimaryAttack + 0.4f < UTIL_WeaponTimeBase()),
+ gpGlobals->v_forward,
+ &tr,
+ (DMG_NEVERGIB | DMG_BULLET));
ApplyMultiDamage(m_pPlayer->pev, m_pPlayer->pev);
@@ -379,28 +402,27 @@ BOOL CKnife::Swing(BOOL fFirst)
if (pEntity) // -V595
#endif
{
+ if (pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE
#ifdef REGAMEDLL_FIXES
- if (pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE && pEntity->Classify() != CLASS_VEHICLE)
-#else
- if (pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE)
+ && pEntity->Classify() != CLASS_VEHICLE
#endif
+ )
{
// play thwack or smack sound
switch (RANDOM_LONG(0, 3))
{
- case 0: EMIT_SOUND(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_hit1.wav", VOL_NORM, ATTN_NORM); break;
- case 1: EMIT_SOUND(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_hit2.wav", VOL_NORM, ATTN_NORM); break;
- case 2: EMIT_SOUND(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_hit3.wav", VOL_NORM, ATTN_NORM); break;
- case 3: EMIT_SOUND(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_hit4.wav", VOL_NORM, ATTN_NORM); break;
+ case 0: EMIT_SOUND(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_hit1.wav", VOL_NORM, ATTN_NORM); break;
+ case 1: EMIT_SOUND(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_hit2.wav", VOL_NORM, ATTN_NORM); break;
+ case 2: EMIT_SOUND(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_hit3.wav", VOL_NORM, ATTN_NORM); break;
+ case 3: EMIT_SOUND(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_hit4.wav", VOL_NORM, ATTN_NORM); break;
}
m_pPlayer->m_iWeaponVolume = KNIFE_BODYHIT_VOLUME;
if (!pEntity->IsAlive())
return TRUE;
- else
- flVol = 0.1f;
+ flVol = 0.1f;
fHitWorld = FALSE;
}
}
@@ -449,13 +471,23 @@ BOOL CKnife::Stab(BOOL fFirst)
UTIL_MakeVectors(m_pPlayer->pev->v_angle);
vecSrc = m_pPlayer->GetGunPosition();
- vecEnd = vecSrc + gpGlobals->v_forward * m_flStabDistance;
+ vecEnd = vecSrc + gpGlobals->v_forward * KnifeStabDistance();
+#ifdef REGAMEDLL_ADD
+ gpGlobals->trace_flags = FTRACE_KNIFE;
+#endif
UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, m_pPlayer->edict(), &tr);
if (tr.flFraction >= 1.0f)
{
+#ifdef REGAMEDLL_ADD
+ gpGlobals->trace_flags = FTRACE_KNIFE;
+#endif
UTIL_TraceHull(vecSrc, vecEnd, dont_ignore_monsters, head_hull, m_pPlayer->edict(), &tr);
+#ifdef REGAMEDLL_ADD
+ // We manually reset it because Engine doesn't unlike TraceLine
+ gpGlobals->trace_flags = 0;
+#endif
if (tr.flFraction < 1.0f)
{
@@ -486,10 +518,15 @@ BOOL CKnife::Stab(BOOL fFirst)
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.0f;
// play wiff or swish sound
- if (RANDOM_LONG(0, 1))
- EMIT_SOUND_DYN(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_slash1.wav", VOL_NORM, ATTN_NORM, 0, 94);
- else
- EMIT_SOUND_DYN(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_slash2.wav", VOL_NORM, ATTN_NORM, 0, 94);
+ EMIT_SOUND_DYN(m_pPlayer->edict(),
+ CHAN_WEAPON,
+ RANDOM_LONG(0, 1) ?
+ "weapons/knife_slash1.wav" :
+ "weapons/knife_slash2.wav",
+ VOL_NORM,
+ ATTN_NORM,
+ 0,
+ 94);
// player "shoot" animation
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
@@ -517,7 +554,7 @@ BOOL CKnife::Stab(BOOL fFirst)
// player "shoot" animation
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
- float flDamage = m_flStabBaseDamage;
+ float flDamage = KnifeStabDamage();
if (pEntity && pEntity->IsPlayer())
{
@@ -532,10 +569,10 @@ BOOL CKnife::Stab(BOOL fFirst)
flDot = DotProduct(vec2LOS, gpGlobals->v_forward.Make2D());
- //Triple the damage if we are stabbing them in the back.
+ // Multiply the damage if we are stabbing them in the back.
if (flDot > 0.80f)
{
- flDamage *= 3.0f;
+ flDamage *= KnifeBackStabMultiplier();
}
}
@@ -549,11 +586,11 @@ BOOL CKnife::Stab(BOOL fFirst)
if (pEntity) // -V595
#endif
{
+ if (pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE
#ifdef REGAMEDLL_FIXES
- if (pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE && pEntity->Classify() != CLASS_VEHICLE)
-#else
- if (pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE)
+ && pEntity->Classify() != CLASS_VEHICLE
#endif
+ )
{
EMIT_SOUND(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_stab.wav", VOL_NORM, ATTN_NORM);
m_pPlayer->m_iWeaponVolume = KNIFE_BODYHIT_VOLUME;
diff --git a/regamedll/game_shared/bot/bot_util.cpp b/regamedll/game_shared/bot/bot_util.cpp
index d14aaaeba..9b5e2013e 100644
--- a/regamedll/game_shared/bot/bot_util.cpp
+++ b/regamedll/game_shared/bot/bot_util.cpp
@@ -613,6 +613,13 @@ void CONSOLE_ECHO_LOGGED(const char *pszMsg, ...)
void BotPrecache()
{
+#ifdef REGAMEDLL_FIXES
+ // all resources above are used between navarea, improved bots and tutor
+ // you can run cs1.6 with bots so it's not only limited to czero
+ if (!AreRunningCZero() && !AreBotsAllowed())
+ return;
+#endif
+
s_iBeamSprite = PRECACHE_MODEL("sprites/smoke.spr");
PRECACHE_SOUND("buttons/bell1.wav");
@@ -621,7 +628,12 @@ void BotPrecache()
PRECACHE_SOUND("buttons/button11.wav");
PRECACHE_SOUND("buttons/latchunlocked2.wav");
PRECACHE_SOUND("buttons/lightswitch2.wav");
- PRECACHE_SOUND("ambience/quail1.wav");
+
+#ifdef REGAMEDLL_FIXES
+ PRECACHE_GENERIC("sound/ambience/quail1.wav");
+#else
+ PRECACHE_SOUND("ambience/quail1.wav"); // not used internally
+#endif
PRECACHE_SOUND("events/tutor_msg.wav");
PRECACHE_SOUND("events/enemy_died.wav");