diff --git a/README.md b/README.md
index 4df82a681..36b8e1d59 100644
--- a/README.md
+++ b/README.md
@@ -100,6 +100,7 @@ This means that plugins that do binary code analysis (Orpheu for example) probab
| mp_fadetoblack | 0 | 0 | 2 | Observer's screen will fade to black on kill event or permanent.
`0` No fade.
`1` Fade to black and won't be able to watch anybody.
`2` fade to black only on kill moment. |
| mp_falldamage | 1 | 0 | 1 | Damage from falling.
`0` disabled
`1` enabled |
| sv_allchat | 1 | 0 | 1 | Players can receive all other players text chat, team restrictions apply
`0` disabled
`1` enabled |
+| mp_max_alive_name_changes | -1 | -1 | - | Maximum amount of nickname changes before next respawn
`-1` unlimited (default behaviour)
`0` Allow to change only at spawn `>0` Allow to change arbitrary amount of nicks |
## How to install zBot for CS 1.6?
diff --git a/dist/game.cfg b/dist/game.cfg
index 175f8d803..771460441 100644
--- a/dist/game.cfg
+++ b/dist/game.cfg
@@ -462,3 +462,11 @@ mp_free_armor 0
//
// Default value: "0"
sv_allchat 0
+
+// Maximum amount of nickname changes before next respawn.
+// -1 - unlimited (default behaviour)
+// 0 - Allow to change only at spawn
+// >0 - Allow to change arbitrary amount of nicks
+//
+// Default value: "-1"
+mp_max_alive_name_changes -1
diff --git a/regamedll/dlls/API/CSPlayer.cpp b/regamedll/dlls/API/CSPlayer.cpp
index e2d69608d..4be7c3aff 100644
--- a/regamedll/dlls/API/CSPlayer.cpp
+++ b/regamedll/dlls/API/CSPlayer.cpp
@@ -539,6 +539,7 @@ void CCSPlayer::Reset()
m_iWeaponInfiniteIds = 0;
m_bCanShootOverride = false;
m_bGameForcingRespawn = false;
+ m_iNickChangesBeforeSpawn = -1;
}
void CCSPlayer::OnSpawn()
@@ -562,3 +563,22 @@ void CCSPlayer::OnKilled()
}
#endif
}
+
+EXT_FUNC void CCSPlayer::OnRoundRespawn()
+{
+ m_iNickChangesBeforeSpawn = 0;
+}
+
+EXT_FUNC bool CCSPlayer::CanChangeNickname()
+{
+#ifdef REGAMEDLL_ADD
+ return (max_alive_name_changes.value >= 0 && m_iNickChangesBeforeSpawn > max_alive_name_changes.value);
+#else
+ return false;
+#endif
+}
+
+EXT_FUNC void CCSPlayer::OnNicknameChanged()
+{
+ m_iNickChangesBeforeSpawn++;
+}
diff --git a/regamedll/dlls/game.cpp b/regamedll/dlls/game.cpp
index dbe9b9ae7..ed904ada0 100644
--- a/regamedll/dlls/game.cpp
+++ b/regamedll/dlls/game.cpp
@@ -159,6 +159,7 @@ cvar_t t_default_weapons_secondary = { "mp_t_default_weapons_secondary", "
cvar_t t_default_weapons_primary = { "mp_t_default_weapons_primary", "", 0, 0.0f, nullptr };
cvar_t free_armor = { "mp_free_armor", "0", 0, 0.0f, nullptr };
cvar_t allchat = { "sv_allchat", "0", 0, 0.0f, nullptr };
+cvar_t max_alive_name_changes = { "mp_max_alive_name_changes", "-1", 0, 0.0f, nullptr };
void GameDLL_Version_f()
{
@@ -387,6 +388,7 @@ void EXT_FUNC GameDLLInit()
CVAR_REGISTER(&t_default_weapons_primary);
CVAR_REGISTER(&free_armor);
CVAR_REGISTER(&allchat);
+ CVAR_REGISTER(&max_alive_name_changes);
// print version
CONSOLE_ECHO("ReGameDLL version: " APP_VERSION "\n");
diff --git a/regamedll/dlls/game.h b/regamedll/dlls/game.h
index cc04e1c68..48d9a29d9 100644
--- a/regamedll/dlls/game.h
+++ b/regamedll/dlls/game.h
@@ -185,6 +185,7 @@ extern cvar_t t_default_weapons_secondary;
extern cvar_t t_default_weapons_primary;
extern cvar_t free_armor;
extern cvar_t allchat;
+extern cvar_t max_alive_name_changes;
#endif
diff --git a/regamedll/dlls/player.cpp b/regamedll/dlls/player.cpp
index 8c595776a..21037f5aa 100644
--- a/regamedll/dlls/player.cpp
+++ b/regamedll/dlls/player.cpp
@@ -173,7 +173,11 @@ bool EXT_FUNC CBasePlayer::__API_HOOK(SetClientUserInfoName)(char *infobuffer, c
}
#endif
- if (pev->deadflag != DEAD_NO)
+ if (IsAlive()
+#ifdef REGAMEDLL_ADD
+ || CSPlayer()->CanChangeNickname()
+#endif
+ )
{
m_bHasChangedName = true;
Q_snprintf(m_szNewName, sizeof(m_szNewName), "%s", szNewName);
@@ -191,6 +195,10 @@ bool EXT_FUNC CBasePlayer::__API_HOOK(SetClientUserInfoName)(char *infobuffer, c
WRITE_STRING(szNewName);
MESSAGE_END();
+#ifdef REGAMEDLL_ADD
+ CSPlayer()->OnNicknameChanged();
+#endif
+
UTIL_LogPrintf("\"%s<%i><%s><%s>\" changed name to \"%s\"\n", STRING(pev->netname), GETPLAYERUSERID(edict()), GETPLAYERAUTHID(edict()), GetTeam(m_iTeam), szNewName);
return true;
}
@@ -3842,6 +3850,10 @@ void EXT_FUNC CBasePlayer::__API_HOOK(RoundRespawn)()
#endif
}
+#ifdef REGAMEDLL_ADD
+ CSPlayer()->OnRoundRespawn();
+#endif
+
if (m_iMenu != Menu_ChooseAppearance)
{
respawn(pev);
diff --git a/regamedll/public/regamedll/API/CSPlayer.h b/regamedll/public/regamedll/API/CSPlayer.h
index 5020585a6..2051a5133 100644
--- a/regamedll/public/regamedll/API/CSPlayer.h
+++ b/regamedll/public/regamedll/API/CSPlayer.h
@@ -46,7 +46,8 @@ class CCSPlayer: public CCSMonster {
m_iWeaponInfiniteAmmo(0),
m_iWeaponInfiniteIds(0),
m_bCanShootOverride(false),
- m_bGameForcingRespawn(false)
+ m_bGameForcingRespawn(false),
+ m_iNickChangesBeforeSpawn(-1)
{
m_szModel[0] = '\0';
}
@@ -101,6 +102,9 @@ class CCSPlayer: public CCSMonster {
void OnSpawn();
void OnKilled();
+ void OnRoundRespawn();
+ bool CanChangeNickname();
+ void OnNicknameChanged();
CBasePlayer *BasePlayer() const;
@@ -125,6 +129,7 @@ class CCSPlayer: public CCSMonster {
int m_iWeaponInfiniteIds;
bool m_bCanShootOverride;
bool m_bGameForcingRespawn;
+ int m_iNickChangesBeforeSpawn;
};
// Inlines