diff --git a/README.md b/README.md
index 3150af51..93cd795d 100644
--- a/README.md
+++ b/README.md
@@ -115,6 +115,7 @@ This means that plugins that do binary code analysis (Orpheu for example) probab
| mp_assist_damage_threshold | 40 | 0 | 100 | Sets the percentage of damage needed to score an assist. |
| mp_freezetime_duck | 1 | 0 | 1 | Allow players to duck during freezetime.
`0` disabled
`1` enabled |
| mp_freezetime_jump | 1 | 0 | 1 | Allow players to jump during freezetime.
`0` disabled
`1` enabled |
+| mp_defuser_allocation | 0 | 0 | 2 | Give defuser on player spawn.
`0` disabled
`1` Random players.
`2` All players. |
## How to install zBot for CS 1.6?
diff --git a/dist/game.cfg b/dist/game.cfg
index 7d077571..91009dd0 100644
--- a/dist/game.cfg
+++ b/dist/game.cfg
@@ -567,3 +567,11 @@ mp_freezetime_duck "1"
//
// Default value: "1"
mp_freezetime_jump "1"
+
+// Give defuser on player spawn
+// 0 - No free defusers (default behavior)
+// 1 - Random players
+// 2 - All players
+//
+// Default value: "0"
+mp_defuser_allocation "0"
diff --git a/regamedll/dlls/game.cpp b/regamedll/dlls/game.cpp
index 423250ce..4ab375d8 100644
--- a/regamedll/dlls/game.cpp
+++ b/regamedll/dlls/game.cpp
@@ -177,6 +177,7 @@ cvar_t hostages_rescued_ratio = { "mp_hostages_rescued_ratio", "1.0", 0, 1.0f, n
cvar_t legacy_vehicle_block = { "mp_legacy_vehicle_block", "1", 0, 0.0f, nullptr };
cvar_t dying_time = { "mp_dying_time", "3.0", 0, 3.0f, nullptr };
+cvar_t defuser_allocation = { "mp_defuser_allocation", "0", 0, 0.0f, nullptr };
void GameDLL_Version_f()
{
@@ -439,6 +440,7 @@ void EXT_FUNC GameDLLInit()
CVAR_REGISTER(&freezetime_duck);
CVAR_REGISTER(&freezetime_jump);
+ CVAR_REGISTER(&defuser_allocation);
// print version
CONSOLE_ECHO("ReGameDLL version: " APP_VERSION "\n");
diff --git a/regamedll/dlls/game.h b/regamedll/dlls/game.h
index cff031fb..706e1c2a 100644
--- a/regamedll/dlls/game.h
+++ b/regamedll/dlls/game.h
@@ -200,6 +200,7 @@ extern cvar_t deathmsg_flags;
extern cvar_t assist_damage_threshold;
extern cvar_t freezetime_duck;
extern cvar_t freezetime_jump;
+extern cvar_t defuser_allocation;
#endif
diff --git a/regamedll/dlls/gamerules.h b/regamedll/dlls/gamerules.h
index e29aaba8..e7dc3508 100644
--- a/regamedll/dlls/gamerules.h
+++ b/regamedll/dlls/gamerules.h
@@ -255,6 +255,13 @@ enum KillRarity
KILLRARITY_REVENGE = 0x100 // Revenge by the killer
};
+enum
+{
+ DEFUSERALLOCATION_NONE = 0,
+ DEFUSERALLOCATION_RANDOM = 1,
+ DEFUSERALLOCATION_ALL = 2,
+};
+
class CItem;
class CGameRules
@@ -738,6 +745,8 @@ public:
int GetRarityOfKill(CBaseEntity *pKiller, CBasePlayer *pVictim, CBasePlayer *pAssister, const char *killerWeaponName, bool bFlashAssist);
CBasePlayer *CheckAssistsToKill(CBaseEntity *pKiller, CBasePlayer *pVictim, bool &bFlashAssist);
+ void GiveDefuserToRandomPlayer();
+
private:
void MarkLivingPlayersOnTeamAsNotReceivingMoneyNextRound(int iTeam);
diff --git a/regamedll/dlls/multiplay_gamerules.cpp b/regamedll/dlls/multiplay_gamerules.cpp
index c8ce2896..229da7c1 100644
--- a/regamedll/dlls/multiplay_gamerules.cpp
+++ b/regamedll/dlls/multiplay_gamerules.cpp
@@ -2063,6 +2063,11 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(RestartRound)()
GiveC4();
}
+#ifdef REGAMEDLL_ADD
+ if (m_bMapHasBombTarget && (int)defuser_allocation.value == DEFUSERALLOCATION_RANDOM)
+ GiveDefuserToRandomPlayer();
+#endif
+
if (TheBots)
{
TheBots->OnEvent(EVENT_BUY_TIME_START);
@@ -3837,6 +3842,10 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(PlayerSpawn)(CBasePlayer *pPlayer)
#ifdef REGAMEDLL_ADD
if (respawn_immunitytime.value > 0)
pPlayer->SetSpawnProtection(respawn_immunitytime.value);
+
+ // remove any defusers left over from previous random if there is just one random one
+ if (m_bMapHasBombTarget && (int)defuser_allocation.value == DEFUSERALLOCATION_RANDOM)
+ pPlayer->RemoveDefuser();
#endif
}
@@ -5376,3 +5385,54 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(SendDeathMessage)(CBaseEntity *pKil
MESSAGE_END();
}
+
+void CHalfLifeMultiplay::GiveDefuserToRandomPlayer()
+{
+ int iDefusersToGive = 2;
+ CUtlVector candidates;
+ candidates.EnsureCapacity(MAX_CLIENTS);
+
+ // add all CT candidates to a list
+ for (int i = 1; i <= gpGlobals->maxClients; i++)
+ {
+ CBasePlayer *pPlayer = UTIL_PlayerByIndex(i);
+ if (!pPlayer || FNullEnt(pPlayer->edict()))
+ continue;
+
+ if (!pPlayer->IsAlive() || pPlayer->m_iTeam != CT)
+ continue;
+
+ candidates.AddToTail(pPlayer);
+ }
+
+ // randomly shuffle the list; this will keep the selection random in case of ties
+ for (int i = 0; i < candidates.Count(); i++) {
+ SWAP(candidates[i], candidates[RANDOM_LONG(0, candidates.Count() - 1)]);
+ }
+
+ // now sort the shuffled list into subgroups
+ candidates.Sort([](CBasePlayer *const *left, CBasePlayer *const *right) -> int {
+ // should we prioritize humans over bots?
+ if (cv_bot_defer_to_human.value != 0.0f)
+ {
+ if ((*left)->IsBot() && !(*right)->IsBot())
+ return 1;
+
+ if (!(*left)->IsBot() && (*right)->IsBot())
+ return -1;
+ }
+
+ return 0;
+ }
+ );
+
+ // give defusers to the first N candidates
+ for (int i = 0; i < iDefusersToGive && i < candidates.Count(); ++i)
+ {
+ CBasePlayer *pPlayer = candidates[i];
+ assert(pPlayer && pPlayer->m_iTeam == CT && pPlayer->IsAlive());
+
+ pPlayer->GiveDefuser();
+ ClientPrint(pPlayer->pev, HUD_PRINTCENTER, "#Got_defuser");
+ }
+}
diff --git a/regamedll/dlls/player.cpp b/regamedll/dlls/player.cpp
index e2770a03..0bc4e4fc 100644
--- a/regamedll/dlls/player.cpp
+++ b/regamedll/dlls/player.cpp
@@ -10314,6 +10314,9 @@ void EXT_FUNC CBasePlayer::__API_HOOK(OnSpawnEquip)(bool addDefault, bool equipG
case ARMOR_VESTHELM: GiveNamedItemEx("item_assaultsuit"); break;
}
}
+
+ if (NeedsDefuseKit() && (int)defuser_allocation.value == DEFUSERALLOCATION_ALL)
+ GiveNamedItemEx("item_thighpack");
#endif
}