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 @@

Targets plugin version 3.0.0 Beta 2, 2009.12.11
Written by Richard Helgeby

-

Manual last modified: 2009.12.11

+

Manual last modified: 2010.07.04

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) {