diff --git a/cstrike/addons/sourcemod/configs/zr/playerclasses.txt b/cstrike/addons/sourcemod/configs/zr/playerclasses.txt
index bcbb39d..36ae1fa 100644
--- a/cstrike/addons/sourcemod/configs/zr/playerclasses.txt
+++ b/cstrike/addons/sourcemod/configs/zr/playerclasses.txt
@@ -90,7 +90,7 @@
"health_infect_gain" "700"
"kill_bonus" "2"
- "speed" "350"
+ "speed" "75"
"knockback" "4"
"jump_height" "1.1"
"jump_distance" "1.2"
@@ -134,7 +134,7 @@
"health_infect_gain" "500"
"kill_bonus" "2"
- "speed" "380"
+ "speed" "100"
"knockback" "4.5"
"jump_height" "1.3"
"jump_distance" "1.2"
@@ -178,7 +178,7 @@
"health_infect_gain" "850"
"kill_bonus" "2"
- "speed" "275"
+ "speed" "-25"
"knockback" "3.5"
"jump_height" "1.3"
"jump_distance" "1.3"
@@ -222,7 +222,7 @@
"health_infect_gain" "1000"
"kill_bonus" "2"
- "speed" "280"
+ "speed" "-20"
"knockback" "2.5"
"jump_height" "0.9"
"jump_distance" "0.9"
@@ -266,7 +266,7 @@
"health_infect_gain" "700"
"kill_bonus" "4"
- "speed" "400"
+ "speed" "110"
"knockback" "2.8"
"jump_height" "1.2"
"jump_distance" "1.3"
@@ -310,7 +310,7 @@
"health_infect_gain" "700"
"kill_bonus" "1"
- "speed" "425"
+ "speed" "115"
"knockback" "2.8"
"jump_height" "1.2"
"jump_distance" "1.3"
@@ -360,7 +360,7 @@
"health_infect_gain" "0"
"kill_bonus" "2"
- "speed" "300"
+ "speed" "0"
"knockback" "0"
"jump_height" "1.0"
"jump_distance" "1.0"
@@ -404,7 +404,7 @@
"health_infect_gain" "0"
"kill_bonus" "1"
- "speed" "320"
+ "speed" "0"
"knockback" "0"
"jump_height" "1.2"
"jump_distance" "1.2"
@@ -448,7 +448,7 @@
"health_infect_gain" "0"
"kill_bonus" "1"
- "speed" "320"
+ "speed" "50"
"knockback" "0"
"jump_height" "1.2"
"jump_distance" "1.2"
@@ -492,7 +492,7 @@
"health_infect_gain" "0"
"kill_bonus" "1"
- "speed" "380"
+ "speed" "50"
"knockback" "0"
"jump_height" "1.0"
"jump_distance" "1.0"
@@ -536,7 +536,7 @@
"health_infect_gain" "0"
"kill_bonus" "1"
- "speed" "300"
+ "speed" "-30"
"knockback" "0"
"jump_height" "1.3"
"jump_distance" "1.3"
diff --git a/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg b/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg
index 6201d73..b5fdcaf 100644
--- a/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg
+++ b/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg
@@ -208,6 +208,10 @@ zr_classes_human_select "1"
// Default: "1"
zr_classes_admin_select "1"
+// Speed method to use when applying player speed. Do not touch this if you don't know what you're doing! ["lmv" = Lagged movement value | "prop" = Player speed property]
+// Default: "command"
+zr_classes_speed_method "prop"
+
// Overlay
// Allow players to toggle class overlay.
diff --git a/docs/zr_manual.htm b/docs/zr_manual.htm
index bae32a3..d587114 100644
--- a/docs/zr_manual.htm
+++ b/docs/zr_manual.htm
@@ -16,7 +16,7 @@
-
+
Index
@@ -291,14 +291,8 @@ for both zombies and humans in different classes.
SourceMod Documentation
-
- ZRTools extension (bundled). Provides some extra functions needed by Zombie:Reloaded.
- See Plugin Installation (2.2).
-
- - Or, depending on Zombie:Reloaded release -
- SDK Hooks Extension
- (version 1.1 or newer).
-
+ SDK Hooks Extension
+ (version 1.3 or newer).
2.2 Plugin Installation
@@ -1343,11 +1337,14 @@ the admin-only flag in the flags attribute.
speed |
decimal |
- 10.0 - 2000.0 |
+ 10.0 - 2000.0 | -200.0 - 800.0 |
The player's running speed.
+ Note: The limits of this attribute depends on the speed method used.
+ In LMV-mode the values are absolute (10 to 2000), but in prop-mode values are offsets from
+ normal speed at 250 (-200 to 800).
|
@@ -1783,6 +1780,23 @@ Place these console variables in the main configuration file:
0 or 1
+
+
+ zr_classes_speed_method |
+ "prop" |
+
+
+
+ Speed method to use when setting player speed.
+ Options:
+
+ "lmv" | Modifies speed with the lagged movement
+ value. This is the old method and is available for compatibility reasons. |
+ "prop" | Modifies speed with the players' speed
+ property. |
+
+ |
+
5. Modifying Class Attributes
diff --git a/env/include/sdkhooks.inc b/env/include/sdkhooks.inc
index b225c8c..bba7237 100644
--- a/env/include/sdkhooks.inc
+++ b/env/include/sdkhooks.inc
@@ -58,16 +58,47 @@ enum SDKHookType
SDKHook_WeaponCanUse,
SDKHook_WeaponDrop,
SDKHook_WeaponEquip,
+ SDKHook_WeaponSwitch,
+ SDKHook_ShouldCollide,
+ SDKHook_PreThinkPost,
+ SDKHook_PostThinkPost,
+ SDKHook_ThinkPost
+};
+
+/*
+ Alphabetized for easy readability
+
+ SDKHook_EndTouch
+ SDKHook_FireBulletsPost
+ SDKHook_OnTakeDamage
+ SDKHook_OnTakeDamagePost
+ SDKHook_PreThink
+ SDKHook_PreThinkPost
+ SDKHook_PostThink
+ SDKHook_PostThinkPost
+ SDKHook_SetTransmit
+ SDKHook_ShouldCollide
+ SDKHook_Spawn
+ SDKHook_StartTouch
+ SDKHook_Think
+ SDKHook_ThinkPost
+ SDKHook_Touch
+ SDKHook_TraceAttack
+ SDKHook_TraceAttackPost
+ SDKHook_WeaponCanSwitchTo
+ SDKHook_WeaponCanUse
+ SDKHook_WeaponDrop
+ SDKHook_WeaponEquip
SDKHook_WeaponSwitch
-}
+*/
funcenum SDKHookCB
{
- // PreThink
- // PostThink
+ // PreThink/Post
+ // PostThink/Post
public(client),
// Spawn
- // Think
+ // Think/Post
public(entity),
// EndTouch
// StartTouch
@@ -90,8 +121,10 @@ funcenum SDKHookCB
// TraceAttack
Action:public(victim, &attacker, &inflictor, &Float:damage, &damagetype, &ammotype, hitbox, hitgroup),
// TraceAttackPost
- public(victim, attacker, inflictor, Float:damage, damagetype, ammotype, hitbox, hitgroup)
-}
+ public(victim, attacker, inflictor, Float:damage, damagetype, ammotype, hitbox, hitgroup),
+ // ShouldCollide
+ Action:public(entity, &collisiongroup, &contentsmask, &bool:result)
+};
/**
@@ -138,6 +171,16 @@ forward Action:OnLevelInit(const String:mapName[], String:mapEntities[2097152]);
*/
native SDKHook(entity, SDKHookType:type, SDKHookCB:callback);
+/**
+ * @brief Hooks an entity
+ *
+ * @param entity Entity index
+ * @param type Type of function to hook
+ * @param callback Function to call when hook is called
+ * @return bool Hook Successful
+ */
+native bool:SDKHookEx(entity, SDKHookType:type, SDKHookCB:callback);
+
/**
* @brief Unhooks an entity
*
@@ -164,4 +207,4 @@ public Extension:__ext_sdkhooks =
#else
required = 0,
#endif
-};
+};
\ No newline at end of file
diff --git a/src/zombiereloaded.sp b/src/zombiereloaded.sp
index 6bf23f2..2c85d19 100644
--- a/src/zombiereloaded.sp
+++ b/src/zombiereloaded.sp
@@ -214,6 +214,7 @@ public OnConfigsExecuted()
DamageLoad();
VEffectsLoad();
SEffectsLoad();
+ ClassOnConfigsExecuted();
ClassLoad();
VolLoad();
@@ -297,3 +298,20 @@ public OnClientDisconnect(client)
ZSpawnOnClientDisconnect(client);
VolOnPlayerDisconnect(client);
}
+
+/**
+ * Called when a clients movement buttons are being processed
+ *
+ * @param client Index of the client.
+ * @param buttons Copyback buffer containing the current commands (as bitflags - see entity_prop_stocks.inc).
+ * @param impulse Copyback buffer containing the current impulse command.
+ * @param vel Players desired velocity.
+ * @param angles Players desired view angles.
+ * @param weapon Entity index of the new weapon if player switches weapon, 0 otherwise.
+ * @return Plugin_Handled to block the commands from being processed, Plugin_Continue otherwise.
+ */
+public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:angles[3], &weapon)
+{
+ Class_OnPlayerRunCmd(client, vel);
+ return Plugin_Continue;
+}
diff --git a/src/zr/cvars.inc b/src/zr/cvars.inc
index 1a4532b..d390997 100644
--- a/src/zr/cvars.inc
+++ b/src/zr/cvars.inc
@@ -70,6 +70,7 @@ enum CvarsList
Handle:CVAR_CLASSES_ZOMBIE_SELECT,
Handle:CVAR_CLASSES_HUMAN_SELECT,
Handle:CVAR_CLASSES_ADMIN_SELECT,
+ Handle:CVAR_CLASSES_SPEED_METHOD,
Handle:CVAR_WEAPONS,
Handle:CVAR_WEAPONS_RESTRICT,
Handle:CVAR_WEAPONS_RESTRICT_ENDEQUIP,
@@ -274,6 +275,7 @@ CvarsCreate()
g_hCvarsList[CVAR_CLASSES_ZOMBIE_SELECT] = CreateConVar("zr_classes_zombie_select", "1", "Allow players to select zombie classes.");
g_hCvarsList[CVAR_CLASSES_HUMAN_SELECT] = CreateConVar("zr_classes_human_select", "1", "Allow players to select human classes.");
g_hCvarsList[CVAR_CLASSES_ADMIN_SELECT] = CreateConVar("zr_classes_admin_select", "1", "Allow admins to select admin mode classes. (Not to be confused by admin-only classes!)");
+ g_hCvarsList[CVAR_CLASSES_SPEED_METHOD] = CreateConVar("zr_classes_speed_method", "prop", "Speed method to use when applying player speed. Do not touch this if you don't know what you're doing! [\"lmv\" = Lagged movement value | \"prop\" = Player speed property");
// Menu
g_hCvarsList[CVAR_CLASSES_MENU_AUTOCLOSE] = CreateConVar("zr_classes_menu_autoclose", "1", "Automatically close class selection menu after selecting a class.");
diff --git a/src/zr/playerclasses/apply.inc b/src/zr/playerclasses/apply.inc
index 1b405c7..e0df7b9 100644
--- a/src/zr/playerclasses/apply.inc
+++ b/src/zr/playerclasses/apply.inc
@@ -25,6 +25,11 @@
* ============================================================================
*/
+/**
+ * Array that stores the client's current speed.
+ */
+new Float:g_flClassApplySpeed[MAXPLAYERS + 1];
+
/**
* Applies all class attributes on a player. Changing model, hp, speed, health,
* effects etc. The players current team will be used to get the class index.
@@ -418,6 +423,80 @@ bool:ClassApplySpeed(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER)
speed = ClassGetSpeed(classindex, cachetype);
}
- ToolsSetClientLMV(client, speed);
+ ClassApplySpeedEx(client, speed);
return true;
}
+
+/**
+ * Applies the specified speed to the player.
+ *
+ * @param client Client to apply to.
+ * @param speed Speed value.
+ */
+ClassApplySpeedEx(client, Float:speed)
+{
+ // Check what speed method that's used and apply it.
+ switch (ClassSpeedMethod)
+ {
+ case ClassSpeed_LMV:
+ {
+ ToolsSetClientLMV(client, speed);
+ }
+ case ClassSpeed_Prop:
+ {
+ g_flClassApplySpeed[client] = speed;
+ }
+ }
+}
+
+/**
+ * Called before the client can "think"
+ * Here we can change the client's speed through m_flMaxSpeed.
+ *
+ * @param client The client index.
+ */
+public ClassPreThinkPost(client)
+{
+ // Only apply speed if the prop method is used.
+ if (ClassSpeedMethod == ClassSpeed_Prop)
+ {
+ if (!IsPlayerAlive(client))
+ {
+ return;
+ }
+
+ // Note: Default is around 200.0 - 250.0
+ new Float:newspeed = GetEntPropFloat(client, Prop_Data, "m_flMaxspeed") + g_flClassApplySpeed[client];
+ SetEntPropFloat(client, Prop_Data, "m_flMaxspeed", newspeed);
+ }
+}
+
+/**
+ * Called when a clients movement buttons are being processed
+ *
+ * @param client Index of the client.
+ * @param vel Players desired velocity.
+ */
+Class_OnPlayerRunCmd(client, Float:vel[3])
+{
+ if (!IsPlayerAlive(client))
+ return;
+
+ // Only modify speed if the prop method is used.
+ if (ClassSpeedMethod == ClassSpeed_Prop)
+ {
+ // x-axis speed.
+ if (vel[0] < 0.0)
+ vel[0] = -5000.0;
+
+ else if (vel[0] > 0.0)
+ vel[0] = 5000.0;
+
+ // y-axis speed.
+ if (vel[1] < 0.0)
+ vel[1] = -5000.0;
+
+ else if (vel[1] > 0.0)
+ vel[1] = 5000.0;
+ }
+}
diff --git a/src/zr/playerclasses/classevents.inc b/src/zr/playerclasses/classevents.inc
index fcbc51c..1801d9c 100644
--- a/src/zr/playerclasses/classevents.inc
+++ b/src/zr/playerclasses/classevents.inc
@@ -67,11 +67,34 @@ ClassOnMapStart()
ClassHealthRegenInit();
}
+/**
+ * Called when all configs are executed.
+ */
+ClassOnConfigsExecuted()
+{
+ new ClassSpeedMethods:speedMethod = ClassGetSpeedMethod();
+
+ if (speedMethod != ClassSpeed_Invalid)
+ {
+ // Set speed method.
+ ClassSpeedMethod = speedMethod;
+ }
+ else
+ {
+ // Fall back on default to avoid errors.
+ ClassSpeedMethod = ClassSpeed_Prop;
+ LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModules:LogModule_Playerclasses, "Config validation", "Warning: Invalid value in zr_classes_speed_method. Using default value.");
+ }
+}
+
/**
* Client has just connected to the server.
*/
ClassOnClientConnected(client)
{
+ // Unhook "PreThinkPost" on the client.
+ SDKUnhook(client, SDKHook_PreThinkPost, ClassPreThinkPost);
+
// Initialize the admin checked variable.
g_bAdminChecked[client] = false;
}
@@ -81,6 +104,9 @@ ClassOnClientConnected(client)
*/
ClassClientInit(client)
{
+ // Hook "PreThinkPost" on the client.
+ SDKHook(client, SDKHook_PreThinkPost, ClassPreThinkPost);
+
// Reset spawn flag.
ClassPlayerSpawned[client] = false;
}
diff --git a/src/zr/playerclasses/filtertools.inc b/src/zr/playerclasses/filtertools.inc
index f8c8df6..95c2859 100644
--- a/src/zr/playerclasses/filtertools.inc
+++ b/src/zr/playerclasses/filtertools.inc
@@ -267,7 +267,22 @@ stock ClassValidateAttributes(classindex)
// Speed.
new Float:speed = ClassData[classindex][Class_Speed];
- if (!(speed >= ZR_CLASS_SPEED_MIN && speed <= ZR_CLASS_SPEED_MAX))
+ new Float:min;
+ new Float:max;
+ switch (ClassSpeedMethod)
+ {
+ case ClassSpeed_LMV:
+ {
+ min = ZR_CLASS_SPEED_LMV_MIN;
+ max = ZR_CLASS_SPEED_LMV_MAX;
+ }
+ case ClassSpeed_Prop:
+ {
+ min = ZR_CLASS_SPEED_PROP_MIN;
+ max = ZR_CLASS_SPEED_PROP_MAX;
+ }
+ }
+ if (!(speed >= min && speed <= max))
{
flags += ZR_CLASS_SPEED;
}
@@ -419,7 +434,22 @@ stock ClassValidateEditableAttributes(attributes[ClassEditableAttributes])
new Float:speed = attributes[ClassEdit_Speed];
if (speed >= 0)
{
- if (!(speed >= ZR_CLASS_SPEED_MIN && speed <= ZR_CLASS_SPEED_MAX))
+ new Float:min;
+ new Float:max;
+ switch (ClassSpeedMethod)
+ {
+ case ClassSpeed_LMV:
+ {
+ min = ZR_CLASS_SPEED_LMV_MIN;
+ max = ZR_CLASS_SPEED_LMV_MAX;
+ }
+ case ClassSpeed_Prop:
+ {
+ min = ZR_CLASS_SPEED_PROP_MIN;
+ max = ZR_CLASS_SPEED_PROP_MAX;
+ }
+ }
+ if (!(speed >= min && speed <= max))
{
flags += ZR_CLASS_SPEED;
}
diff --git a/src/zr/playerclasses/playerclasses.inc b/src/zr/playerclasses/playerclasses.inc
index ada7748..30d1f8e 100644
--- a/src/zr/playerclasses/playerclasses.inc
+++ b/src/zr/playerclasses/playerclasses.inc
@@ -124,7 +124,7 @@
#define ZR_CLASS_DEFAULT_HEALTH_REGEN_AMOUNT 2
#define ZR_CLASS_DEFAULT_HEALTH_INFECT_GAIN 800
#define ZR_CLASS_DEFAULT_KILL_BONUS 2
-#define ZR_CLASS_DEFAULT_SPEED 360.0
+#define ZR_CLASS_DEFAULT_SPEED 0.0
#define ZR_CLASS_DEFAULT_KNOCKBACK 2.0
#define ZR_CLASS_DEFAULT_JUMP_HEIGHT 10.0
#define ZR_CLASS_DEFAULT_JUMP_DISTANCE 0.2
@@ -163,8 +163,10 @@
#define ZR_CLASS_HEALTH_INFECT_GAIN_MAX 20000
#define ZR_CLASS_KILL_BONUS_MIN 0
#define ZR_CLASS_KILL_BONUS_MAX 16
-#define ZR_CLASS_SPEED_MIN 10.0
-#define ZR_CLASS_SPEED_MAX 2000.0
+#define ZR_CLASS_SPEED_LMV_MIN 10.0
+#define ZR_CLASS_SPEED_LMV_MAX 2000.0
+#define ZR_CLASS_SPEED_PROP_MIN -200.0
+#define ZR_CLASS_SPEED_PROP_MAX 800.0
#define ZR_CLASS_KNOCKBACK_MIN -30.0
#define ZR_CLASS_KNOCKBACK_MAX 30.0
#define ZR_CLASS_KNOCKBACK_IGNORE -31.0 /** Used by class editor volumetric feature. */
@@ -366,6 +368,16 @@ enum ClassFilter
ClassFilter_Client /** The client to check for class group permissions. Use 0 to ignore group filter and negative to exclude classes with groups set. */
}
+/**
+ * Speed methods for applying player speed.
+ */
+enum ClassSpeedMethods
+{
+ ClassSpeed_Invalid = -1,
+ ClassSpeed_LMV, /** Modifies lagged movement value. */
+ ClassSpeed_Prop, /** Modifies players' max speed property(m_flMaxspeed). */
+}
+
/**
* Empty filter structure.
*/
@@ -463,6 +475,11 @@ new String:ClassOriginalPlayerModel[MAXPLAYERS + 1][PLATFORM_MAX_PATH];
*/
new bool:ClassPlayerSpawned[MAXPLAYERS + 1];
+/**
+ * What method used to apply speed on players.
+ */
+new ClassSpeedMethods:ClassSpeedMethod = ClassSpeed_Prop;
+
#include "zr/playerclasses/filtertools"
#include "zr/playerclasses/attributes"
#include "zr/playerclasses/apply"
@@ -655,6 +672,30 @@ public ClassOnConfigReload(ConfigFile:config)
ClassLoad();
}
+/**
+ * Gets the speed method.
+ *
+ * @return Speed method, or ClassSpeed_Invalid on error.
+ */
+ClassSpeedMethods:ClassGetSpeedMethod()
+{
+ decl String:speedMethod[16];
+ speedMethod[0] = 0;
+
+ GetConVarString(g_hCvarsList[CVAR_CLASSES_SPEED_METHOD], speedMethod, sizeof(speedMethod));
+
+ if (StrEqual(speedMethod, "lmv", false))
+ {
+ return ClassSpeed_LMV;
+ }
+ else if (StrEqual(speedMethod, "prop", false))
+ {
+ return ClassSpeed_Prop;
+ }
+
+ return ClassSpeed_Invalid;
+}
+
/**
* Updates the class data cache. Original values are retrieved from ClassData.
*
diff --git a/src/zr/spawnprotect.inc b/src/zr/spawnprotect.inc
index 9815c9f..f5f08b8 100644
--- a/src/zr/spawnprotect.inc
+++ b/src/zr/spawnprotect.inc
@@ -124,15 +124,44 @@ SpawnProtectStart(client)
return;
}
- // Set spawn protect flag on client.
- bInfectImmune[client][INFECT_TYPE_NORMAL] = true;
-
// Get spawn protect attribute cvars.
new Float:speed = GetConVarFloat(g_hCvarsList[CVAR_SPAWNPROTECT_SPEED]);
new alpha = GetConVarInt(g_hCvarsList[CVAR_SPAWNPROTECT_ALPHA]);
+ // Validate attributes
+ new Float:min;
+ new Float:max;
+ switch (ClassSpeedMethod)
+ {
+ case ClassSpeed_LMV:
+ {
+ min = ZR_CLASS_SPEED_LMV_MIN;
+ max = ZR_CLASS_SPEED_LMV_MAX;
+ }
+ case ClassSpeed_Prop:
+ {
+ min = ZR_CLASS_SPEED_PROP_MIN;
+ max = ZR_CLASS_SPEED_PROP_MAX;
+ }
+ }
+ if (speed < min && speed > max)
+ {
+ // Log a warning and abort.
+ LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModules:LogModule_Config, "Config validation", "Out of range value in cvar zr_spawnprotect_speed (%f). Aborting spawn protection.", speed);
+ return;
+ }
+ if (alpha < ZR_CLASS_ALPHA_INITIAL_MIN && alpha > ZR_CLASS_ALPHA_INITIAL_MAX)
+ {
+ // Log a warning and abort.
+ LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModules:LogModule_Config, "Config validation", "Out of range value in cvar zr_spawnprotect_alpha (%d). Aborting spawn protection.", alpha);
+ return;
+ }
+
+ // Set spawn protect flag on client.
+ bInfectImmune[client][INFECT_TYPE_NORMAL] = true;
+
// Set spawn protect attributes.
- ToolsSetClientLMV(client, speed);
+ ClassApplySpeedEx(client, speed);
ToolsSetClientAlpha(client, alpha);
// Set time left to zr_protect_time's value.
diff --git a/src/zr/tools_functions.inc b/src/zr/tools_functions.inc
index af75668..a15e194 100644
--- a/src/zr/tools_functions.inc
+++ b/src/zr/tools_functions.inc
@@ -70,7 +70,7 @@ stock ToolsClientVelocity(client, Float:vecVelocity[3], bool:apply = true, bool:
/**
* Set a client's lagged movement value.
* @param client The client index.
- * @param value LMV value. (1.0 = default, 2.0 = double)
+ * @param value LMV value. (300.0 = default, 600.0 = double)
*/
stock ToolsSetClientLMV(client, Float:fLMV)
{