diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9bf09b4..e2de751 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,6 +26,10 @@ jobs: - name: Compile Plugin run: | + spcomp -i ./ rrm_attribute_clip.sp + spcomp -i ./ rrm_attribute_firing.sp + spcomp -i ./ rrm_attribute_projectile.sp + spcomp -i ./ rrm_attribute_spread.sp spcomp -i ./ rrm_bleed.sp spcomp -i ./ rrm_charge.sp spcomp -i ./ rrm_explode.sp @@ -43,5 +47,6 @@ jobs: spcomp -i ./ rrm_powerup_strength.sp spcomp -i ./ rrm_powerup_vampire.sp spcomp -i ./ rrm_resize.sp + spcomp -i ./ rrm_skeletons.sp spcomp -i ./ rrm_stun.sp spcomp -i ./ rrm_taunt.sp \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b48de22..78484ec 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,6 +28,10 @@ jobs: - name: Compile Plugin run: | + spcomp -i ./ rrm_attribute_clip.sp + spcomp -i ./ rrm_attribute_firing.sp + spcomp -i ./ rrm_attribute_projectile.sp + spcomp -i ./ rrm_attribute_spread.sp spcomp -i ./ rrm_bleed.sp spcomp -i ./ rrm_charge.sp spcomp -i ./ rrm_explode.sp @@ -45,6 +49,7 @@ jobs: spcomp -i ./ rrm_powerup_strength.sp spcomp -i ./ rrm_powerup_vampire.sp spcomp -i ./ rrm_resize.sp + spcomp -i ./ rrm_skeletons.sp spcomp -i ./ rrm_stun.sp spcomp -i ./ rrm_taunt.sp diff --git a/README.md b/README.md index fd981c9..a9b0b8a 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,18 @@ Additional modifiers for the [RRM](https://forums.alliedmods.net/showthread.php? |cvar|param|description| |---|:-:|---| +|`rrm_attribute_clip_min`|`0.5`|Min clip size| +|`rrm_attribute_clip_max`|`4.0`|Max clip size| +|`rrm_attribute_clip_delay`|`1.2`|Attribute delay| +|`rrm_attribute_firing_min`|`0.5`|Min firing speed| +|`rrm_attribute_firing_max`|`4.0`|Max firing speed| +|`rrm_attribute_firing_delay`|`1.2`|Attribute delay| +|`rrm_attribute_projectile_min`|`0.2`|Min projectile speed| +|`rrm_attribute_projectile_max`|`4.0`|Max projectile speed| +|`rrm_attribute_projectile_delay`|`1.2`|Attribute delay| +|`rrm_attribute_spread_min`|`0.1`|Min bullet spread speed| +|`rrm_attribute_spread_max`|`3.0`|Max bullet spread speed| +|`rrm_attribute_spread_delay`|`1.2`|Attribute delay| |`rrm_bleed_min`|`0.1`|Min bleed chance| |`rrm_bleed_max`|`1.0`|Max bleed chance| |`rrm_bleed_duration`|`3.0`|Bleed duration| @@ -24,6 +36,7 @@ Additional modifiers for the [RRM](https://forums.alliedmods.net/showthread.php? |`rrm_milk_min`|`0.1`|Min mad milk chance| |`rrm_milk_max`|`1.0`|Max mad milk chance| |`rrm_milk_duration`|`3.0`|Mad milk duration| +|`rrm_skeleton_duration`|`30.0`|Skeleton duration| |`rrm_size_min`|`0.25`|Min size| |`rrm_size_max`|`1.35`|Max size| |`rrm_stun_min`|`0.1`|Min stun chance| diff --git a/rrm_attribute_clip.sp b/rrm_attribute_clip.sp new file mode 100644 index 0000000..6113338 --- /dev/null +++ b/rrm_attribute_clip.sp @@ -0,0 +1,143 @@ +// Copyright (C) 2023 Katsute | Licensed under CC BY-NC-SA 4.0 + +#pragma semicolon 1 + +#define RRM_VERSION "1.0" + +#include +#include +#include +#include +#include +#include + +#pragma newdecls required + +int gEnabled = 0; +float gMul = 0.0; +ConVar cMin = null, cMax = null, cDelay = null; +float gMin = 0.0, gMax = 0.0, gDelay = 0.0; + +public Plugin myinfo = { + name = "[RRM] Clip Size Modifier", + author = "Katsute", + description = "Modifier that modifies clip size.", + version = "1.0" +}; + +public void OnPluginStart(){ + cMin = CreateConVar("rrm_attribute_clip_min", "0.5", "Minimum value for the random number generator."); + cMax = CreateConVar("rrm_attribute_clip_max", "4.0", "Maximum value for the random number generator."); + cDelay = CreateConVar("rrm_attribute_clip_delay", "1.2", "Delay to apply attribute."); + + cMin.AddChangeHook(OnConvarChanged); + cMax.AddChangeHook(OnConvarChanged); + cDelay.AddChangeHook(OnConvarChanged); + + gMin = cMin.FloatValue; + gMax = cMax.FloatValue; + gDelay = cDelay.FloatValue; + + HookEvent("post_inventory_application", PostInventoryApplication); + + if(RRM_IsRegOpen()) + RegisterModifiers(); + + AutoExecConfig(true, "rrm_attribute_clip", "rrm"); +} + +public int RRM_OnRegOpen(){ + RegisterModifiers(); +} + +void RegisterModifiers(){ + RRM_Register("Clip Size", gMin, gMax, false, RRM_Callback_Attribute); +} + +public void OnConvarChanged(Handle convar, char[] oldValue, char[] newValue){ + if (StrEqual(oldValue, newValue, true)) + return; + + float fNewValue = StringToFloat(newValue); + + if(convar == cMin) + gMin = fNewValue; + else if(convar == cMax) + gMax = fNewValue; + else if(convar == cDelay) + gDelay = fNewValue; +} + +public int RRM_Callback_Attribute(bool enable, float value){ + gEnabled = enable; + if(gEnabled) + gMul = value; + for(int i = 1; i < MaxClients; i++){ + if(IsClientInGame(i)){ + int health = GetClientHealth(i); + TF2_RemoveAllWeapons(i); + TF2_RegeneratePlayer(i); + SetEntityHealth(i, health < 1 ? 1 : health); + } + } + return gEnabled; +} + +public void PostInventoryApplication(const Handle event, const char[] name, const bool dontBroadcast){ + if(gEnabled){ + int client = GetClientOfUserId(GetEventInt(event, "userid")); + CreateTimer(gDelay, PostInventoryApplicationDelayed, client, TIMER_FLAG_NO_MAPCHANGE); + } +} + +public Action PostInventoryApplicationDelayed(const Handle timer, const int client){ + if(IsClientInGame(client)){ + int primary = GetPlayerWeaponSlot(client, 0); + int secondary = GetPlayerWeaponSlot(client, 1); + int melee = GetPlayerWeaponSlot(client, 2); + + if(primary != -1 && TF2Attrib_GetByDefIndex(primary, 2050) == Address_Null){ + ApplyPrimary(primary); + TF2Attrib_SetByDefIndex(primary, 2050, 1.0); + } + if(secondary != -1 && TF2Attrib_GetByDefIndex(secondary, 2050) == Address_Null){ + ApplySecondary(secondary); + TF2Attrib_SetByDefIndex(secondary, 2050, 1.0); + } + if(melee != -1 && TF2Attrib_GetByDefIndex(melee, 2050) == Address_Null){ + ApplyMelee(melee); + TF2Attrib_SetByDefIndex(melee, 2050, 1.0); + } + } + return Plugin_Continue; +} + +public void ApplyAttribute(const int ent, const int attribute, const float value){ + if(ent != -1 && IsValidEntity(ent)){ + Address addr = TF2Attrib_GetByDefIndex(ent, attribute); + float current = addr != Address_Null ? TF2Attrib_GetValue(addr) : 1.0; + TF2Attrib_SetByDefIndex(ent, attribute, current * value); + } +} + +public void ApplyPrimary(const int ent){ + int index = GetEntProp(ent, Prop_Send, "m_iItemDefinitionIndex"); + if(index != 441 && index != 588) + ApplyAttribute(ent, 4, gMul); + else + ApplyAttribute(ent, 335, gMul); + ApplyAttribute(ent, 97, 1/gMul); +} + +public void ApplySecondary(const int ent){ + int index = GetEntProp(ent, Prop_Send, "m_iItemDefinitionIndex"); + if(index != 442 && index != 595) + ApplyAttribute(ent, 4, gMul); + else + ApplyAttribute(ent, 335, gMul); + ApplyAttribute(ent, 97, (1/gMul) > 1.0 ? 1.0 : (1/gMul)); +} + +public void ApplyMelee(const int ent){ + +} \ No newline at end of file diff --git a/rrm_attribute_firing.sp b/rrm_attribute_firing.sp new file mode 100644 index 0000000..6f79379 --- /dev/null +++ b/rrm_attribute_firing.sp @@ -0,0 +1,138 @@ +// Copyright (C) 2023 Katsute | Licensed under CC BY-NC-SA 4.0 + +#pragma semicolon 1 + +#define RRM_VERSION "1.0" + +#include +#include +#include +#include +#include +#include + +#pragma newdecls required + +int gEnabled = 0; +float gMul = 0.0; +ConVar cMin = null, cMax = null, cDelay = null; +float gMin = 0.0, gMax = 0.0, gDelay = 0.0; + +public Plugin myinfo = { + name = "[RRM] Firing Speed Modifier", + author = "Katsute", + description = "Modifier that modifies firing speed.", + version = "1.0" +}; + +public void OnPluginStart(){ + cMin = CreateConVar("rrm_attribute_firing_min", "0.5", "Minimum value for the random number generator."); + cMax = CreateConVar("rrm_attribute_firing_max", "4.0", "Maximum value for the random number generator."); + cDelay = CreateConVar("rrm_attribute_firing_delay", "1.2", "Delay to apply attribute."); + + cMin.AddChangeHook(OnConvarChanged); + cMax.AddChangeHook(OnConvarChanged); + cDelay.AddChangeHook(OnConvarChanged); + + gMin = cMin.FloatValue; + gMax = cMax.FloatValue; + gDelay = cDelay.FloatValue; + + HookEvent("post_inventory_application", PostInventoryApplication); + + if(RRM_IsRegOpen()) + RegisterModifiers(); + + AutoExecConfig(true, "rrm_attribute_firing", "rrm"); +} + +public int RRM_OnRegOpen(){ + RegisterModifiers(); +} + +void RegisterModifiers(){ + RRM_Register("Firing Rate", gMin, gMax, false, RRM_Callback_Attribute); +} + +public void OnConvarChanged(Handle convar, char[] oldValue, char[] newValue){ + if (StrEqual(oldValue, newValue, true)) + return; + + float fNewValue = StringToFloat(newValue); + + if(convar == cMin) + gMin = fNewValue; + else if(convar == cMax) + gMax = fNewValue; + else if(convar == cDelay) + gDelay = fNewValue; +} + +public int RRM_Callback_Attribute(bool enable, float value){ + gEnabled = enable; + if(gEnabled) + gMul = value; + for(int i = 1; i < MaxClients; i++){ + if(IsClientInGame(i)){ + int health = GetClientHealth(i); + TF2_RemoveAllWeapons(i); + TF2_RegeneratePlayer(i); + SetEntityHealth(i, health < 1 ? 1 : health); + } + } + return gEnabled; +} + +public void PostInventoryApplication(const Handle event, const char[] name, const bool dontBroadcast){ + if(gEnabled){ + int client = GetClientOfUserId(GetEventInt(event, "userid")); + CreateTimer(gDelay, PostInventoryApplicationDelayed, client, TIMER_FLAG_NO_MAPCHANGE); + } +} + +public Action PostInventoryApplicationDelayed(const Handle timer, const int client){ + if(IsClientInGame(client)){ + int primary = GetPlayerWeaponSlot(client, 0); + int secondary = GetPlayerWeaponSlot(client, 1); + int melee = GetPlayerWeaponSlot(client, 2); + + if(primary != -1 && TF2Attrib_GetByDefIndex(primary, 2050) == Address_Null){ + ApplyPrimary(primary); + TF2Attrib_SetByDefIndex(primary, 2050, 1.0); + } + if(secondary != -1 && TF2Attrib_GetByDefIndex(secondary, 2050) == Address_Null){ + ApplySecondary(secondary); + TF2Attrib_SetByDefIndex(secondary, 2050, 1.0); + } + if(melee != -1 && TF2Attrib_GetByDefIndex(melee, 2050) == Address_Null){ + ApplyMelee(melee); + TF2Attrib_SetByDefIndex(melee, 2050, 1.0); + } + } + return Plugin_Continue; +} + +public void ApplyAttribute(const int ent, const int attribute, const float value){ + if(ent != -1 && IsValidEntity(ent)){ + Address addr = TF2Attrib_GetByDefIndex(ent, attribute); + float current = addr != Address_Null ? TF2Attrib_GetValue(addr) : 1.0; + TF2Attrib_SetByDefIndex(ent, attribute, current * value); + } +} + +public void ApplyPrimary(const int ent){ + ApplyAttribute(ent, 6, 1/gMul); + ApplyAttribute(ent, 97, (1/gMul) > 1.0 ? 1.0 : (1/gMul)); + ApplyAttribute(ent, 41, gMul); +} + +public void ApplySecondary(const int ent){ + ApplyAttribute(ent, 6, 1/gMul); + ApplyAttribute(ent, 97, (1/gMul) > 1 ? 1.0 : (1/gMul)); +} + +public void ApplyMelee(const int ent){ + ApplyAttribute(ent, 6, 1/gMul); + ApplyAttribute(ent, 97, (1/gMul) > 1.0 ? 1.0 : (1/gMul)); + ApplyAttribute(ent, 343, 1/gMul); +} \ No newline at end of file diff --git a/rrm_attribute_projectile.sp b/rrm_attribute_projectile.sp new file mode 100644 index 0000000..840f5d6 --- /dev/null +++ b/rrm_attribute_projectile.sp @@ -0,0 +1,133 @@ +// Copyright (C) 2023 Katsute | Licensed under CC BY-NC-SA 4.0 + +#pragma semicolon 1 + +#define RRM_VERSION "1.0" + +#include +#include +#include +#include +#include +#include + +#pragma newdecls required + +int gEnabled = 0; +float gMul = 0.0; +ConVar cMin = null, cMax = null, cDelay = null; +float gMin = 0.0, gMax = 0.0, gDelay = 0.0; + +public Plugin myinfo = { + name = "[RRM] Projectile Speed Modifier", + author = "Katsute", + description = "Modifier that modifies projectile speed.", + version = "1.0" +}; + +public void OnPluginStart(){ + cMin = CreateConVar("rrm_attribute_projectile_min", "0.2", "Minimum value for the random number generator."); + cMax = CreateConVar("rrm_attribute_projectile_max", "4.0", "Maximum value for the random number generator."); + cDelay = CreateConVar("rrm_attribute_projectile_delay", "1.2", "Delay to apply attribute."); + + cMin.AddChangeHook(OnConvarChanged); + cMax.AddChangeHook(OnConvarChanged); + cDelay.AddChangeHook(OnConvarChanged); + + gMin = cMin.FloatValue; + gMax = cMax.FloatValue; + gDelay = cDelay.FloatValue; + + HookEvent("post_inventory_application", PostInventoryApplication); + + if(RRM_IsRegOpen()) + RegisterModifiers(); + + AutoExecConfig(true, "rrm_attribute_projectile", "rrm"); +} + +public int RRM_OnRegOpen(){ + RegisterModifiers(); +} + +void RegisterModifiers(){ + RRM_Register("Projectile Speed", gMin, gMax, false, RRM_Callback_Attribute); +} + +public void OnConvarChanged(Handle convar, char[] oldValue, char[] newValue){ + if (StrEqual(oldValue, newValue, true)) + return; + + float fNewValue = StringToFloat(newValue); + + if(convar == cMin) + gMin = fNewValue; + else if(convar == cMax) + gMax = fNewValue; + else if(convar == cDelay) + gDelay = fNewValue; +} + +public int RRM_Callback_Attribute(bool enable, float value){ + gEnabled = enable; + if(gEnabled) + gMul = value; + for(int i = 1; i < MaxClients; i++){ + if(IsClientInGame(i)){ + int health = GetClientHealth(i); + TF2_RemoveAllWeapons(i); + TF2_RegeneratePlayer(i); + SetEntityHealth(i, health < 1 ? 1 : health); + } + } + return gEnabled; +} + +public void PostInventoryApplication(const Handle event, const char[] name, const bool dontBroadcast){ + if(gEnabled){ + int client = GetClientOfUserId(GetEventInt(event, "userid")); + CreateTimer(gDelay, PostInventoryApplicationDelayed, client, TIMER_FLAG_NO_MAPCHANGE); + } +} + +public Action PostInventoryApplicationDelayed(const Handle timer, const int client){ + if(IsClientInGame(client)){ + int primary = GetPlayerWeaponSlot(client, 0); + int secondary = GetPlayerWeaponSlot(client, 1); + int melee = GetPlayerWeaponSlot(client, 2); + + if(primary != -1 && TF2Attrib_GetByDefIndex(primary, 2050) == Address_Null){ + ApplyPrimary(primary); + TF2Attrib_SetByDefIndex(primary, 2050, 1.0); + } + if(secondary != -1 && TF2Attrib_GetByDefIndex(secondary, 2050) == Address_Null){ + ApplySecondary(secondary); + TF2Attrib_SetByDefIndex(secondary, 2050, 1.0); + } + if(melee != -1 && TF2Attrib_GetByDefIndex(melee, 2050) == Address_Null){ + ApplyMelee(melee); + TF2Attrib_SetByDefIndex(melee, 2050, 1.0); + } + } + return Plugin_Continue; +} + +public void ApplyAttribute(const int ent, const int attribute, const float value){ + if(ent != -1 && IsValidEntity(ent)){ + Address addr = TF2Attrib_GetByDefIndex(ent, attribute); + float current = addr != Address_Null ? TF2Attrib_GetValue(addr) : 1.0; + TF2Attrib_SetByDefIndex(ent, attribute, current * value); + } +} + +public void ApplyPrimary(const int ent){ + ApplyAttribute(ent, 103, gMul); +} + +public void ApplySecondary(const int ent){ + ApplyAttribute(ent, 103, gMul); +} + +public void ApplyMelee(const int ent){ + ApplyAttribute(ent, 103, gMul); +} \ No newline at end of file diff --git a/rrm_attribute_spread.sp b/rrm_attribute_spread.sp new file mode 100644 index 0000000..ac0560a --- /dev/null +++ b/rrm_attribute_spread.sp @@ -0,0 +1,133 @@ +// Copyright (C) 2023 Katsute | Licensed under CC BY-NC-SA 4.0 + +#pragma semicolon 1 + +#define RRM_VERSION "1.0" + +#include +#include +#include +#include +#include +#include + +#pragma newdecls required + +int gEnabled = 0; +float gMul = 0.0; +ConVar cMin = null, cMax = null, cDelay = null; +float gMin = 0.0, gMax = 0.0, gDelay = 0.0; + +public Plugin myinfo = { + name = "[RRM] Bullet Spread Modifier", + author = "Katsute", + description = "Modifier that modifies bullet spread.", + version = "1.0" +}; + +public void OnPluginStart(){ + cMin = CreateConVar("rrm_attribute_spread_min", "0.1", "Minimum value for the random number generator."); + cMax = CreateConVar("rrm_attribute_spread_max", "3.0", "Maximum value for the random number generator."); + cDelay = CreateConVar("rrm_attribute_spread_delay", "1.2", "Delay to apply attribute."); + + cMin.AddChangeHook(OnConvarChanged); + cMax.AddChangeHook(OnConvarChanged); + cDelay.AddChangeHook(OnConvarChanged); + + gMin = cMin.FloatValue; + gMax = cMax.FloatValue; + gDelay = cDelay.FloatValue; + + HookEvent("post_inventory_application", PostInventoryApplication); + + if(RRM_IsRegOpen()) + RegisterModifiers(); + + AutoExecConfig(true, "rrm_attribute_spread", "rrm"); +} + +public int RRM_OnRegOpen(){ + RegisterModifiers(); +} + +void RegisterModifiers(){ + RRM_Register("Bullet Spread", gMin, gMax, false, RRM_Callback_Attribute); +} + +public void OnConvarChanged(Handle convar, char[] oldValue, char[] newValue){ + if (StrEqual(oldValue, newValue, true)) + return; + + float fNewValue = StringToFloat(newValue); + + if(convar == cMin) + gMin = fNewValue; + else if(convar == cMax) + gMax = fNewValue; + else if(convar == cDelay) + gDelay = fNewValue; +} + +public int RRM_Callback_Attribute(bool enable, float value){ + gEnabled = enable; + if(gEnabled) + gMul = value; + for(int i = 1; i < MaxClients; i++){ + if(IsClientInGame(i)){ + int health = GetClientHealth(i); + TF2_RemoveAllWeapons(i); + TF2_RegeneratePlayer(i); + SetEntityHealth(i, health < 1 ? 1 : health); + } + } + return gEnabled; +} + +public void PostInventoryApplication(const Handle event, const char[] name, const bool dontBroadcast){ + if(gEnabled){ + int client = GetClientOfUserId(GetEventInt(event, "userid")); + CreateTimer(gDelay, PostInventoryApplicationDelayed, client, TIMER_FLAG_NO_MAPCHANGE); + } +} + +public Action PostInventoryApplicationDelayed(const Handle timer, const int client){ + if(IsClientInGame(client)){ + int primary = GetPlayerWeaponSlot(client, 0); + int secondary = GetPlayerWeaponSlot(client, 1); + int melee = GetPlayerWeaponSlot(client, 2); + + if(primary != -1 && TF2Attrib_GetByDefIndex(primary, 2050) == Address_Null){ + ApplyPrimary(primary); + TF2Attrib_SetByDefIndex(primary, 2050, 1.0); + } + if(secondary != -1 && TF2Attrib_GetByDefIndex(secondary, 2050) == Address_Null){ + ApplySecondary(secondary); + TF2Attrib_SetByDefIndex(secondary, 2050, 1.0); + } + if(melee != -1 && TF2Attrib_GetByDefIndex(melee, 2050) == Address_Null){ + ApplyMelee(melee); + TF2Attrib_SetByDefIndex(melee, 2050, 1.0); + } + } + return Plugin_Continue; +} + +public void ApplyAttribute(const int ent, const int attribute, const float value){ + if(ent != -1 && IsValidEntity(ent)){ + Address addr = TF2Attrib_GetByDefIndex(ent, attribute); + float current = addr != Address_Null ? TF2Attrib_GetValue(addr) : 1.0; + TF2Attrib_SetByDefIndex(ent, attribute, current * value); + } +} + +public void ApplyPrimary(const int ent){ + ApplyAttribute(ent, 106, gMul); +} + +public void ApplySecondary(const int ent){ + ApplyAttribute(ent, 106, gMul); +} + +public void ApplyMelee(const int ent){ + ApplyAttribute(ent, 106, gMul); +} \ No newline at end of file diff --git a/rrm_medieval.sp b/rrm_medieval.sp index f7be166..23f42c0 100644 --- a/rrm_medieval.sp +++ b/rrm_medieval.sp @@ -59,21 +59,25 @@ public int RRM_Callback_Medieval(bool enable, float value) void EnableMedieval() { GameRules_SetProp("m_bPlayingMedieval", 1); - for (int i = 1; i < MaxClients; i++) - { - if(!IsClientInGame(i)) - continue; - TF2_RespawnPlayer(i); + for(int i = 1; i < MaxClients; i++){ + if(IsClientInGame(i)){ + int health = GetClientHealth(i); + TF2_RemoveAllWeapons(i); + TF2_RegeneratePlayer(i); + SetEntityHealth(i, health < 1 ? 1 : health); + } } } void DisableMedieval() { GameRules_SetProp("m_bPlayingMedieval", 0); - for (int i = 1; i < MaxClients; i++) - { - if(!IsClientInGame(i)) - continue; - TF2_RespawnPlayer(i); + for(int i = 1; i < MaxClients; i++){ + if(IsClientInGame(i)){ + int health = GetClientHealth(i); + TF2_RemoveAllWeapons(i); + TF2_RegeneratePlayer(i); + SetEntityHealth(i, health < 1 ? 1 : health); + } } } \ No newline at end of file diff --git a/rrm_skeletons.sp b/rrm_skeletons.sp new file mode 100644 index 0000000..8e81ce4 --- /dev/null +++ b/rrm_skeletons.sp @@ -0,0 +1,101 @@ +// Copyright (C) 2023 Katsute | Licensed under CC BY-NC-SA 4.0 + +#pragma semicolon 1 + +#define RRM_VERSION "1.0" + +#include +#include +#include +#include +#include +#include + +#pragma newdecls required + +int gEnabled = 0; +ConVar cDuration = null; +float gDuration = 0.0; + +public Plugin myinfo = +{ + name = "[RRM] Skeleton Modifier", + author = "Katsute", + description = "Modifier that spawns skeletons.", + version = "1.0" +}; + +public void OnPluginStart() +{ + cDuration = CreateConVar("rrm_skeleton_duration", "30.0", "Duration for skeletons to exist."); + + cDuration.AddChangeHook(OnConvarChanged); + + gDuration = cDuration.FloatValue; + + if(RRM_IsRegOpen()) + RegisterModifiers(); + + AutoExecConfig(true, "rrm_skeleton", "rrm"); + + HookEvent("player_death", OnPlayerDeath); +} + +public int RRM_OnRegOpen() +{ + RegisterModifiers(); +} + +void RegisterModifiers() +{ + RRM_Register("Skeletons", 0.0, 0.0, false, RRM_Callback_Skeletons); +} + +public void OnConvarChanged(Handle convar, char[] oldValue, char[] newValue) +{ + if (StrEqual(oldValue, newValue, true)) + return; + + float fNewValue = StringToFloat(newValue); + + if(convar == cDuration) + gDuration = fNewValue; +} + +public int RRM_Callback_Skeletons(bool enable, float value) +{ + gEnabled = enable; + return gEnabled; +} + +public void OnPlayerDeath(const Handle event, const char[] name, const bool dontBroadcast){ + if(gEnabled){ + int client = GetClientOfUserId(GetEventInt(event, "userid")); + int attacker = GetClientOfUserId(GetEventInt(event, "attacker")); + + if(client != attacker && 1 <= client <= MaxClients && IsClientInGame(client) && 1 <= attacker <= MaxClients && IsClientInGame(attacker)){ + float origin[3]; + GetClientAbsOrigin(client, origin); + float angles[3]; + GetClientAbsAngles(client, angles); + angles[0] = 0.0; + angles[2] = 0.0; + + int ent = CreateEntityByName("tf_zombie"); + + TeleportEntity(ent, origin, angles, NULL_VECTOR); + + SetEntProp(ent, Prop_Send, "m_iTeamNum", GetClientTeam(client)); + SetEntProp(ent, Prop_Send, "m_nSkin", GetClientTeam(client) - 2); + + DispatchSpawn(ent); + CreateTimer(gDuration, OnSkeletonDuration, ent, TIMER_FLAG_NO_MAPCHANGE); + } + } +} + +public Action OnSkeletonDuration(const Handle timer, const int ent){ + if(IsValidEntity(ent)) + AcceptEntityInput(ent, "Kill"); + return Plugin_Continue; +} \ No newline at end of file