diff --git a/README.md b/README.md
index 6713f49a..ecda6502 100644
--- a/README.md
+++ b/README.md
@@ -109,6 +109,7 @@ This means that plugins that do binary code analysis (Orpheu for example) probab
| mp_give_c4_frags | 3 | - | - | How many bonuses (frags) will get the player who defused or exploded the bomb. |
| mp_hostages_rescued_ratio | 1.0 | 0.0 | 1.0 | Ratio of hostages rescued to win the round. |
| mp_legacy_vehicle_block | 1 | 0 | 1 | Legacy func_vehicle behavior when blocked by another entity.
`0` New behavior
`1` Legacy behavior |
+| mp_dying_time | 3.0 | 0.0 | - | Time for switch to free observing after death.
`0` - disable spectating around death.
`>0.00001` - time delay to start spectate.
`NOTE`: The countdown starts when the player’s death animation is finished.|
## How to install zBot for CS 1.6?
diff --git a/dist/game.cfg b/dist/game.cfg
index 25ba9877..76b28aa7 100644
--- a/dist/game.cfg
+++ b/dist/game.cfg
@@ -521,3 +521,11 @@ mp_hostages_rescued_ratio "1.0"
//
// Default value: "1"
mp_legacy_vehicle_block "1"
+
+// Time for switch to free observing after death.
+// NOTE: The countdown starts when the player’s death animation is finished.
+// 0 - disable spectating around death
+// >0.00001 - time delay to start spectate
+//
+// Default value: "3.0"
+mp_dying_time "3.0"
diff --git a/regamedll/dlls/game.cpp b/regamedll/dlls/game.cpp
index 2e0ef12b..237a8f51 100644
--- a/regamedll/dlls/game.cpp
+++ b/regamedll/dlls/game.cpp
@@ -170,6 +170,8 @@ 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 };
+
void GameDLL_Version_f()
{
if (Q_stricmp(CMD_ARGV(1), "version") != 0)
@@ -418,6 +420,8 @@ void EXT_FUNC GameDLLInit()
CVAR_REGISTER(&legacy_vehicle_block);
+ CVAR_REGISTER(&dying_time);
+
// print version
CONSOLE_ECHO("ReGameDLL version: " APP_VERSION "\n");
diff --git a/regamedll/dlls/game.h b/regamedll/dlls/game.h
index ed2ae509..18ae0fdb 100644
--- a/regamedll/dlls/game.h
+++ b/regamedll/dlls/game.h
@@ -192,8 +192,9 @@ extern cvar_t sv_enablebunnyhopping;
extern cvar_t plant_c4_anywhere;
extern cvar_t give_c4_frags;
extern cvar_t hostages_rescued_ratio;
-
extern cvar_t legacy_vehicle_block;
+extern cvar_t dying_time;
+
#endif
extern cvar_t scoreboard_showmoney;
diff --git a/regamedll/dlls/gamerules.h b/regamedll/dlls/gamerules.h
index d6975df0..f6c621bd 100644
--- a/regamedll/dlls/gamerules.h
+++ b/regamedll/dlls/gamerules.h
@@ -46,6 +46,7 @@ const float ROUND_RESPAWN_TIME = 20.0f;
const float ROUND_BEGIN_DELAY = 5.0f; // delay before beginning new round
const float ITEM_KILL_DELAY = 300.0f;
const float RADIO_TIMEOUT = 1.5f;
+const float DEATH_ANIMATION_TIME = 3.0f;
const int MAX_INTERMISSION_TIME = 120; // longest the intermission can last, in seconds
@@ -206,7 +207,7 @@ enum
SCENARIO_BLOCK_PRISON_ESCAPE_TIME = BIT(8), // flag "i"
SCENARIO_BLOCK_BOMB_TIME = BIT(9), // flag "j"
SCENARIO_BLOCK_HOSTAGE_RESCUE_TIME = BIT(10), // flag "k"
-
+
};
// Player relationship return codes
@@ -336,6 +337,7 @@ public:
inline void SetGameOver() { m_bGameOver = true; }
static float GetItemKillDelay();
static float GetRadioTimeout();
+ static float GetDyingTime();
public:
BOOL m_bFreezePeriod; // TRUE at beginning of round, set to FALSE when the period expires
@@ -921,6 +923,15 @@ inline float CGameRules::GetRadioTimeout()
#endif
}
+inline float CGameRules::GetDyingTime()
+{
+#ifdef REGAMEDLL_ADD
+ return dying_time.value;
+#else
+ return DEATH_ANIMATION_TIME;
+#endif
+}
+
bool IsBotSpeaking();
void SV_Continue_f();
void SV_Tutor_Toggle_f();
diff --git a/regamedll/dlls/player.cpp b/regamedll/dlls/player.cpp
index 92a0d69e..58f82720 100644
--- a/regamedll/dlls/player.cpp
+++ b/regamedll/dlls/player.cpp
@@ -3857,7 +3857,7 @@ void CBasePlayer::PlayerDeathThink()
{
// if the player has been dead for one second longer than allowed by forcerespawn,
// forcerespawn isn't on. Send the player off to an intermission camera until they choose to respawn.
- if (g_pGameRules->IsMultiplayer() && HasTimePassedSinceDeath(3.0f) && !(m_afPhysicsFlags & PFLAG_OBSERVER))
+ if (g_pGameRules->IsMultiplayer() && HasTimePassedSinceDeath(CGameRules::GetDyingTime()) && !(m_afPhysicsFlags & PFLAG_OBSERVER))
{
// Send message to everybody to spawn a corpse.
SpawnClientSideCorpse();
@@ -8818,9 +8818,7 @@ void CBasePlayer::SpawnClientSideCorpse()
if (pev->effects & EF_NODRAW)
return;
- // do not make a corpse if the player goes to respawn.
- if (pev->deadflag == DEAD_RESPAWNABLE)
- return;
+ // deadflag == DEAD_RESPAWNABLE already checked before
#endif
#ifdef REGAMEDLL_ADD
@@ -8830,6 +8828,41 @@ void CBasePlayer::SpawnClientSideCorpse()
char *infobuffer = GET_INFO_BUFFER(edict());
char *pModel = GET_KEY_VALUE(infobuffer, "model");
+ float timeDiff = pev->animtime - gpGlobals->time;
+
+#ifdef REGAMEDLL_ADD
+ if (CGameRules::GetDyingTime() < DEATH_ANIMATION_TIME) // a short time, timeDiff estimates to be small
+ {
+ float animDuration = -1.0;
+
+ studiohdr_t *pstudiohdr = (studiohdr_t *)GET_MODEL_PTR(ENT(pev));
+ if (pstudiohdr && pev->sequence < pstudiohdr->numseq) // model ptr and sequence validation
+ {
+ // get current sequence time
+ mstudioseqdesc_t *pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + int(pev->sequence);
+ animDuration = pseqdesc->numframes / pseqdesc->fps;
+ }
+
+ if (animDuration <= 0.0)
+ {
+ // in case of failure
+ animDuration = DEATH_ANIMATION_TIME;
+ }
+
+ // client receives a negative value
+ animDuration *= -1.0;
+
+ if (animDuration < timeDiff) // reasonable way to fix client side unfinished sequence bug
+ {
+ // by some reason, if client receives a value less
+ // than "(negative current sequence time) * 100"
+ // animation will play visually awkward
+ // at this function call time, player death animation
+ // has already finished so we can safely fake it
+ timeDiff = animDuration;
+ }
+ }
+#endif
MESSAGE_BEGIN(MSG_ALL, gmsgSendCorpse);
WRITE_STRING(pModel);
@@ -8839,14 +8872,17 @@ void CBasePlayer::SpawnClientSideCorpse()
WRITE_COORD(pev->angles.x);
WRITE_COORD(pev->angles.y);
WRITE_COORD(pev->angles.z);
- WRITE_LONG((pev->animtime - gpGlobals->time) * 100);
+ WRITE_LONG(timeDiff * 100);
WRITE_BYTE(pev->sequence);
WRITE_BYTE(pev->body);
WRITE_BYTE(m_iTeam);
WRITE_BYTE(entindex());
MESSAGE_END();
+#ifndef REGAMEDLL_FIXES
+ // already defined in StartDeathCam
m_canSwitchObserverModes = true;
+#endif
if (TheTutor)
{