From 21dca4f0211f6ee8885b303e50910655c29dfb43 Mon Sep 17 00:00:00 2001 From: RetroReul Date: Fri, 13 Mar 2026 22:19:49 +0200 Subject: [PATCH 01/11] some methods --- .../AudioMethods/SpeakerExistsMethod.cs | 23 ++++++ .../Methods/DoorMethods/PryGateMethod.cs | 45 ++++++++++++ .../ElevatorMethods/ElevatorInfoMethod.cs | 50 +++++++++++++ .../ElevatorMethods/SetElevatorTextMethod.cs | 27 +++++++ .../Methods/HealthMethods/RegenerateMethod.cs | 27 +++++++ .../Methods/ItemMethods/ForceEquipMethod.cs | 32 ++++++++ .../MapMethods/CreateRagdolllMethod.cs | 73 +++++++++++++++++++ .../Methods/PlayerMethods/JumpMethod.cs | 31 ++++++++ .../PlayerMethods/SetSpectatabilityMethod.cs | 30 ++++++++ .../PlayerMethods/ShowHitMarkerMethod.cs | 28 +++++++ .../Methods/PlayerMethods/StaminaMethod.cs | 63 ++++++++++++++++ .../ScriptMethods/ScriptExistsMethod.cs | 26 +++++++ .../Methods/TextMethods/ContainsTextMethod.cs | 27 +++++++ 13 files changed, 482 insertions(+) create mode 100644 Code/MethodSystem/Methods/AudioMethods/SpeakerExistsMethod.cs create mode 100644 Code/MethodSystem/Methods/DoorMethods/PryGateMethod.cs create mode 100644 Code/MethodSystem/Methods/ElevatorMethods/ElevatorInfoMethod.cs create mode 100644 Code/MethodSystem/Methods/ElevatorMethods/SetElevatorTextMethod.cs create mode 100644 Code/MethodSystem/Methods/HealthMethods/RegenerateMethod.cs create mode 100644 Code/MethodSystem/Methods/ItemMethods/ForceEquipMethod.cs create mode 100644 Code/MethodSystem/Methods/MapMethods/CreateRagdolllMethod.cs create mode 100644 Code/MethodSystem/Methods/PlayerMethods/JumpMethod.cs create mode 100644 Code/MethodSystem/Methods/PlayerMethods/SetSpectatabilityMethod.cs create mode 100644 Code/MethodSystem/Methods/PlayerMethods/ShowHitMarkerMethod.cs create mode 100644 Code/MethodSystem/Methods/PlayerMethods/StaminaMethod.cs create mode 100644 Code/MethodSystem/Methods/ScriptMethods/ScriptExistsMethod.cs create mode 100644 Code/MethodSystem/Methods/TextMethods/ContainsTextMethod.cs diff --git a/Code/MethodSystem/Methods/AudioMethods/SpeakerExistsMethod.cs b/Code/MethodSystem/Methods/AudioMethods/SpeakerExistsMethod.cs new file mode 100644 index 0000000..c877e3f --- /dev/null +++ b/Code/MethodSystem/Methods/AudioMethods/SpeakerExistsMethod.cs @@ -0,0 +1,23 @@ +using JetBrains.Annotations; +using SER.Code.ArgumentSystem.Arguments; +using SER.Code.ArgumentSystem.BaseArguments; +using SER.Code.MethodSystem.BaseMethods.Synchronous; +using SER.Code.ValueSystem; + +namespace SER.Code.MethodSystem.Methods.AudioMethods; + +[UsedImplicitly] +public class SpeakerExistsMethod : ReturningMethod +{ + public override string Description => "Returns true or false indicating if a speaker with the provided name exists."; + + public override Argument[] ExpectedArguments { get; } = + [ + new TextArgument("speaker name") + ]; + + public override void Execute() + { + ReturnValue = AudioPlayer.TryGet(Args.GetText("speaker name"), out _); + } +} \ No newline at end of file diff --git a/Code/MethodSystem/Methods/DoorMethods/PryGateMethod.cs b/Code/MethodSystem/Methods/DoorMethods/PryGateMethod.cs new file mode 100644 index 0000000..ee28f7c --- /dev/null +++ b/Code/MethodSystem/Methods/DoorMethods/PryGateMethod.cs @@ -0,0 +1,45 @@ +using JetBrains.Annotations; +using LabApi.Features.Wrappers; +using MapGeneration.Distributors; +using SER.Code.ArgumentSystem.Arguments; +using SER.Code.ArgumentSystem.BaseArguments; +using SER.Code.MethodSystem.BaseMethods.Synchronous; + +namespace SER.Code.MethodSystem.Methods.DoorMethods; + +[UsedImplicitly] +public class PryGateMethod : SynchronousMethod +{ + public override string Description => "Pries a gate."; + + public override Argument[] ExpectedArguments => + [ + new DoorArgument("gate"), + new BoolArgument("should play effects") + { + DefaultValue = new(false, "does not play button effects"), + Description = "Whether to play gate button effects when pried." + } + ]; + + public override void Execute() + { + var door = Args.GetDoor("gate"); + var playEffects = Args.GetBool("should play effects"); + + if (door is not Gate gate) return; + + if (gate.IsOpened || gate.ExactState != 0f || gate.Base.IsBeingPried) return; + + if (playEffects) + { + gate.PlayPermissionDeniedAnimation(); + gate.PlayLockBypassDeniedSound(); + } + + // Spawn pickups in case a player goes through the gate. This should not duplicate pickups if the gate gets opened properly later. + SpawnablesDistributorBase.ServerSpawnForAllDoor(gate.Base); + + gate.Pry(); + } +} \ No newline at end of file diff --git a/Code/MethodSystem/Methods/ElevatorMethods/ElevatorInfoMethod.cs b/Code/MethodSystem/Methods/ElevatorMethods/ElevatorInfoMethod.cs new file mode 100644 index 0000000..857f7f1 --- /dev/null +++ b/Code/MethodSystem/Methods/ElevatorMethods/ElevatorInfoMethod.cs @@ -0,0 +1,50 @@ +using JetBrains.Annotations; +using LabApi.Features.Wrappers; +using SER.Code.ArgumentSystem.Arguments; +using SER.Code.ArgumentSystem.BaseArguments; +using SER.Code.Exceptions; +using SER.Code.MethodSystem.BaseMethods.Synchronous; +using SER.Code.MethodSystem.MethodDescriptors; +using SER.Code.ValueSystem; + +namespace SER.Code.MethodSystem.Methods.ElevatorMethods; + +[UsedImplicitly] +public class ElevatorInfoMethod : ReturningMethod, IReferenceResolvingMethod +{ + public override string? Description => IReferenceResolvingMethod.Desc.Get(this); + public override Argument[] ExpectedArguments => + [ + new ReferenceArgument("elevator"), + new OptionsArgument("info", options: + [ + new("name"), + new("group"), + new("isReady"), + new("isGoingUp"), + new("currentSequence"), + new("allDoorsLockedReason"), + new("anyDoorLockedReason"), + new("isAdminLocked") + ]) + ]; + public override void Execute() + { + var elevator = Args.GetReference("elevator"); + ReturnValue = Args.GetOption("info") switch + { + "name" => new StaticTextValue(elevator.Base.name), + "group" => new StaticTextValue(elevator.Group.ToString()), + "isready" => new BoolValue(elevator.IsReady), + "isgoingup" => new BoolValue(elevator.GoingUp), + "currentsequence" => new StaticTextValue(elevator.CurrentSequence.ToString()), + "alldoorslockedreason" => new StaticTextValue(elevator.AllDoorsLockedReason.ToString()), + "anydoorlockedreason" => new StaticTextValue(elevator.AnyDoorLockedReason.ToString()), + "isadminlocked" => new BoolValue(elevator.DynamicAdminLock), + _ => throw new ScriptRuntimeError(this, "out of range") + }; + } + + public override TypeOfValue Returns => new TypesOfValue([typeof(TextValue), typeof(BoolValue)]); + public Type ResolvesReference => typeof(Elevator); +} \ No newline at end of file diff --git a/Code/MethodSystem/Methods/ElevatorMethods/SetElevatorTextMethod.cs b/Code/MethodSystem/Methods/ElevatorMethods/SetElevatorTextMethod.cs new file mode 100644 index 0000000..5089bf3 --- /dev/null +++ b/Code/MethodSystem/Methods/ElevatorMethods/SetElevatorTextMethod.cs @@ -0,0 +1,27 @@ +using JetBrains.Annotations; +using LabApi.Features.Wrappers; +using SER.Code.ArgumentSystem.Arguments; +using SER.Code.ArgumentSystem.BaseArguments; +using SER.Code.MethodSystem.BaseMethods.Synchronous; + +namespace SER.Code.MethodSystem.Methods.ElevatorMethods; + +[UsedImplicitly] +public class SetElevatorTextMethod : SynchronousMethod +{ + public override string Description => "Changes the text on the elevator panels between LCZ and HCZ."; + + public override Argument[] ExpectedArguments => + [ + new TextArgument("new text") + { + DefaultValue = new(string.Empty, "Resets the text to it's original value."), + Description = "An empty value will reset the text." + } + ]; + + public override void Execute() + { + Decontamination.ElevatorsText = Args.GetText("text"); + } +} \ No newline at end of file diff --git a/Code/MethodSystem/Methods/HealthMethods/RegenerateMethod.cs b/Code/MethodSystem/Methods/HealthMethods/RegenerateMethod.cs new file mode 100644 index 0000000..8979ae2 --- /dev/null +++ b/Code/MethodSystem/Methods/HealthMethods/RegenerateMethod.cs @@ -0,0 +1,27 @@ +using JetBrains.Annotations; +using SER.Code.ArgumentSystem.Arguments; +using SER.Code.ArgumentSystem.BaseArguments; +using SER.Code.MethodSystem.BaseMethods.Synchronous; + +namespace SER.Code.MethodSystem.Methods.HealthMethods; + +[UsedImplicitly] +public class RegenerateMethod : SynchronousMethod +{ + public override string Description => "Adds health regeneration to players."; + + public override Argument[] ExpectedArguments => + [ + new PlayersArgument("players"), + new FloatArgument("regeneration rate"), + new FloatArgument("regeneration duration") + ]; + + public override void Execute() + { + var players = Args.GetPlayers("players"); + var regenerationRate = Args.GetFloat("regeneration rate"); + var regenerationDuration = Args.GetFloat("regeneration duration"); + players.ForEach(plr => plr.AddRegeneration(regenerationRate, regenerationDuration)); + } +} \ No newline at end of file diff --git a/Code/MethodSystem/Methods/ItemMethods/ForceEquipMethod.cs b/Code/MethodSystem/Methods/ItemMethods/ForceEquipMethod.cs new file mode 100644 index 0000000..bc95f6b --- /dev/null +++ b/Code/MethodSystem/Methods/ItemMethods/ForceEquipMethod.cs @@ -0,0 +1,32 @@ +using JetBrains.Annotations; +using LabApi.Features.Wrappers; +using SER.Code.ArgumentSystem.Arguments; +using SER.Code.ArgumentSystem.BaseArguments; +using SER.Code.MethodSystem.BaseMethods.Synchronous; + +namespace SER.Code.MethodSystem.Methods.ItemMethods; + +[UsedImplicitly] +public class ForceEquipMethod : SynchronousMethod +{ + public override string Description => "Forces players to equip a provided item."; + + public override Argument[] ExpectedArguments => + [ + new PlayersArgument("players"), + new EnumArgument("item type") + { DefaultValue = new(ItemType.None, "Un-equip held item.") } + ]; + + public override void Execute() + { + var players = Args.GetPlayers("players"); + var itemType = Args.GetEnum("item type"); + + players.ForEach(plr => + { + var item = itemType != ItemType.None ? Item.Get(plr.Inventory.UserInventory.Items.FirstOrDefault(x => x.Value.ItemTypeId == itemType).Value) : null; + plr.CurrentItem = item; + }); + } +} \ No newline at end of file diff --git a/Code/MethodSystem/Methods/MapMethods/CreateRagdolllMethod.cs b/Code/MethodSystem/Methods/MapMethods/CreateRagdolllMethod.cs new file mode 100644 index 0000000..3bf9739 --- /dev/null +++ b/Code/MethodSystem/Methods/MapMethods/CreateRagdolllMethod.cs @@ -0,0 +1,73 @@ +using JetBrains.Annotations; +using LabApi.Features.Wrappers; +using PlayerRoles; +using PlayerStatsSystem; +using SER.Code.ArgumentSystem.Arguments; +using SER.Code.ArgumentSystem.BaseArguments; +using SER.Code.Exceptions; +using SER.Code.MethodSystem.BaseMethods.Synchronous; +using SER.Code.MethodSystem.MethodDescriptors; +using SER.Code.ValueSystem; +using UnityEngine; + +namespace SER.Code.MethodSystem.Methods.MapMethods; + +[UsedImplicitly] +public class SpawnRagdollMethod : SynchronousMethod, ICanError +{ + public override string Description => "Spawns a ragdoll."; + + public override Argument[] ExpectedArguments => + [ + new EnumArgument("role"), + new TextArgument("name"), + new ReferenceArgument("position"), + new ReferenceArgument("scale") + { DefaultValue = new(null, "default size") }, + new ReferenceArgument("rotation") + { DefaultValue = new(Quaternion.identity, "default rotation") }, + new AnyValueArgument("damage handler") + { + DefaultValue = new(new CustomReasonDamageHandler(""), "damage reason will be blank"), + Description = $"Accepts a {nameof(TextValue)} or a {nameof(DamageHandlerBase)} reference." + }, + ]; + + public override void Execute() + { + var role = Args.GetEnum("role"); + var name = Args.GetText("name"); + var position = Args.GetReference("position"); + var scale = Args.GetReference("scale"); + var rotation = Args.GetReference("rotation"); + var value = Args.GetAnyValue("damage handler"); + + DamageHandlerBase? damageHandler = null; + + switch (value) + { + case ReferenceValue referenceValue: + { + if (referenceValue.Value is DamageHandlerBase handler) + damageHandler = handler; + else + throw new ScriptRuntimeError(this, ErrorReasons[1]); + break; + } + case TextValue textValue: + damageHandler = new CustomReasonDamageHandler(textValue.StringRep); + break; + } + + if (damageHandler is null) + throw new ScriptRuntimeError(this, ErrorReasons[0]); + + Ragdoll.SpawnRagdoll(role, position, rotation, damageHandler, name, scale); + } + + public string[] ErrorReasons => + [ + $"Damage handler value must be a {nameof(DamageHandlerBase)} reference or a {nameof(TextValue)}.", + $"The provided reference value was not a {nameof(DamageHandlerBase)} reference." + ]; +} \ No newline at end of file diff --git a/Code/MethodSystem/Methods/PlayerMethods/JumpMethod.cs b/Code/MethodSystem/Methods/PlayerMethods/JumpMethod.cs new file mode 100644 index 0000000..d348632 --- /dev/null +++ b/Code/MethodSystem/Methods/PlayerMethods/JumpMethod.cs @@ -0,0 +1,31 @@ +using JetBrains.Annotations; +using SER.Code.ArgumentSystem.Arguments; +using SER.Code.ArgumentSystem.BaseArguments; +using SER.Code.MethodSystem.BaseMethods.Synchronous; +using SER.Code.MethodSystem.MethodDescriptors; + +namespace SER.Code.MethodSystem.Methods.PlayerMethods; + +[UsedImplicitly] +public class JumpMethod : SynchronousMethod, IAdditionalDescription +{ + public override string Description => + "Makes players jump (with modifiable jump strength)."; + + public override Argument[] ExpectedArguments { get; } = + [ + new PlayersArgument("players"), + new FloatArgument("jump strength") + { DefaultValue = new(4.9f, "default jump strength") } + ]; + + public override void Execute() + { + var players = Args.GetPlayers("players"); + var jumpStrength = Args.GetFloat("jump strength"); + + players.ForEach(plr => plr.Jump(jumpStrength)); + } + + public string AdditionalDescription => "This also works for players in the air. Allowing for mid-air jumps."; +} \ No newline at end of file diff --git a/Code/MethodSystem/Methods/PlayerMethods/SetSpectatabilityMethod.cs b/Code/MethodSystem/Methods/PlayerMethods/SetSpectatabilityMethod.cs new file mode 100644 index 0000000..3ca512b --- /dev/null +++ b/Code/MethodSystem/Methods/PlayerMethods/SetSpectatabilityMethod.cs @@ -0,0 +1,30 @@ +using JetBrains.Annotations; +using PlayerRoles.Spectating; +using SER.Code.ArgumentSystem.Arguments; +using SER.Code.ArgumentSystem.BaseArguments; +using SER.Code.MethodSystem.BaseMethods.Synchronous; + +namespace SER.Code.MethodSystem.Methods.PlayerMethods; + +[UsedImplicitly] +public class SetSpectatabilityMethod : SynchronousMethod +{ + public override string Description => "Sets spectatability for players."; + + public override Argument[] ExpectedArguments { get; } = + [ + new PlayersArgument("players"), + new BoolArgument("is spectatable") + ]; + + public override void Execute() + { + var players = Args.GetPlayers("players"); + var isSpectatable = Args.GetBool("is spectatable"); + + players.ForEach(player => + { + SpectatableVisibilityManager.SetHidden(player.ReferenceHub, isSpectatable); + }); + } +} \ No newline at end of file diff --git a/Code/MethodSystem/Methods/PlayerMethods/ShowHitMarkerMethod.cs b/Code/MethodSystem/Methods/PlayerMethods/ShowHitMarkerMethod.cs new file mode 100644 index 0000000..7f070a3 --- /dev/null +++ b/Code/MethodSystem/Methods/PlayerMethods/ShowHitMarkerMethod.cs @@ -0,0 +1,28 @@ +using JetBrains.Annotations; +using SER.Code.ArgumentSystem.Arguments; +using SER.Code.ArgumentSystem.BaseArguments; +using SER.Code.MethodSystem.BaseMethods.Synchronous; + +namespace SER.Code.MethodSystem.Methods.PlayerMethods; + +[UsedImplicitly] +public class ShowHitMarkerMethod : SynchronousMethod +{ + public override string Description => + "Shows a hit marker to players."; + + public override Argument[] ExpectedArguments { get; } = + [ + new PlayersArgument("players"), + new FloatArgument("hitmarker size") + { DefaultValue = new(1f, "default size") } + ]; + + public override void Execute() + { + var players = Args.GetPlayers("players"); + var size = Args.GetFloat("hitmarker size"); + + players.ForEach(plr => plr.SendHitMarker(size)); + } +} \ No newline at end of file diff --git a/Code/MethodSystem/Methods/PlayerMethods/StaminaMethod.cs b/Code/MethodSystem/Methods/PlayerMethods/StaminaMethod.cs new file mode 100644 index 0000000..ed63fbf --- /dev/null +++ b/Code/MethodSystem/Methods/PlayerMethods/StaminaMethod.cs @@ -0,0 +1,63 @@ +using JetBrains.Annotations; +using PlayerRoles.FirstPersonControl; +using SER.Code.ArgumentSystem.Arguments; +using SER.Code.ArgumentSystem.BaseArguments; +using SER.Code.MethodSystem.BaseMethods.Synchronous; + +namespace SER.Code.MethodSystem.Methods.PlayerMethods; + +[UsedImplicitly] +public class StaminaMethod : SynchronousMethod +{ + public override string Description => "Control a player's stamina."; + + public override Argument[] ExpectedArguments => + [ + new OptionsArgument("options", options: + [ + new("add"), + new("remove"), + new("set"), + ]), + new PlayersArgument("players"), + new FloatArgument("stamina value", 0f, 1f) + { + Description = "Stamina is valued from 0 to 1. 0 meaning an empty stamina bar and 1 meaning a full stamina bar." + }, + new BoolArgument("delay stamina regen") + { + Description = "Stops stamina regeneration for a short duration after applying new stamina value, just like at the end of a sprint.", + DefaultValue = new(true, "will delay stamina regeneration for a second when new stamina value is applied.") + } + ]; + + public override void Execute() + { + var players = Args.GetPlayers("players"); + var staminaValue = Args.GetFloat("stamina value"); + + players.ForEach(plr => + { + if (plr?.RoleBase is not IFpcRole currentRole) return; + var newStamina = 0f; + switch (Args.GetOption("options")) + { + case "add": + newStamina = plr.StaminaRemaining + staminaValue; + if (newStamina > 1) newStamina = 1; + break; + case "remove": + newStamina = plr.StaminaRemaining - staminaValue; + if (newStamina < 0) newStamina = 0; + break; + case "set": + newStamina = staminaValue; + break; + } + + plr.StaminaRemaining = newStamina; + if (Args.GetBool("delay stamina regen")) + currentRole.FpcModule.StateProcessor._regenStopwatch.Restart(); + }); + } +} \ No newline at end of file diff --git a/Code/MethodSystem/Methods/ScriptMethods/ScriptExistsMethod.cs b/Code/MethodSystem/Methods/ScriptMethods/ScriptExistsMethod.cs new file mode 100644 index 0000000..8d40ebb --- /dev/null +++ b/Code/MethodSystem/Methods/ScriptMethods/ScriptExistsMethod.cs @@ -0,0 +1,26 @@ +using JetBrains.Annotations; +using SER.Code.ArgumentSystem.Arguments; +using SER.Code.ArgumentSystem.BaseArguments; +using SER.Code.MethodSystem.BaseMethods.Synchronous; +using SER.Code.ValueSystem; + +namespace SER.Code.MethodSystem.Methods.ScriptMethods; + +[UsedImplicitly] +public class ScriptExistsMethod : ReturningMethod +{ + public override string Description => "Returns true or false indicating if a script with the provided name exists."; + + public override Argument[] ExpectedArguments => + [ + new TextArgument("script name") + ]; + + public override void Execute() + { + var scriptName = Args.GetText("script name"); + ReturnValue = new BoolValue(FileSystem.FileSystem.RegisteredScriptPaths.Any(p => Path.GetFileNameWithoutExtension(p) == scriptName)); + } + + public override TypeOfValue Returns => new SingleTypeOfValue(typeof(BoolValue)); +} \ No newline at end of file diff --git a/Code/MethodSystem/Methods/TextMethods/ContainsTextMethod.cs b/Code/MethodSystem/Methods/TextMethods/ContainsTextMethod.cs new file mode 100644 index 0000000..0433416 --- /dev/null +++ b/Code/MethodSystem/Methods/TextMethods/ContainsTextMethod.cs @@ -0,0 +1,27 @@ +using JetBrains.Annotations; +using SER.Code.ArgumentSystem.Arguments; +using SER.Code.ArgumentSystem.BaseArguments; +using SER.Code.MethodSystem.BaseMethods.Synchronous; +using SER.Code.ValueSystem; + +namespace SER.Code.MethodSystem.Methods.TextMethods; + +[UsedImplicitly] +public class ContainsTextMethod : ReturningMethod +{ + public override string Description => "Returns true or false indicating if the provided text contains a provided value."; + + public override Argument[] ExpectedArguments => + [ + new TextArgument("text"), + new TextArgument("text to check for"), + ]; + public override void Execute() + { + var stringToCheck = Args.GetText("text"); + var substringToCheck = Args.GetText("text to check for"); + ReturnValue = new BoolValue(stringToCheck.Contains(substringToCheck)); + } + + public override TypeOfValue Returns => new SingleTypeOfValue(typeof(BoolValue)); +} \ No newline at end of file From 86d610deae6155a2ed2c0b793127a65650ab8857 Mon Sep 17 00:00:00 2001 From: RetroReul Date: Fri, 13 Mar 2026 23:31:49 +0200 Subject: [PATCH 02/11] fixed some oopsies --- Code/Exceptions/RetroReulFuckedUpException.cs | 12 ++++++++++++ .../Methods/ElevatorMethods/ElevatorInfoMethod.cs | 9 ++++++--- .../Methods/ElevatorMethods/SetElevatorTextMethod.cs | 8 +++++--- .../Methods/PlayerMethods/StaminaMethod.cs | 6 +++--- 4 files changed, 26 insertions(+), 9 deletions(-) create mode 100644 Code/Exceptions/RetroReulFuckedUpException.cs diff --git a/Code/Exceptions/RetroReulFuckedUpException.cs b/Code/Exceptions/RetroReulFuckedUpException.cs new file mode 100644 index 0000000..14b9ad8 --- /dev/null +++ b/Code/Exceptions/RetroReulFuckedUpException.cs @@ -0,0 +1,12 @@ +namespace SER.Code.Exceptions; + +public class RetroReulFuckedUpException : DeveloperFuckedUpException +{ + public RetroReulFuckedUpException() : base("retroreul") + { + } + + public RetroReulFuckedUpException(string msg) : base("retroreul", msg) + { + } +} \ No newline at end of file diff --git a/Code/MethodSystem/Methods/ElevatorMethods/ElevatorInfoMethod.cs b/Code/MethodSystem/Methods/ElevatorMethods/ElevatorInfoMethod.cs index 857f7f1..ad0110f 100644 --- a/Code/MethodSystem/Methods/ElevatorMethods/ElevatorInfoMethod.cs +++ b/Code/MethodSystem/Methods/ElevatorMethods/ElevatorInfoMethod.cs @@ -12,7 +12,7 @@ namespace SER.Code.MethodSystem.Methods.ElevatorMethods; [UsedImplicitly] public class ElevatorInfoMethod : ReturningMethod, IReferenceResolvingMethod { - public override string? Description => IReferenceResolvingMethod.Desc.Get(this); + public override string Description => IReferenceResolvingMethod.Desc.Get(this); public override Argument[] ExpectedArguments => [ new ReferenceArgument("elevator"), @@ -41,10 +41,13 @@ public override void Execute() "alldoorslockedreason" => new StaticTextValue(elevator.AllDoorsLockedReason.ToString()), "anydoorlockedreason" => new StaticTextValue(elevator.AnyDoorLockedReason.ToString()), "isadminlocked" => new BoolValue(elevator.DynamicAdminLock), - _ => throw new ScriptRuntimeError(this, "out of range") + _ => throw new RetroReulFuckedUpException() }; } - public override TypeOfValue Returns => new TypesOfValue([typeof(TextValue), typeof(BoolValue)]); + public override TypeOfValue Returns => new TypesOfValue([ + typeof(TextValue), + typeof(BoolValue) + ]); public Type ResolvesReference => typeof(Elevator); } \ No newline at end of file diff --git a/Code/MethodSystem/Methods/ElevatorMethods/SetElevatorTextMethod.cs b/Code/MethodSystem/Methods/ElevatorMethods/SetElevatorTextMethod.cs index 5089bf3..33793e8 100644 --- a/Code/MethodSystem/Methods/ElevatorMethods/SetElevatorTextMethod.cs +++ b/Code/MethodSystem/Methods/ElevatorMethods/SetElevatorTextMethod.cs @@ -3,20 +3,20 @@ using SER.Code.ArgumentSystem.Arguments; using SER.Code.ArgumentSystem.BaseArguments; using SER.Code.MethodSystem.BaseMethods.Synchronous; +using SER.Code.MethodSystem.MethodDescriptors; namespace SER.Code.MethodSystem.Methods.ElevatorMethods; [UsedImplicitly] -public class SetElevatorTextMethod : SynchronousMethod +public class SetElevatorTextMethod : SynchronousMethod, IAdditionalDescription { public override string Description => "Changes the text on the elevator panels between LCZ and HCZ."; public override Argument[] ExpectedArguments => [ - new TextArgument("new text") + new TextArgument("text") { DefaultValue = new(string.Empty, "Resets the text to it's original value."), - Description = "An empty value will reset the text." } ]; @@ -24,4 +24,6 @@ public override void Execute() { Decontamination.ElevatorsText = Args.GetText("text"); } + + public string AdditionalDescription => "An empty text value will reset the elevator panel text to it's original value."; } \ No newline at end of file diff --git a/Code/MethodSystem/Methods/PlayerMethods/StaminaMethod.cs b/Code/MethodSystem/Methods/PlayerMethods/StaminaMethod.cs index ed63fbf..9e97f96 100644 --- a/Code/MethodSystem/Methods/PlayerMethods/StaminaMethod.cs +++ b/Code/MethodSystem/Methods/PlayerMethods/StaminaMethod.cs @@ -9,7 +9,7 @@ namespace SER.Code.MethodSystem.Methods.PlayerMethods; [UsedImplicitly] public class StaminaMethod : SynchronousMethod { - public override string Description => "Control a player's stamina."; + public override string Description => "Control the stamina of players."; public override Argument[] ExpectedArguments => [ @@ -44,11 +44,11 @@ public override void Execute() { case "add": newStamina = plr.StaminaRemaining + staminaValue; - if (newStamina > 1) newStamina = 1; + if (newStamina > 1f) newStamina = 1f; break; case "remove": newStamina = plr.StaminaRemaining - staminaValue; - if (newStamina < 0) newStamina = 0; + if (newStamina < 0f) newStamina = 0f; break; case "set": newStamina = staminaValue; From bff908c221579a81f3cd73ac859e73489459e92d Mon Sep 17 00:00:00 2001 From: RetroReul Date: Fri, 13 Mar 2026 23:49:16 +0200 Subject: [PATCH 03/11] effect category + new methods (includes a way for non-exiled users to take advantage of effects via events) --- .../EffectMethods/ClearEffectMethod.cs | 38 ++++++++++++++ .../Methods/EffectMethods/EffectInfoMethod.cs | 50 +++++++++++++++++++ .../GiveEffectMethod.cs | 2 +- .../Methods/EffectMethods/HasEffectMethod.cs | 39 +++++++++++++++ 4 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 Code/MethodSystem/Methods/EffectMethods/ClearEffectMethod.cs create mode 100644 Code/MethodSystem/Methods/EffectMethods/EffectInfoMethod.cs rename Code/MethodSystem/Methods/{PlayerMethods => EffectMethods}/GiveEffectMethod.cs (96%) create mode 100644 Code/MethodSystem/Methods/EffectMethods/HasEffectMethod.cs diff --git a/Code/MethodSystem/Methods/EffectMethods/ClearEffectMethod.cs b/Code/MethodSystem/Methods/EffectMethods/ClearEffectMethod.cs new file mode 100644 index 0000000..f274fe9 --- /dev/null +++ b/Code/MethodSystem/Methods/EffectMethods/ClearEffectMethod.cs @@ -0,0 +1,38 @@ +using Exiled.API.Enums; +using Exiled.API.Features; +using JetBrains.Annotations; +using SER.Code.ArgumentSystem.Arguments; +using SER.Code.ArgumentSystem.BaseArguments; +using SER.Code.Helpers; +using SER.Code.MethodSystem.BaseMethods.Synchronous; +using SER.Code.MethodSystem.MethodDescriptors; +using SER.Code.MethodSystem.Structures; + +namespace SER.Code.MethodSystem.Methods.EffectMethods; + +[UsedImplicitly] +public class ClearEffectMethod : SynchronousMethod, IDependOnFramework, IAdditionalDescription +{ + public override string Description => "Removes the provided status effect from players."; + + public override Argument[] ExpectedArguments => + [ + new PlayersArgument("players"), + new EnumArgument("effect type") + { DefaultValue = new (EffectType.None, "Removes all status effects") }, + ]; + + public override void Execute() + { + var players = Args.GetPlayers("players"); + var effectType = Args.GetEnum("effect type"); + + if (effectType == EffectType.None) + players.ForEach(plr => Player.Get(plr).DisableAllEffects()); + else + players.ForEach(plr => Player.Get(plr).DisableEffect(effectType)); + } + + public FrameworkBridge.Type DependsOn => FrameworkBridge.Type.Exiled; + public string AdditionalDescription => $"Using the effect type {EffectType.None} will remove all status effects."; +} \ No newline at end of file diff --git a/Code/MethodSystem/Methods/EffectMethods/EffectInfoMethod.cs b/Code/MethodSystem/Methods/EffectMethods/EffectInfoMethod.cs new file mode 100644 index 0000000..7c70beb --- /dev/null +++ b/Code/MethodSystem/Methods/EffectMethods/EffectInfoMethod.cs @@ -0,0 +1,50 @@ +using CustomPlayerEffects; +using JetBrains.Annotations; +using SER.Code.ArgumentSystem.Arguments; +using SER.Code.ArgumentSystem.BaseArguments; +using SER.Code.Exceptions; +using SER.Code.MethodSystem.BaseMethods.Synchronous; +using SER.Code.MethodSystem.MethodDescriptors; +using SER.Code.ValueSystem; + +namespace SER.Code.MethodSystem.Methods.EffectMethods; + +[UsedImplicitly] +public class EffectInfoMethod : LiteralValueReturningMethod, IReferenceResolvingMethod +{ + public override string Description => IReferenceResolvingMethod.Desc.Get(this); + + public override Argument[] ExpectedArguments => + [ + new ReferenceArgument("effect"), + new OptionsArgument("info", options: + [ + new("name"), + new("duration"), + new("intensity"), + new("classification"), + new("timeLeft") + ]) + ]; + public override void Execute() + { + var effect = Args.GetReference("effect"); + ReturnValue = Args.GetOption("info") switch + { + "name" => new StaticTextValue(effect.name), + "duration" => new DurationValue(TimeSpan.FromSeconds(effect.Duration)), + "intensity" => new NumberValue(effect.Intensity), + "classification" => new StaticTextValue(effect.Classification.ToString()), + "timeleft" => new DurationValue(TimeSpan.FromSeconds(effect.TimeLeft)), + _ => throw new RetroReulFuckedUpException() + }; + } + + public override TypeOfValue LiteralReturnTypes => new TypesOfValue([ + typeof(TextValue), + typeof(NumberValue), + typeof(DurationValue) + ]); + + public Type ResolvesReference => typeof(StatusEffectBase); +} \ No newline at end of file diff --git a/Code/MethodSystem/Methods/PlayerMethods/GiveEffectMethod.cs b/Code/MethodSystem/Methods/EffectMethods/GiveEffectMethod.cs similarity index 96% rename from Code/MethodSystem/Methods/PlayerMethods/GiveEffectMethod.cs rename to Code/MethodSystem/Methods/EffectMethods/GiveEffectMethod.cs index a386d91..8f28237 100644 --- a/Code/MethodSystem/Methods/PlayerMethods/GiveEffectMethod.cs +++ b/Code/MethodSystem/Methods/EffectMethods/GiveEffectMethod.cs @@ -7,7 +7,7 @@ using SER.Code.MethodSystem.BaseMethods.Synchronous; using SER.Code.MethodSystem.Structures; -namespace SER.Code.MethodSystem.Methods.PlayerMethods; +namespace SER.Code.MethodSystem.Methods.EffectMethods; [UsedImplicitly] public class GiveEffectMethod : SynchronousMethod, IDependOnFramework diff --git a/Code/MethodSystem/Methods/EffectMethods/HasEffectMethod.cs b/Code/MethodSystem/Methods/EffectMethods/HasEffectMethod.cs new file mode 100644 index 0000000..fcbd284 --- /dev/null +++ b/Code/MethodSystem/Methods/EffectMethods/HasEffectMethod.cs @@ -0,0 +1,39 @@ +using Exiled.API.Enums; +using Exiled.API.Features; +using JetBrains.Annotations; +using SER.Code.ArgumentSystem.Arguments; +using SER.Code.ArgumentSystem.BaseArguments; +using SER.Code.Helpers; +using SER.Code.MethodSystem.BaseMethods.Synchronous; +using SER.Code.MethodSystem.Structures; +using SER.Code.ValueSystem; + +namespace SER.Code.MethodSystem.Methods.EffectMethods; + +[UsedImplicitly] +public class HasEffectMethod : LiteralValueReturningMethod, IDependOnFramework +{ + public override TypeOfValue LiteralReturnTypes => new SingleTypeOfValue(typeof(BoolValue)); + + public override string Description => "Returns true or false indicating if the player has the provided effect."; + + public override Argument[] ExpectedArguments => + [ + new PlayerArgument("player"), + new EnumArgument("effect type") + ]; + + public override void Execute() + { + var player = Args.GetPlayer("player"); + var effectType = Args.GetEnum("effect type"); + + if (!Player.Get(player).TryGetEffect(effectType, out var effect)) + ReturnValue = new BoolValue(false); + + // this feels kinda stupid, but you never know... + ReturnValue = new BoolValue(effect.IsEnabled); + } + + public FrameworkBridge.Type DependsOn => FrameworkBridge.Type.Exiled; +} \ No newline at end of file From b9d824a3765ae0179769ba0e0ab368ebc7dd53a1 Mon Sep 17 00:00:00 2001 From: RetroReul Date: Sat, 14 Mar 2026 00:12:31 +0200 Subject: [PATCH 04/11] new player properties --- .../ExpressionTokens/PlayerExpressionToken.cs | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Code/TokenSystem/Tokens/ExpressionTokens/PlayerExpressionToken.cs b/Code/TokenSystem/Tokens/ExpressionTokens/PlayerExpressionToken.cs index dc00afe..938967b 100644 --- a/Code/TokenSystem/Tokens/ExpressionTokens/PlayerExpressionToken.cs +++ b/Code/TokenSystem/Tokens/ExpressionTokens/PlayerExpressionToken.cs @@ -1,6 +1,8 @@ using LabApi.Features.Wrappers; using PlayerRoles; +using PlayerRoles.FirstPersonControl; using PlayerRoles.PlayableScps.Scp079; +using Respawning.NamingRules; using SER.Code.ArgumentSystem.Arguments; using SER.Code.Extensions; using SER.Code.Helpers.ResultSystem; @@ -67,6 +69,16 @@ public enum PlayerProperty RelativeZ, IsNpc, IsDummy, + IsSpeaking, + IsSpectatable, + IsJumping, + IsGrounded, + Stamina, + MovementState, + RoleColor, + LifeId, + UnitId, + Unit, } public abstract class Info @@ -177,7 +189,17 @@ public class Info(Func handler, string? description) : Info [PlayerProperty.RelativeY] = new Info(plr => (decimal)plr.RelativeRoomPosition().y, "Returns the player's y relative to the current room or 0 if in no room"), [PlayerProperty.RelativeZ] = new Info(plr => (decimal)plr.RelativeRoomPosition().z, "Returns the player's z relative to the current room or 0 if in no room"), [PlayerProperty.IsNpc] = new Info(plr => plr.IsNpc, "True if it's a player without any client connected to it"), - [PlayerProperty.IsDummy] = new Info(plr => plr.IsDummy, null) + [PlayerProperty.IsDummy] = new Info(plr => plr.IsDummy, null), + [PlayerProperty.IsSpeaking] = new Info(plr => plr.IsSpeaking, null), + [PlayerProperty.IsSpectatable] = new Info(plr => plr.IsSpectatable, null), + [PlayerProperty.IsJumping] = new Info(plr => plr.RoleBase is IFpcRole currentRole && currentRole.FpcModule.Motor.JumpController.IsJumping, null), + [PlayerProperty.IsGrounded] = new Info(plr => plr.ReferenceHub.IsGrounded(), null), + [PlayerProperty.Stamina] = new Info(plr => (decimal)plr.StaminaRemaining, "Returns the player's remaining stamina."), + [PlayerProperty.MovementState] = new Info(plr => plr.RoleBase is IFpcRole currentRole ? currentRole.FpcModule.CurrentMovementState.ToString().ToStaticTextValue() : new("None"), "Returns the player's movement state or 'None' if the player is not a first-person role."), + [PlayerProperty.RoleColor] = new Info(plr => plr.RoleBase.RoleColor.ToHex().ToStaticTextValue(), "Returns the hex value of the player's role color."), + [PlayerProperty.LifeId] = new Info(plr => plr.LifeId, null), + [PlayerProperty.UnitId] = new Info(plr => (decimal)plr.UnitId, null), + [PlayerProperty.Unit] = new Info(plr => NamingRulesManager.ClientFetchReceived(plr.Team, plr.UnitId).ToStaticTextValue(), "Returns the player's unit (e.g FOXTROT-03) if player is NTF or Facility Guard, otherwise returns an empty text value."), }; protected override IParseResult InternalParse(BaseToken[] tokens) From ab0eef16671e853690f7264599a0cb4ecce9785d Mon Sep 17 00:00:00 2001 From: RetroReul Date: Sat, 14 Mar 2026 02:13:44 +0200 Subject: [PATCH 05/11] minor changes --- .../Methods/EffectMethods/ClearEffectMethod.cs | 13 ++++++------- .../Methods/ElevatorMethods/ElevatorInfoMethod.cs | 4 ++-- .../Methods/ItemMethods/ForceEquipMethod.cs | 4 +++- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Code/MethodSystem/Methods/EffectMethods/ClearEffectMethod.cs b/Code/MethodSystem/Methods/EffectMethods/ClearEffectMethod.cs index f274fe9..81512a5 100644 --- a/Code/MethodSystem/Methods/EffectMethods/ClearEffectMethod.cs +++ b/Code/MethodSystem/Methods/EffectMethods/ClearEffectMethod.cs @@ -11,7 +11,7 @@ namespace SER.Code.MethodSystem.Methods.EffectMethods; [UsedImplicitly] -public class ClearEffectMethod : SynchronousMethod, IDependOnFramework, IAdditionalDescription +public class ClearEffectMethod : SynchronousMethod, IDependOnFramework { public override string Description => "Removes the provided status effect from players."; @@ -19,20 +19,19 @@ public class ClearEffectMethod : SynchronousMethod, IDependOnFramework, IAdditio [ new PlayersArgument("players"), new EnumArgument("effect type") - { DefaultValue = new (EffectType.None, "Removes all status effects") }, + { DefaultValue = new (null, "Removes all status effects") }, ]; public override void Execute() { var players = Args.GetPlayers("players"); - var effectType = Args.GetEnum("effect type"); + var effectType = Args.GetNullableEnum("effect type"); - if (effectType == EffectType.None) - players.ForEach(plr => Player.Get(plr).DisableAllEffects()); + if (effectType.HasValue) + players.ForEach(plr => Player.Get(plr).DisableEffect(effectType.Value)); else - players.ForEach(plr => Player.Get(plr).DisableEffect(effectType)); + players.ForEach(plr => Player.Get(plr).DisableAllEffects()); } public FrameworkBridge.Type DependsOn => FrameworkBridge.Type.Exiled; - public string AdditionalDescription => $"Using the effect type {EffectType.None} will remove all status effects."; } \ No newline at end of file diff --git a/Code/MethodSystem/Methods/ElevatorMethods/ElevatorInfoMethod.cs b/Code/MethodSystem/Methods/ElevatorMethods/ElevatorInfoMethod.cs index ad0110f..2056786 100644 --- a/Code/MethodSystem/Methods/ElevatorMethods/ElevatorInfoMethod.cs +++ b/Code/MethodSystem/Methods/ElevatorMethods/ElevatorInfoMethod.cs @@ -10,7 +10,7 @@ namespace SER.Code.MethodSystem.Methods.ElevatorMethods; [UsedImplicitly] -public class ElevatorInfoMethod : ReturningMethod, IReferenceResolvingMethod +public class ElevatorInfoMethod : LiteralValueReturningMethod, IReferenceResolvingMethod { public override string Description => IReferenceResolvingMethod.Desc.Get(this); public override Argument[] ExpectedArguments => @@ -45,7 +45,7 @@ public override void Execute() }; } - public override TypeOfValue Returns => new TypesOfValue([ + public override TypeOfValue LiteralReturnTypes => new TypesOfValue([ typeof(TextValue), typeof(BoolValue) ]); diff --git a/Code/MethodSystem/Methods/ItemMethods/ForceEquipMethod.cs b/Code/MethodSystem/Methods/ItemMethods/ForceEquipMethod.cs index bc95f6b..bbf537f 100644 --- a/Code/MethodSystem/Methods/ItemMethods/ForceEquipMethod.cs +++ b/Code/MethodSystem/Methods/ItemMethods/ForceEquipMethod.cs @@ -25,7 +25,9 @@ public override void Execute() players.ForEach(plr => { - var item = itemType != ItemType.None ? Item.Get(plr.Inventory.UserInventory.Items.FirstOrDefault(x => x.Value.ItemTypeId == itemType).Value) : null; + var item = itemType != ItemType.None + ? Item.Get(plr.Inventory.UserInventory.Items.FirstOrDefault(x => x.Value.ItemTypeId == itemType).Value) + : null; plr.CurrentItem = item; }); } From 09019724493a73278213ba3fcf54443870155d74 Mon Sep 17 00:00:00 2001 From: RetroReul Date: Sat, 14 Mar 2026 02:18:07 +0200 Subject: [PATCH 06/11] fixed really big oopsies --- ...gdolllMethod.cs => CreateRagdollMethod.cs} | 50 +++++++++++++++---- 1 file changed, 40 insertions(+), 10 deletions(-) rename Code/MethodSystem/Methods/MapMethods/{CreateRagdolllMethod.cs => CreateRagdollMethod.cs} (54%) diff --git a/Code/MethodSystem/Methods/MapMethods/CreateRagdolllMethod.cs b/Code/MethodSystem/Methods/MapMethods/CreateRagdollMethod.cs similarity index 54% rename from Code/MethodSystem/Methods/MapMethods/CreateRagdolllMethod.cs rename to Code/MethodSystem/Methods/MapMethods/CreateRagdollMethod.cs index 3bf9739..b2171dc 100644 --- a/Code/MethodSystem/Methods/MapMethods/CreateRagdolllMethod.cs +++ b/Code/MethodSystem/Methods/MapMethods/CreateRagdollMethod.cs @@ -1,6 +1,7 @@ using JetBrains.Annotations; using LabApi.Features.Wrappers; using PlayerRoles; +using PlayerRoles.Ragdolls; using PlayerStatsSystem; using SER.Code.ArgumentSystem.Arguments; using SER.Code.ArgumentSystem.BaseArguments; @@ -21,14 +22,26 @@ public class SpawnRagdollMethod : SynchronousMethod, ICanError [ new EnumArgument("role"), new TextArgument("name"), - new ReferenceArgument("position"), - new ReferenceArgument("scale") - { DefaultValue = new(null, "default size") }, - new ReferenceArgument("rotation") - { DefaultValue = new(Quaternion.identity, "default rotation") }, + new FloatArgument("x position"), + new FloatArgument("y position"), + new FloatArgument("z position"), + new FloatArgument("x size") + { DefaultValue = new(null, "default role x scale") }, + new FloatArgument("y size") + { DefaultValue = new(null, "default role y scale") }, + new FloatArgument("z size") + { DefaultValue = new(null, "default role z scale") }, + new FloatArgument("x rotation") + { DefaultValue = new(0f, null) }, + new FloatArgument("y rotation") + { DefaultValue = new(0f, null) }, + new FloatArgument("z rotation") + { DefaultValue = new(0f, null) }, + new FloatArgument("w rotation") + { DefaultValue = new(1f, null) }, new AnyValueArgument("damage handler") { - DefaultValue = new(new CustomReasonDamageHandler(""), "damage reason will be blank"), + DefaultValue = new(new CustomReasonDamageHandler(""), "Damage reason will be blank"), Description = $"Accepts a {nameof(TextValue)} or a {nameof(DamageHandlerBase)} reference." }, ]; @@ -37,11 +50,28 @@ public override void Execute() { var role = Args.GetEnum("role"); var name = Args.GetText("name"); - var position = Args.GetReference("position"); - var scale = Args.GetReference("scale"); - var rotation = Args.GetReference("rotation"); + + var xPosition = Args.GetFloat("x position"); + var yPosition = Args.GetFloat("y position"); + var zPosition = Args.GetFloat("z position"); + + var defaultSize = RagdollManager.GetDefaultScale(role); + + var xSize = Args.GetNullableFloat("x size") ?? defaultSize.x; + var ySize = Args.GetNullableFloat("y size") ?? defaultSize.y; + var zSize = Args.GetNullableFloat("z size") ?? defaultSize.z; + + var xRotation = Args.GetFloat("x rotation"); + var yRotation = Args.GetFloat("y rotation"); + var zRotation = Args.GetFloat("z rotation"); + var wRotation = Args.GetFloat("w rotation"); + var value = Args.GetAnyValue("damage handler"); + var position = new Vector3(xPosition, yPosition, zPosition); + var rotation = new Quaternion(xRotation, yRotation, zRotation, wRotation); + var size = new Vector3(xSize, ySize, zSize); + DamageHandlerBase? damageHandler = null; switch (value) @@ -62,7 +92,7 @@ public override void Execute() if (damageHandler is null) throw new ScriptRuntimeError(this, ErrorReasons[0]); - Ragdoll.SpawnRagdoll(role, position, rotation, damageHandler, name, scale); + Ragdoll.SpawnRagdoll(role, position, rotation, damageHandler, name, size); } public string[] ErrorReasons => From 94791896252574d90bbfb7c371b98c880d070405 Mon Sep 17 00:00:00 2001 From: RetroReul Date: Sat, 14 Mar 2026 02:20:32 +0200 Subject: [PATCH 07/11] minor change to CreateRagdollMethod.cs --- .../MethodSystem/Methods/MapMethods/CreateRagdollMethod.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Code/MethodSystem/Methods/MapMethods/CreateRagdollMethod.cs b/Code/MethodSystem/Methods/MapMethods/CreateRagdollMethod.cs index b2171dc..ba9798a 100644 --- a/Code/MethodSystem/Methods/MapMethods/CreateRagdollMethod.cs +++ b/Code/MethodSystem/Methods/MapMethods/CreateRagdollMethod.cs @@ -72,7 +72,7 @@ public override void Execute() var rotation = new Quaternion(xRotation, yRotation, zRotation, wRotation); var size = new Vector3(xSize, ySize, zSize); - DamageHandlerBase? damageHandler = null; + DamageHandlerBase? damageHandler; switch (value) { @@ -87,11 +87,10 @@ public override void Execute() case TextValue textValue: damageHandler = new CustomReasonDamageHandler(textValue.StringRep); break; + default: + throw new ScriptRuntimeError(this, ErrorReasons[0]); } - if (damageHandler is null) - throw new ScriptRuntimeError(this, ErrorReasons[0]); - Ragdoll.SpawnRagdoll(role, position, rotation, damageHandler, name, size); } From 316740273cfd2c4b0ed5b3595400d806c00fd0a5 Mon Sep 17 00:00:00 2001 From: RetroReul Date: Sat, 14 Mar 2026 03:26:05 +0200 Subject: [PATCH 08/11] extra info options for DoorInfoMethod.cs and ServerInfoMethod.cs --- Code/MethodSystem/Methods/DoorMethods/DoorInfoMethod.cs | 4 ++++ Code/MethodSystem/Methods/ServerMethods/ServerInfoMethod.cs | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/Code/MethodSystem/Methods/DoorMethods/DoorInfoMethod.cs b/Code/MethodSystem/Methods/DoorMethods/DoorInfoMethod.cs index 519bfb2..a313be3 100644 --- a/Code/MethodSystem/Methods/DoorMethods/DoorInfoMethod.cs +++ b/Code/MethodSystem/Methods/DoorMethods/DoorInfoMethod.cs @@ -33,6 +33,8 @@ public class DoorInfoMethod : LiteralValueReturningMethod, IReferenceResolvingMe "isClosed", "isLocked", "isUnlocked", + "isGate", + "isCheckpoint", Option.Enum("name"), "unityName", "remainingHealth", @@ -54,6 +56,8 @@ public override void Execute() "isclosed" => new BoolValue(!door.IsOpened), "islocked" => new BoolValue(door.IsLocked), "isunlocked" => new BoolValue(!door.IsLocked), + "isgate" => new BoolValue(door is Gate), + "ischeckpoint" => new BoolValue(door is CheckpointDoor), "remaininghealth" => new NumberValue(door is BreakableDoor bDoor ? (decimal)bDoor.Health : -1), "maxhealth" => new NumberValue(door is BreakableDoor bDoor ? (decimal)bDoor.MaxHealth : -1), "permissions" => new StaticTextValue(door.Permissions.ToString()), diff --git a/Code/MethodSystem/Methods/ServerMethods/ServerInfoMethod.cs b/Code/MethodSystem/Methods/ServerMethods/ServerInfoMethod.cs index 9c396d0..9e7dda6 100644 --- a/Code/MethodSystem/Methods/ServerMethods/ServerInfoMethod.cs +++ b/Code/MethodSystem/Methods/ServerMethods/ServerInfoMethod.cs @@ -19,8 +19,10 @@ public class ServerInfoMethod : ReturningMethod "ip", "port", "name", + "playerCount", "maxPlayers", "tps", + "maxTps", "isVerified") ]; @@ -37,8 +39,10 @@ public override void Execute() "ip" => new StaticTextValue(Server.IpAddress), "port" => new NumberValue(Server.Port), "name" => new StaticTextValue(Server.ServerListName), + "playercount" => new NumberValue(Server.PlayerCount), "maxplayers" => new NumberValue(Server.MaxPlayers), "tps" => new NumberValue((decimal)Server.Tps), + "maxtps" => new NumberValue(Server.MaxTps), "isverified" => new BoolValue(CustomNetworkManager.IsVerified), _ => throw new TosoksFuckedUpException("out of order") }; From 3b10022c1e3b96502985ca887f419c614df97747 Mon Sep 17 00:00:00 2001 From: RetroReul Date: Sat, 14 Mar 2026 04:13:07 +0200 Subject: [PATCH 09/11] forgot to rename from SpawnRagdoll to CreateRagdoll --- Code/MethodSystem/Methods/MapMethods/CreateRagdollMethod.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/MethodSystem/Methods/MapMethods/CreateRagdollMethod.cs b/Code/MethodSystem/Methods/MapMethods/CreateRagdollMethod.cs index ba9798a..bbc88fb 100644 --- a/Code/MethodSystem/Methods/MapMethods/CreateRagdollMethod.cs +++ b/Code/MethodSystem/Methods/MapMethods/CreateRagdollMethod.cs @@ -14,7 +14,7 @@ namespace SER.Code.MethodSystem.Methods.MapMethods; [UsedImplicitly] -public class SpawnRagdollMethod : SynchronousMethod, ICanError +public class CreateRagdollMethod : SynchronousMethod, ICanError { public override string Description => "Spawns a ragdoll."; From e5da27423d72e9df35e9a17581ba91e1592321e0 Mon Sep 17 00:00:00 2001 From: RetroReul Date: Mon, 16 Mar 2026 19:06:46 +0200 Subject: [PATCH 10/11] SetSpectatabilityMethod.cs made it into base SER :D --- .../PlayerMethods/SetSpectatabilityMethod.cs | 30 ------------------- 1 file changed, 30 deletions(-) delete mode 100644 Code/MethodSystem/Methods/PlayerMethods/SetSpectatabilityMethod.cs diff --git a/Code/MethodSystem/Methods/PlayerMethods/SetSpectatabilityMethod.cs b/Code/MethodSystem/Methods/PlayerMethods/SetSpectatabilityMethod.cs deleted file mode 100644 index 3ca512b..0000000 --- a/Code/MethodSystem/Methods/PlayerMethods/SetSpectatabilityMethod.cs +++ /dev/null @@ -1,30 +0,0 @@ -using JetBrains.Annotations; -using PlayerRoles.Spectating; -using SER.Code.ArgumentSystem.Arguments; -using SER.Code.ArgumentSystem.BaseArguments; -using SER.Code.MethodSystem.BaseMethods.Synchronous; - -namespace SER.Code.MethodSystem.Methods.PlayerMethods; - -[UsedImplicitly] -public class SetSpectatabilityMethod : SynchronousMethod -{ - public override string Description => "Sets spectatability for players."; - - public override Argument[] ExpectedArguments { get; } = - [ - new PlayersArgument("players"), - new BoolArgument("is spectatable") - ]; - - public override void Execute() - { - var players = Args.GetPlayers("players"); - var isSpectatable = Args.GetBool("is spectatable"); - - players.ForEach(player => - { - SpectatableVisibilityManager.SetHidden(player.ReferenceHub, isSpectatable); - }); - } -} \ No newline at end of file From a34409d5009f2b8dafde8393ae93c3c7b28f3d9b Mon Sep 17 00:00:00 2001 From: RetroReul Date: Mon, 16 Mar 2026 19:12:40 +0200 Subject: [PATCH 11/11] changes to effect methods to keep up with recent commits --- .../Methods/EffectMethods/ClearEffectMethod.cs | 6 ++++-- .../Methods/EffectMethods/GiveEffectMethod.cs | 12 +++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Code/MethodSystem/Methods/EffectMethods/ClearEffectMethod.cs b/Code/MethodSystem/Methods/EffectMethods/ClearEffectMethod.cs index 81512a5..f738cf1 100644 --- a/Code/MethodSystem/Methods/EffectMethods/ClearEffectMethod.cs +++ b/Code/MethodSystem/Methods/EffectMethods/ClearEffectMethod.cs @@ -28,9 +28,11 @@ public override void Execute() var effectType = Args.GetNullableEnum("effect type"); if (effectType.HasValue) - players.ForEach(plr => Player.Get(plr).DisableEffect(effectType.Value)); + foreach (var plr in players) + Player.Get(plr).DisableEffect(effectType.Value); else - players.ForEach(plr => Player.Get(plr).DisableAllEffects()); + foreach (var plr in players) + Player.Get(plr).DisableAllEffects(); } public FrameworkBridge.Type DependsOn => FrameworkBridge.Type.Exiled; diff --git a/Code/MethodSystem/Methods/EffectMethods/GiveEffectMethod.cs b/Code/MethodSystem/Methods/EffectMethods/GiveEffectMethod.cs index 8f28237..3381a76 100644 --- a/Code/MethodSystem/Methods/EffectMethods/GiveEffectMethod.cs +++ b/Code/MethodSystem/Methods/EffectMethods/GiveEffectMethod.cs @@ -13,7 +13,7 @@ namespace SER.Code.MethodSystem.Methods.EffectMethods; public class GiveEffectMethod : SynchronousMethod, IDependOnFramework { public FrameworkBridge.Type DependsOn => FrameworkBridge.Type.Exiled; - + public override string Description => "Adds a provided effect to a player."; public override Argument[] ExpectedArguments => @@ -40,9 +40,11 @@ public override void Execute() var effectType = Args.GetEnum("effect type"); var duration = (float)Args.GetDuration("duration").TotalSeconds; var intensity = (byte)Args.GetInt("intensity"); - - players.ForEach(plr - => Player.Get(plr).EnableEffect(effectType, intensity, duration) - ); + var addDurationIfActive = Args.GetBool("add duration if active"); + + foreach (var plr in players) + { + Player.Get(plr).EnableEffect(effectType, intensity, duration, addDurationIfActive); + } } } \ No newline at end of file