diff --git a/Code/ArgumentSystem/Arguments/GateArgument.cs b/Code/ArgumentSystem/Arguments/GateArgument.cs new file mode 100644 index 00000000..48810d93 --- /dev/null +++ b/Code/ArgumentSystem/Arguments/GateArgument.cs @@ -0,0 +1,61 @@ +using JetBrains.Annotations; +using LabApi.Features.Enums; +using LabApi.Features.Wrappers; +using SER.Code.ArgumentSystem.BaseArguments; +using SER.Code.Extensions; +using SER.Code.Helpers.ResultSystem; +using SER.Code.TokenSystem.Tokens; +using SER.Code.TokenSystem.Tokens.Interfaces; +using SER.Code.ValueSystem; + +namespace SER.Code.ArgumentSystem.Arguments; + +public class GateArgument(string name) : EnumHandlingArgument(name) +{ + public override string InputDescription => $"{nameof(DoorName)} enum (that is a gate) or reference to {nameof(Gate)}"; + + [UsedImplicitly] + public DynamicTryGet GetConvertSolution(BaseToken token) + { + return ResolveEnums( + token, + new() + { + [typeof(DoorName)] = doorName => + { + var door = Gate.List.Where(gate => gate.DoorName == (DoorName)doorName).GetRandomValue(); + if (door is null) + { + return $"Gate with name '{doorName}' does not exist."; + } + + return door; + } + }, + () => + { + Result rs = $"Value '{token.RawRep}' cannot be interpreted as {InputDescription}."; + + if (token is not IValueToken val || !val.CapableOf(out var func)) + { + return rs; + } + + return new(() => + { + if (func().HasErrored(out var error, out var refVal)) + { + return error; + } + + if (ReferenceArgument.TryParse(refVal).WasSuccessful(out var gate)) + { + return gate; + } + + return rs; + }); + } + ); + } +} \ No newline at end of file diff --git a/Code/ArgumentSystem/ProvidedArguments.cs b/Code/ArgumentSystem/ProvidedArguments.cs index 562eca54..524d02ee 100644 --- a/Code/ArgumentSystem/ProvidedArguments.cs +++ b/Code/ArgumentSystem/ProvidedArguments.cs @@ -160,6 +160,11 @@ public Door GetDoor(string argName) return GetValue(argName); } + public Gate GetGate(string argName) + { + return GetValue(argName); + } + public TimeSpan? GetNullableDuration(string argName) { return GetValueNullableStruct(argName); diff --git a/Code/ContextSystem/Contexts/Control/ReturnKeyword.cs b/Code/ContextSystem/Contexts/Control/ReturnKeyword.cs index eb2b1c97..9a8a25e4 100644 --- a/Code/ContextSystem/Contexts/Control/ReturnKeyword.cs +++ b/Code/ContextSystem/Contexts/Control/ReturnKeyword.cs @@ -4,10 +4,7 @@ using SER.Code.ContextSystem.Structures; using SER.Code.Exceptions; using SER.Code.Helpers.ResultSystem; -using SER.Code.TokenSystem.Structures; using SER.Code.TokenSystem.Tokens; -using SER.Code.TokenSystem.Tokens.Interfaces; -using SER.Code.ValueSystem; namespace SER.Code.ContextSystem.Contexts.Control; diff --git a/Code/Exceptions/RetroReulFuckedUpException.cs b/Code/Exceptions/RetroReulFuckedUpException.cs new file mode 100644 index 00000000..14b9ad8f --- /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/AudioMethods/SpeakerExistsMethod.cs b/Code/MethodSystem/Methods/AudioMethods/SpeakerExistsMethod.cs new file mode 100644 index 00000000..c877e3f1 --- /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 00000000..e6061bfb --- /dev/null +++ b/Code/MethodSystem/Methods/DoorMethods/PryGateMethod.cs @@ -0,0 +1,42 @@ +using JetBrains.Annotations; +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 GateArgument("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 gate = Args.GetGate("gate"); + var playEffects = Args.GetBool("should play effects"); + + 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/EffectMethods/ClearEffectMethod.cs b/Code/MethodSystem/Methods/EffectMethods/ClearEffectMethod.cs new file mode 100644 index 00000000..4b67f139 --- /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.Structures; + +namespace SER.Code.MethodSystem.Methods.EffectMethods; + +[UsedImplicitly] +public class ClearEffectMethod : SynchronousMethod, IDependOnFramework +{ + public override string Description => "Removes the provided status effect from players."; + + public override Argument[] ExpectedArguments => + [ + new PlayersArgument("players"), + new EnumArgument("effect type") + { DefaultValue = new (null, "Removes all status effects") }, + ]; + + public override void Execute() + { + var players = Args.GetPlayers("players"); + var effectType = Args.GetNullableEnum("effect type"); + + if (effectType.HasValue) + foreach (var plr in players) + Player.Get(plr).DisableEffect(effectType.Value); + else + foreach (var plr in players) + Player.Get(plr).DisableAllEffects(); + } + + public FrameworkBridge.Type DependsOn => FrameworkBridge.Type.Exiled; +} \ 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 da15446a..3381a761 100644 --- a/Code/MethodSystem/Methods/PlayerMethods/GiveEffectMethod.cs +++ b/Code/MethodSystem/Methods/EffectMethods/GiveEffectMethod.cs @@ -7,13 +7,13 @@ 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 { public FrameworkBridge.Type DependsOn => FrameworkBridge.Type.Exiled; - + public override string Description => "Adds a provided effect to a player."; public override Argument[] ExpectedArguments => diff --git a/Code/MethodSystem/Methods/EffectMethods/HasEffectMethod.cs b/Code/MethodSystem/Methods/EffectMethods/HasEffectMethod.cs new file mode 100644 index 00000000..fcbd2844 --- /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 diff --git a/Code/MethodSystem/Methods/ElevatorMethods/SetElevatorTextMethod.cs b/Code/MethodSystem/Methods/ElevatorMethods/SetElevatorTextMethod.cs new file mode 100644 index 00000000..33793e84 --- /dev/null +++ b/Code/MethodSystem/Methods/ElevatorMethods/SetElevatorTextMethod.cs @@ -0,0 +1,29 @@ +using JetBrains.Annotations; +using LabApi.Features.Wrappers; +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, IAdditionalDescription +{ + public override string Description => "Changes the text on the elevator panels between LCZ and HCZ."; + + public override Argument[] ExpectedArguments => + [ + new TextArgument("text") + { + DefaultValue = new(string.Empty, "Resets the text to it's original value."), + } + ]; + + 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/HealthMethods/RegenerateMethod.cs b/Code/MethodSystem/Methods/HealthMethods/RegenerateMethod.cs new file mode 100644 index 00000000..8979ae29 --- /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 00000000..bbf537f4 --- /dev/null +++ b/Code/MethodSystem/Methods/ItemMethods/ForceEquipMethod.cs @@ -0,0 +1,34 @@ +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/CreateRagdollMethod.cs b/Code/MethodSystem/Methods/MapMethods/CreateRagdollMethod.cs new file mode 100644 index 00000000..4232d6f5 --- /dev/null +++ b/Code/MethodSystem/Methods/MapMethods/CreateRagdollMethod.cs @@ -0,0 +1,102 @@ +using JetBrains.Annotations; +using LabApi.Features.Wrappers; +using PlayerRoles; +using PlayerRoles.Ragdolls; +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 CreateRagdollMethod : SynchronousMethod, ICanError +{ + public override string Description => "Spawns a ragdoll."; + + public override Argument[] ExpectedArguments => + [ + new EnumArgument("role"), + new TextArgument("name"), + 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 ReferenceValue(new(" ")), "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 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; + + 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; + default: + throw new ScriptRuntimeError(this, ErrorReasons[0]); + } + + Ragdoll.SpawnRagdoll(role, position, rotation, damageHandler, name, size); + } + + 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 00000000..d348632d --- /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/ShowHitMarkerMethod.cs b/Code/MethodSystem/Methods/PlayerMethods/ShowHitMarkerMethod.cs new file mode 100644 index 00000000..4a4a2108 --- /dev/null +++ b/Code/MethodSystem/Methods/PlayerMethods/ShowHitMarkerMethod.cs @@ -0,0 +1,34 @@ +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") }, + new BoolArgument("should play audio") + { DefaultValue = new(true, "Hitmarker will make a noise.")}, + new EnumArgument("hitmarker type") + { DefaultValue = new(HitmarkerType.Regular, "Regular Hitmarker")} + ]; + + public override void Execute() + { + var players = Args.GetPlayers("players"); + var size = Args.GetFloat("hitmarker size"); + var playAudio = Args.GetBool("should play audio"); + var hitmarkerType = Args.GetEnum("hitmarker type"); + + players.ForEach(plr => Hitmarker.SendHitmarkerDirectly(plr.ReferenceHub, size, playAudio, hitmarkerType)); + } +} \ 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 00000000..9e97f965 --- /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 the stamina of players."; + + 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 > 1f) newStamina = 1f; + break; + case "remove": + newStamina = plr.StaminaRemaining - staminaValue; + if (newStamina < 0f) newStamina = 0f; + 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 00000000..8d40ebbf --- /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/ServerMethods/ServerInfoMethod.cs b/Code/MethodSystem/Methods/ServerMethods/ServerInfoMethod.cs index 9c396d02..9e7dda62 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") }; diff --git a/Code/MethodSystem/Methods/TextMethods/ContainsTextMethod.cs b/Code/MethodSystem/Methods/TextMethods/ContainsTextMethod.cs new file mode 100644 index 00000000..04334167 --- /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 diff --git a/Code/ValueSystem/PropertySystem/ReferencePropertyRegistry.cs b/Code/ValueSystem/PropertySystem/ReferencePropertyRegistry.cs index bfbc7c00..17fb85a4 100644 --- a/Code/ValueSystem/PropertySystem/ReferencePropertyRegistry.cs +++ b/Code/ValueSystem/PropertySystem/ReferencePropertyRegistry.cs @@ -156,6 +156,10 @@ public static void Initialize() Register("remainingHealth", d => new NumberValue(d is BreakableDoor bDoor ? (decimal)bDoor.Health : -1), "The remaining health of the door"); Register("maxHealth", d => new NumberValue(d is BreakableDoor bDoor ? (decimal)bDoor.MaxHealth : -1), "The maximum health of the door"); + Register("isGate", d => d is Gate, "Is door a gate?"); + Register("isBreakable", d => d is BreakableDoor, "Is door breakable?"); + Register("isCheckpoint", d => d is CheckpointDoor, "Is door breakable?"); + Register("positionX", p => new NumberValue((decimal)p.Position.x), "The X position of the pickup"); Register("positionY", p => new NumberValue((decimal)p.Position.y), "The Y position of the pickup");