diff --git a/README.md b/README.md
index 6713f49a4..ecda65025 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 25ba9877f..76b28aa78 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/API/CAPI_Impl.cpp b/regamedll/dlls/API/CAPI_Impl.cpp
index 4208c0b9c..292d0b454 100644
--- a/regamedll/dlls/API/CAPI_Impl.cpp
+++ b/regamedll/dlls/API/CAPI_Impl.cpp
@@ -209,6 +209,7 @@ GAMEHOOK_REGISTRY(CBasePlayer_DeathSound);
GAMEHOOK_REGISTRY(CBasePlayer_JoiningThink);
GAMEHOOK_REGISTRY(FreeGameRules);
+GAMEHOOK_REGISTRY(PM_LadderMove);
int CReGameApi::GetMajorVersion() {
return REGAMEDLL_API_VERSION_MAJOR;
diff --git a/regamedll/dlls/API/CAPI_Impl.h b/regamedll/dlls/API/CAPI_Impl.h
index b430f50c5..5c7169ae0 100644
--- a/regamedll/dlls/API/CAPI_Impl.h
+++ b/regamedll/dlls/API/CAPI_Impl.h
@@ -357,6 +357,10 @@ typedef IHookChainRegistryImpl CReGameHookRegi
typedef IHookChainImpl CReGameHook_PM_AirMove;
typedef IHookChainRegistryImpl CReGameHookRegistry_PM_AirMove;
+// PM_LadderMove hook
+typedef IHookChainImpl CReGameHook_PM_LadderMove;
+typedef IHookChainRegistryImpl CReGameHookRegistry_PM_LadderMove;
+
// HandleMenu_ChooseAppearance hook
typedef IHookChainImpl CReGameHook_HandleMenu_ChooseAppearance;
typedef IHookChainRegistryImpl CReGameHookRegistry_HandleMenu_ChooseAppearance;
@@ -777,6 +781,8 @@ class CReGameHookchains: public IReGameHookchains {
CReGameHookRegistry_CBasePlayer_Pain m_CBasePlayer_Pain;
CReGameHookRegistry_CBasePlayer_DeathSound m_CBasePlayer_DeathSound;
CReGameHookRegistry_CBasePlayer_JoiningThink m_CBasePlayer_JoiningThink;
+
+ CReGameHookRegistry_PM_LadderMove m_PM_LadderMove;
CReGameHookRegistry_FreeGameRules m_FreeGameRules;
@@ -912,6 +918,7 @@ class CReGameHookchains: public IReGameHookchains {
virtual IReGameHookRegistry_CBasePlayer_JoiningThink *CBasePlayer_JoiningThink();
virtual IReGameHookRegistry_FreeGameRules *FreeGameRules();
+ virtual IReGameHookRegistry_PM_LadderMove *PM_LadderMove();
};
extern CReGameHookchains g_ReGameHookchains;
diff --git a/regamedll/dlls/API/CSPlayer.cpp b/regamedll/dlls/API/CSPlayer.cpp
index 2a8348cba..c59c314b9 100644
--- a/regamedll/dlls/API/CSPlayer.cpp
+++ b/regamedll/dlls/API/CSPlayer.cpp
@@ -58,7 +58,7 @@ EXT_FUNC bool CCSPlayer::JoinTeam(TeamName team)
pPlayer->StartObserver(pentSpawnSpot->v.origin, pentSpawnSpot->v.angles);
// do we have fadetoblack on? (need to fade their screen back in)
- if (fadetoblack.value)
+ if (fadetoblack.value == FADETOBLACK_STAY)
{
UTIL_ScreenFade(pPlayer, Vector(0, 0, 0), 0.001, 0, 0, FFADE_IN);
}
diff --git a/regamedll/dlls/animating.cpp b/regamedll/dlls/animating.cpp
index 8e7d84334..9e104f22e 100644
--- a/regamedll/dlls/animating.cpp
+++ b/regamedll/dlls/animating.cpp
@@ -179,6 +179,11 @@ NOXREF int CBaseAnimating::GetBodygroup(int iGroup)
return ::GetBodygroup(GET_MODEL_PTR(ENT(pev)), pev, iGroup);
}
+float CBaseAnimating::GetSequenceDuration() const
+{
+ return ::GetSequenceDuration(GET_MODEL_PTR(ENT(pev)), pev);
+}
+
int CBaseAnimating::ExtractBbox(int sequence, float *mins, float *maxs)
{
return ::ExtractBbox(GET_MODEL_PTR(ENT(pev)), sequence, mins, maxs);
diff --git a/regamedll/dlls/animation.cpp b/regamedll/dlls/animation.cpp
index 83c0bd403..7018396aa 100644
--- a/regamedll/dlls/animation.cpp
+++ b/regamedll/dlls/animation.cpp
@@ -246,6 +246,21 @@ void GetSequenceInfo(void *pmodel, entvars_t *pev, float *pflFrameRate, float *p
*pflGroundSpeed = *pflGroundSpeed * pseqdesc->fps / (pseqdesc->numframes - 1);
}
+float GetSequenceDuration(void *pmodel, entvars_t *pev)
+{
+ studiohdr_t *pstudiohdr = (studiohdr_t *)pmodel;
+ if (!pstudiohdr)
+ return 0; // model ptr is not valid
+
+ if (pev->sequence < 0 || pev->sequence >= pstudiohdr->numseq)
+ return 0; // sequence is not valid
+
+ // get current sequence time
+ mstudioseqdesc_t *pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + int(pev->sequence);
+
+ return pseqdesc->numframes / pseqdesc->fps;
+}
+
int GetSequenceFlags(void *pmodel, entvars_t *pev)
{
studiohdr_t *pstudiohdr = (studiohdr_t *)pmodel;
diff --git a/regamedll/dlls/animation.h b/regamedll/dlls/animation.h
index 54af21a8c..7889a140b 100644
--- a/regamedll/dlls/animation.h
+++ b/regamedll/dlls/animation.h
@@ -42,6 +42,7 @@ int LookupActivity(void *pmodel, entvars_t *pev, int activity);
int LookupActivityHeaviest(void *pmodel, entvars_t *pev, int activity);
int LookupSequence(void *pmodel, const char *label);
void GetSequenceInfo(void *pmodel, entvars_t *pev, float *pflFrameRate, float *pflGroundSpeed);
+float GetSequenceDuration(void *pmodel, entvars_t *pev);
int GetSequenceFlags(void *pmodel, entvars_t *pev);
float SetController(void *pmodel, entvars_t *pev, int iController, float flValue);
float SetBlending(void *pmodel, entvars_t *pev, int iBlender, float flValue);
diff --git a/regamedll/dlls/cbase.h b/regamedll/dlls/cbase.h
index 1e11bbeef..146245c76 100644
--- a/regamedll/dlls/cbase.h
+++ b/regamedll/dlls/cbase.h
@@ -369,6 +369,7 @@ class CBaseAnimating: public CBaseDelay {
float SetBoneController(int iController, float flValue = 0.0f);
void InitBoneControllers();
+ float GetSequenceDuration() const;
float SetBlending(int iBlender, float flValue);
void GetBonePosition(int iBone, Vector &origin, Vector &angles);
void GetAutomovement(Vector &origin, Vector &angles, float flInterval = 0.1f);
diff --git a/regamedll/dlls/client.cpp b/regamedll/dlls/client.cpp
index cd52b7bc3..22f58938b 100644
--- a/regamedll/dlls/client.cpp
+++ b/regamedll/dlls/client.cpp
@@ -1911,7 +1911,7 @@ BOOL EXT_FUNC __API_HOOK(HandleMenu_ChooseTeam)(CBasePlayer *pPlayer, int slot)
MESSAGE_END();
#endif
// do we have fadetoblack on? (need to fade their screen back in)
- if (fadetoblack.value)
+ if (fadetoblack.value == FADETOBLACK_STAY)
{
UTIL_ScreenFade(pPlayer, Vector(0, 0, 0), 0.001, 0, 0, FFADE_IN);
}
diff --git a/regamedll/dlls/combat.cpp b/regamedll/dlls/combat.cpp
index 620c84cfd..390c8d613 100644
--- a/regamedll/dlls/combat.cpp
+++ b/regamedll/dlls/combat.cpp
@@ -4,7 +4,7 @@ void PlayerBlind(CBasePlayer *pPlayer, entvars_t *pevInflictor, entvars_t *pevAt
{
UTIL_ScreenFade(pPlayer, color, fadeTime, fadeHold, alpha, 0);
- if (!fadetoblack.value)
+ if (fadetoblack.value != FADETOBLACK_STAY)
{
for (int i = 1; i <= gpGlobals->maxClients; i++)
{
diff --git a/regamedll/dlls/game.cpp b/regamedll/dlls/game.cpp
index 0666c6f88..f55b5fafe 100644
--- a/regamedll/dlls/game.cpp
+++ b/regamedll/dlls/game.cpp
@@ -171,6 +171,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)
@@ -420,6 +422,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 a10af801e..ce37379e1 100644
--- a/regamedll/dlls/game.h
+++ b/regamedll/dlls/game.h
@@ -193,8 +193,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 d6975df02..f6c621bd8 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 @@ class CGameRules
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/gib.cpp b/regamedll/dlls/gib.cpp
index 5b9122d04..069b118d9 100644
--- a/regamedll/dlls/gib.cpp
+++ b/regamedll/dlls/gib.cpp
@@ -5,13 +5,14 @@ LINK_ENTITY_TO_CLASS(gib, CGib, CCSGib)
void CGib::LimitVelocity()
{
float length = pev->velocity.Length();
+ float topspeed = CVAR_GET_FLOAT("sv_maxvelocity") * 0.75f;
- // ceiling at 1500. The gib velocity equation is not bounded properly. Rather than tune it
+ // ceiling at topspeed. The gib velocity equation is not bounded properly. Rather than tune it
// in 3 separate places again, I'll just limit it here.
- if (length > 1500.0)
+ if (length > topspeed)
{
- // This should really be sv_maxvelocity * 0.75 or something
- pev->velocity = pev->velocity.Normalize() * 1500;
+ // DONE: This should really be sv_maxvelocity * 0.75 or something
+ pev->velocity = pev->velocity.Normalize() * topspeed;
}
}
diff --git a/regamedll/dlls/multiplay_gamerules.cpp b/regamedll/dlls/multiplay_gamerules.cpp
index baf916589..03948aafa 100644
--- a/regamedll/dlls/multiplay_gamerules.cpp
+++ b/regamedll/dlls/multiplay_gamerules.cpp
@@ -2393,7 +2393,7 @@ void CHalfLifeMultiplay::Think()
MESSAGE_BEGIN(MSG_ALL, gmsgForceCam);
WRITE_BYTE(forcecamera.value != 0);
WRITE_BYTE(forcechasecam.value != 0);
- WRITE_BYTE(fadetoblack.value != 0);
+ WRITE_BYTE(fadetoblack.value == FADETOBLACK_STAY);
MESSAGE_END();
m_flForceCameraValue = forcecamera.value;
@@ -3456,7 +3456,7 @@ void CHalfLifeMultiplay::InitHUD(CBasePlayer *pl)
MESSAGE_BEGIN(MSG_ONE, gmsgForceCam, nullptr, pl->edict());
WRITE_BYTE(forcecamera.value != 0);
WRITE_BYTE(forcechasecam.value != 0);
- WRITE_BYTE(fadetoblack.value != 0);
+ WRITE_BYTE(fadetoblack.value == FADETOBLACK_STAY);
MESSAGE_END();
if (m_bGameOver)
@@ -3874,7 +3874,7 @@ BOOL EXT_FUNC CHalfLifeMultiplay::__API_HOOK(FPlayerCanRespawn)(CBasePlayer *pPl
{
// If this player just connected and fadetoblack is on, then maybe
// the server admin doesn't want him peeking around.
- if (fadetoblack.value != 0.0f)
+ if (fadetoblack.value == FADETOBLACK_STAY)
{
UTIL_ScreenFade(pPlayer, Vector(0, 0, 0), 3, 3, 255, (FFADE_OUT | FFADE_STAYOUT));
}
diff --git a/regamedll/dlls/observer.cpp b/regamedll/dlls/observer.cpp
index 336b7b3cc..c35b17f9a 100644
--- a/regamedll/dlls/observer.cpp
+++ b/regamedll/dlls/observer.cpp
@@ -6,7 +6,7 @@ int __API_HOOK(GetForceCamera)(CBasePlayer *pObserver)
{
int retVal;
- if (!fadetoblack.value)
+ if (fadetoblack.value != FADETOBLACK_STAY)
{
retVal = int(CVAR_GET_FLOAT("mp_forcechasecam"));
@@ -51,7 +51,7 @@ void UpdateClientEffects(CBasePlayer *pObserver, int oldMode)
{
bool clearProgress = false;
bool clearBlindness = false;
- bool blindnessOk = (fadetoblack.value == 0);
+ bool blindnessOk = (fadetoblack.value != FADETOBLACK_STAY);
bool clearNightvision = false;
if (pObserver->GetObserverMode() == OBS_IN_EYE)
diff --git a/regamedll/dlls/observer.h b/regamedll/dlls/observer.h
index 722c977a4..743936ff9 100644
--- a/regamedll/dlls/observer.h
+++ b/regamedll/dlls/observer.h
@@ -32,6 +32,12 @@
#define CAMERA_MODE_SPEC_ONLY_TEAM 1
#define CAMERA_MODE_SPEC_ONLY_FIRST_PERSON 2
+enum FadeToBlack {
+ FADETOBLACK_OFF,
+ FADETOBLACK_STAY,
+ FADETOBLACK_AT_DYING,
+};
+
int GetForceCamera(CBasePlayer *pObserver);
void UpdateClientEffects(CBasePlayer *pObserver, int oldMode);
diff --git a/regamedll/dlls/player.cpp b/regamedll/dlls/player.cpp
index 401b1be7e..d934dc75c 100644
--- a/regamedll/dlls/player.cpp
+++ b/regamedll/dlls/player.cpp
@@ -2292,6 +2292,8 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib)
UTIL_ScreenFade(this, Vector(0, 0, 0), 3, 3, 255, (FFADE_OUT | FFADE_STAYOUT));
}
#else
+
+ float flDyingDuration = GetSequenceDuration() + CGameRules::GetDyingTime();
switch ((int)fadetoblack.value)
{
default:
@@ -2307,12 +2309,12 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib)
break;
}
- case 1:
+ case FADETOBLACK_STAY:
{
- UTIL_ScreenFade(this, Vector(0, 0, 0), 3, 3, 255, (FFADE_OUT | FFADE_STAYOUT));
+ UTIL_ScreenFade(this, Vector(0, 0, 0), 0.8f, flDyingDuration, 255, (FFADE_OUT | FFADE_STAYOUT));
break;
}
- case 2:
+ case FADETOBLACK_AT_DYING:
{
pev->iuser1 = OBS_CHASE_FREE;
pev->iuser2 = ENTINDEX(edict());
@@ -2323,15 +2325,7 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib)
MESSAGE_BEGIN(MSG_ONE, gmsgADStop, nullptr, pev);
MESSAGE_END();
- for (int i = 1; i <= gpGlobals->maxClients; i++)
- {
- CBasePlayer* pObserver = UTIL_PlayerByIndex(i);
-
- if (pObserver == this || (pObserver && pObserver->IsObservingPlayer(this)))
- {
- UTIL_ScreenFade(pObserver, Vector(0, 0, 0), 1, 4, 255, (FFADE_OUT));
- }
- }
+ UTIL_ScreenFade(this, Vector(0, 0, 0), 0.8f, flDyingDuration, 255, (FFADE_OUT));
break;
}
@@ -3857,7 +3851,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();
@@ -8814,6 +8808,23 @@ int GetPlayerGaitsequence(const edict_t *pEdict)
return pPlayer->m_iGaitsequence;
}
+float CBasePlayer::GetDyingAnimationDuration() const
+{
+ float animDuration = -1.0f;
+
+ if (CGameRules::GetDyingTime() < DEATH_ANIMATION_TIME) // a short time, timeDiff estimates to be small
+ {
+ float flSequenceDuration = GetSequenceDuration();
+ if (flSequenceDuration > 0)
+ animDuration = flSequenceDuration;
+ }
+
+ if (animDuration <= 0)
+ animDuration = CGameRules::GetDyingTime(); // in case of failure
+
+ return animDuration;
+}
+
void CBasePlayer::SpawnClientSideCorpse()
{
#ifdef REGAMEDLL_FIXES
@@ -8821,9 +8832,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
@@ -8833,6 +8842,27 @@ 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 = GetDyingAnimationDuration();
+
+ // 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);
@@ -8842,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)
{
@@ -9898,7 +9931,7 @@ void CBasePlayer::UpdateLocation(bool forceUpdate)
const char *placeName = "";
- if (pev->deadflag == DEAD_NO && AreRunningCZero())
+ if (pev->deadflag == DEAD_NO && AreBotsAllowed())
{
// search the place name where is located the player
Place playerPlace = TheNavAreaGrid.GetPlace(&pev->origin);
diff --git a/regamedll/dlls/player.h b/regamedll/dlls/player.h
index e2f76c680..f1e7009d5 100644
--- a/regamedll/dlls/player.h
+++ b/regamedll/dlls/player.h
@@ -453,6 +453,7 @@ class CBasePlayer: public CBaseMonster {
static CBasePlayer *Instance(entvars_t *pev) { return Instance(ENT(pev)); }
static CBasePlayer *Instance(int offset) { return Instance(ENT(offset)); }
+ float GetDyingAnimationDuration() const;
void SpawnClientSideCorpse();
void Observer_FindNextPlayer(bool bReverse, const char *name = nullptr);
CBasePlayer *Observer_IsValidTarget(int iPlayerIndex, bool bSameTeam);
diff --git a/regamedll/dlls/tutor_base_tutor.cpp b/regamedll/dlls/tutor_base_tutor.cpp
index 8723ca2c8..2268d18b7 100644
--- a/regamedll/dlls/tutor_base_tutor.cpp
+++ b/regamedll/dlls/tutor_base_tutor.cpp
@@ -104,7 +104,7 @@ char *TutorMessageEvent::GetNextParameter(char *buf, int buflen)
Q_strncpy(buf, param->m_data, buflen);
#ifdef REGAMEDLL_FIXES
- buf[buflen] = '\0';
+ buf[buflen - 1] = '\0';
#endif
delete param;
diff --git a/regamedll/dlls/weapons.h b/regamedll/dlls/weapons.h
index 739d1538c..ad4662c1b 100644
--- a/regamedll/dlls/weapons.h
+++ b/regamedll/dlls/weapons.h
@@ -534,7 +534,7 @@ enum usp_shield_e
USP_SHIELD_SHOOT_EMPTY,
USP_SHIELD_RELOAD,
USP_SHIELD_DRAW,
- USP_SHIELD_UP_IDLE,
+ USP_SHIELD_IDLE_UP,
USP_SHIELD_UP,
USP_SHIELD_DOWN,
};
@@ -900,6 +900,19 @@ enum deagle_e
DEAGLE_DRAW,
};
+enum deagle_shield_e
+{
+ DEAGLE_SHIELD_IDLE1,
+ DEAGLE_SHIELD_SHOOT,
+ DEAGLE_SHIELD_SHOOT2,
+ DEAGLE_SHIELD_SHOOT_EMPTY,
+ DEAGLE_SHIELD_RELOAD,
+ DEAGLE_SHIELD_DRAW,
+ DEAGLE_SHIELD_IDLE_UP,
+ DEAGLE_SHIELD_UP,
+ DEAGLE_SHIELD_DOWN,
+};
+
class CDEAGLE: public CBasePlayerWeapon
{
public:
@@ -1065,7 +1078,7 @@ enum glock18_shield_e
GLOCK18_SHIELD_SHOOT_EMPTY,
GLOCK18_SHIELD_RELOAD,
GLOCK18_SHIELD_DRAW,
- GLOCK18_SHIELD_IDLE,
+ GLOCK18_SHIELD_IDLE_UP,
GLOCK18_SHIELD_UP,
GLOCK18_SHIELD_DOWN,
};
@@ -1180,7 +1193,7 @@ enum knife_shield_e
KNIFE_SHIELD_SLASH,
KNIFE_SHIELD_ATTACKHIT,
KNIFE_SHIELD_DRAW,
- KNIFE_SHIELD_UPIDLE,
+ KNIFE_SHIELD_IDLE_UP,
KNIFE_SHIELD_UP,
KNIFE_SHIELD_DOWN,
};
@@ -1858,6 +1871,19 @@ enum fiveseven_e
FIVESEVEN_DRAW,
};
+enum fiveseven_shield_e
+{
+ FIVESEVEN_SHIELD_IDLE1,
+ FIVESEVEN_SHIELD_SHOOT,
+ FIVESEVEN_SHIELD_SHOOT2,
+ FIVESEVEN_SHIELD_SHOOT_EMPTY,
+ FIVESEVEN_SHIELD_RELOAD,
+ FIVESEVEN_SHIELD_DRAW,
+ FIVESEVEN_SHIELD_IDLE_UP,
+ FIVESEVEN_SHIELD_UP,
+ FIVESEVEN_SHIELD_DOWN,
+};
+
class CFiveSeven: public CBasePlayerWeapon
{
public:
diff --git a/regamedll/dlls/weapontype.h b/regamedll/dlls/weapontype.h
index e3527e5fa..97752ec8f 100644
--- a/regamedll/dlls/weapontype.h
+++ b/regamedll/dlls/weapontype.h
@@ -318,25 +318,12 @@ enum AmmoBuyAmount
AMMO_SMOKEGRENADE_BUY = 1,
};
-enum shieldgun_e
-{
- SHIELDGUN_IDLE,
- SHIELDGUN_SHOOT1,
- SHIELDGUN_SHOOT2,
- SHIELDGUN_SHOOT_EMPTY,
- SHIELDGUN_RELOAD,
- SHIELDGUN_DRAW,
- SHIELDGUN_DRAWN_IDLE,
- SHIELDGUN_UP,
- SHIELDGUN_DOWN,
-};
-
// custom
enum shieldgren_e
{
- SHIELDREN_IDLE = 4,
- SHIELDREN_UP,
- SHIELDREN_DOWN
+ SHIELDGREN_IDLE = 4, // 3 is last grenade viewmodel sequence
+ SHIELDGREN_UP,
+ SHIELDGREN_DOWN
};
enum InventorySlotType
diff --git a/regamedll/dlls/wpn_shared/wpn_deagle.cpp b/regamedll/dlls/wpn_shared/wpn_deagle.cpp
index f7a97d5d0..7dbed0c6b 100644
--- a/regamedll/dlls/wpn_shared/wpn_deagle.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_deagle.cpp
@@ -93,7 +93,7 @@ void CDEAGLE::PrimaryAttack()
void CDEAGLE::SecondaryAttack()
{
- ShieldSecondaryFire(SHIELDGUN_UP, SHIELDGUN_DOWN);
+ ShieldSecondaryFire(DEAGLE_SHIELD_UP, DEAGLE_SHIELD_DOWN);
}
void CDEAGLE::DEAGLEFire(float flSpread, float flCycleTime, BOOL fUseSemi)
@@ -204,7 +204,7 @@ void CDEAGLE::WeaponIdle()
if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN)
{
- SendWeaponAnim(SHIELDGUN_DRAWN_IDLE, UseDecrement() != FALSE);
+ SendWeaponAnim(DEAGLE_SHIELD_IDLE_UP, UseDecrement() != FALSE);
}
}
}
diff --git a/regamedll/dlls/wpn_shared/wpn_fiveseven.cpp b/regamedll/dlls/wpn_shared/wpn_fiveseven.cpp
index 67f2f3d57..31f211f08 100644
--- a/regamedll/dlls/wpn_shared/wpn_fiveseven.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_fiveseven.cpp
@@ -92,7 +92,7 @@ void CFiveSeven::PrimaryAttack()
void CFiveSeven::SecondaryAttack()
{
- ShieldSecondaryFire(SHIELDGUN_UP, SHIELDGUN_DOWN);
+ ShieldSecondaryFire(FIVESEVEN_SHIELD_UP, FIVESEVEN_SHIELD_DOWN);
}
void CFiveSeven::FiveSevenFire(float flSpread, float flCycleTime, BOOL fUseSemi)
@@ -208,7 +208,7 @@ void CFiveSeven::WeaponIdle()
if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN)
{
- SendWeaponAnim(SHIELDGUN_DRAWN_IDLE, UseDecrement() != FALSE);
+ SendWeaponAnim(FIVESEVEN_SHIELD_IDLE_UP, UseDecrement() != FALSE);
}
}
else if (m_iClip)
diff --git a/regamedll/dlls/wpn_shared/wpn_flashbang.cpp b/regamedll/dlls/wpn_shared/wpn_flashbang.cpp
index c5462e49b..0443353e8 100644
--- a/regamedll/dlls/wpn_shared/wpn_flashbang.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_flashbang.cpp
@@ -142,7 +142,7 @@ bool CFlashbang::ShieldSecondaryFire(int iUpAnim, int iDownAnim)
void CFlashbang::SecondaryAttack()
{
- ShieldSecondaryFire(SHIELDGUN_DRAW, SHIELDGUN_DRAWN_IDLE);
+ ShieldSecondaryFire(SHIELDGREN_UP, SHIELDGREN_DOWN);
}
void CFlashbang::SetPlayerShieldAnim()
@@ -236,7 +236,7 @@ void CFlashbang::WeaponIdle()
if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN)
{
- SendWeaponAnim(SHIELDREN_IDLE, UseDecrement() != FALSE);
+ SendWeaponAnim(SHIELDGREN_IDLE, UseDecrement() != FALSE);
}
}
else
diff --git a/regamedll/dlls/wpn_shared/wpn_glock18.cpp b/regamedll/dlls/wpn_shared/wpn_glock18.cpp
index b82d5148f..c2f5399d5 100644
--- a/regamedll/dlls/wpn_shared/wpn_glock18.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_glock18.cpp
@@ -295,7 +295,7 @@ void CGLOCK18::WeaponIdle()
if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN)
{
- SendWeaponAnim(GLOCK18_SHIELD_IDLE, UseDecrement() != FALSE);
+ SendWeaponAnim(GLOCK18_SHIELD_IDLE_UP, UseDecrement() != FALSE);
}
}
// only idle if the slid isn't back
diff --git a/regamedll/dlls/wpn_shared/wpn_hegrenade.cpp b/regamedll/dlls/wpn_shared/wpn_hegrenade.cpp
index 3f17e7254..49d8eb7a8 100644
--- a/regamedll/dlls/wpn_shared/wpn_hegrenade.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_hegrenade.cpp
@@ -144,7 +144,7 @@ bool CHEGrenade::ShieldSecondaryFire(int iUpAnim, int iDownAnim)
void CHEGrenade::SecondaryAttack()
{
- ShieldSecondaryFire(SHIELDGUN_DRAW, SHIELDGUN_DRAWN_IDLE);
+ ShieldSecondaryFire(SHIELDGREN_UP, SHIELDGREN_DOWN);
}
void CHEGrenade::SetPlayerShieldAnim()
@@ -247,7 +247,7 @@ void CHEGrenade::WeaponIdle()
if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN)
{
- SendWeaponAnim(SHIELDREN_IDLE, UseDecrement() != FALSE);
+ SendWeaponAnim(SHIELDGREN_IDLE, UseDecrement() != FALSE);
}
}
else
diff --git a/regamedll/dlls/wpn_shared/wpn_p228.cpp b/regamedll/dlls/wpn_shared/wpn_p228.cpp
index 6e2c8d05b..b64f5fcf3 100644
--- a/regamedll/dlls/wpn_shared/wpn_p228.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_p228.cpp
@@ -92,7 +92,7 @@ void CP228::PrimaryAttack()
void CP228::SecondaryAttack()
{
- ShieldSecondaryFire(SHIELDGUN_UP, SHIELDGUN_DOWN);
+ ShieldSecondaryFire(P228_SHIELD_UP, P228_SHIELD_DOWN);
}
void CP228::P228Fire(float flSpread, float flCycleTime, BOOL fUseSemi)
diff --git a/regamedll/dlls/wpn_shared/wpn_smokegrenade.cpp b/regamedll/dlls/wpn_shared/wpn_smokegrenade.cpp
index d63fe3a69..ae13158b4 100644
--- a/regamedll/dlls/wpn_shared/wpn_smokegrenade.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_smokegrenade.cpp
@@ -145,7 +145,7 @@ bool CSmokeGrenade::ShieldSecondaryFire(int iUpAnim, int iDownAnim)
void CSmokeGrenade::SecondaryAttack()
{
- ShieldSecondaryFire(SHIELDGUN_DRAW, SHIELDGUN_DRAWN_IDLE);
+ ShieldSecondaryFire(SHIELDGREN_UP, SHIELDGREN_DOWN);
}
void CSmokeGrenade::SetPlayerShieldAnim()
@@ -251,7 +251,7 @@ void CSmokeGrenade::WeaponIdle()
if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN)
{
- SendWeaponAnim(SHIELDREN_IDLE, UseDecrement() != FALSE);
+ SendWeaponAnim(SHIELDGREN_IDLE, UseDecrement() != FALSE);
}
}
else
diff --git a/regamedll/dlls/wpn_shared/wpn_usp.cpp b/regamedll/dlls/wpn_shared/wpn_usp.cpp
index 6141baebe..0d830d690 100644
--- a/regamedll/dlls/wpn_shared/wpn_usp.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_usp.cpp
@@ -279,7 +279,7 @@ void CUSP::WeaponIdle()
if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN)
{
- SendWeaponAnim(USP_DRAW, UseDecrement());
+ SendWeaponAnim(USP_SHIELD_IDLE_UP, UseDecrement());
}
}
else if (m_iClip)
diff --git a/regamedll/pm_shared/pm_shared.cpp b/regamedll/pm_shared/pm_shared.cpp
index 75d4a4909..b3b57fa5d 100644
--- a/regamedll/pm_shared/pm_shared.cpp
+++ b/regamedll/pm_shared/pm_shared.cpp
@@ -1967,7 +1967,9 @@ void PM_Duck()
}
}
-void PM_LadderMove(physent_t *pLadder)
+LINK_HOOK_VOID_CHAIN(PM_LadderMove, (physent_t *pLadder), pLadder);
+
+void EXT_FUNC __API_HOOK(PM_LadderMove)(physent_t *pLadder)
{
vec3_t ladderCenter;
trace_t trace;
diff --git a/regamedll/pm_shared/pm_shared.h b/regamedll/pm_shared/pm_shared.h
index 94113ae0a..da15fb5b0 100644
--- a/regamedll/pm_shared/pm_shared.h
+++ b/regamedll/pm_shared/pm_shared.h
@@ -77,12 +77,14 @@ void PM_Init(struct playermove_s *ppmove);
void PM_Move(struct playermove_s *ppmove, int server);
char PM_FindTextureType(char *name);
void PM_AirMove_internal();
+void PM_LadderMove(physent_t *pLadder);
#ifdef REGAMEDLL_API
void PM_Init_OrigFunc(struct playermove_s *ppmove);
void PM_Move_OrigFunc(struct playermove_s *ppmove, int server);
void PM_AirMove_OrigFunc(int playerIndex = 0);
void PM_UpdateStepSound_OrigFunc();
+void PM_LadderMove_OrigFunc(physent_t *pLadder);
#else
void PM_AirMove(int playerIndex = 0);
#endif
diff --git a/regamedll/public/regamedll/regamedll_api.h b/regamedll/public/regamedll/regamedll_api.h
index 493736ca2..43b7825aa 100644
--- a/regamedll/public/regamedll/regamedll_api.h
+++ b/regamedll/public/regamedll/regamedll_api.h
@@ -236,6 +236,10 @@ typedef IHookChainRegistry IReGameHookRegistry
typedef IHookChain IReGameHook_PM_AirMove;
typedef IHookChainRegistry IReGameHookRegistry_PM_AirMove;
+// PM_LadderMove hook
+typedef IHookChain IReGameHook_PM_LadderMove;
+typedef IHookChainRegistry IReGameHookRegistry_PM_LadderMove;
+
// HandleMenu_ChooseAppearance hook
typedef IHookChain IReGameHook_HandleMenu_ChooseAppearance;
typedef IHookChainRegistry IReGameHookRegistry_HandleMenu_ChooseAppearance;
@@ -659,6 +663,7 @@ class IReGameHookchains {
virtual IReGameHookRegistry_CBasePlayer_JoiningThink *CBasePlayer_JoiningThink() = 0;
virtual IReGameHookRegistry_FreeGameRules *FreeGameRules() = 0;
+ virtual IReGameHookRegistry_PM_LadderMove *PM_LadderMove() = 0;
};
struct ReGameFuncs_t {