mirror of
https://github.com/All-Of-Us-Mods/MiraAPI.git
synced 2026-10-20 01:46:15 +00:00
Compare commits
19
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a3c8feeab | ||
|
|
833585f15f | ||
|
|
66b4976619 | ||
|
|
9c0b874e34 | ||
|
|
ce0662f772 | ||
|
|
c928eae183 | ||
|
|
68afe58678 | ||
|
|
e3b2477cb8 | ||
|
|
2b568f933b | ||
|
|
a0701d582f | ||
|
|
c42782b157 | ||
|
|
f932c4f3ff | ||
|
|
2666aa171d | ||
|
|
9f99f6abb5 | ||
|
|
aa53af112b | ||
|
|
ff2f44fd64 | ||
|
|
d64972a574 | ||
|
|
bb45bab198 | ||
|
|
1eb13d0513 |
No files matched your search
+1
-105
@@ -1,106 +1,2 @@
|
||||
[*.{cs,vb}]
|
||||
|
||||
# IDE0008: Use explicit type
|
||||
dotnet_diagnostic.IDE0008.severity = none
|
||||
|
||||
# IDE0160: Convert to block scoped namespace
|
||||
dotnet_diagnostic.IDE0160.severity = none
|
||||
|
||||
# IDE0011: Add braces
|
||||
dotnet_diagnostic.IDE0011.severity = none
|
||||
|
||||
# CS8618: Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
|
||||
dotnet_diagnostic.CS8618.severity = none
|
||||
|
||||
# CA1805: Do not initialize unnecessarily
|
||||
dotnet_diagnostic.CA1805.severity = none
|
||||
|
||||
# S3358: Ternary operators should not be nested
|
||||
dotnet_diagnostic.S3358.severity = none
|
||||
|
||||
# IDE1006: Naming Styles
|
||||
dotnet_diagnostic.IDE1006.severity = none
|
||||
|
||||
# S3267: Use LINQ methods to simply foreach loops
|
||||
dotnet_diagnostic.S3267.severity = none
|
||||
|
||||
# S125: Sections of code should not be commented out
|
||||
dotnet_diagnostic.S125.severity = none
|
||||
|
||||
# SA1512: Single-line comments should not be followed by blank line
|
||||
dotnet_diagnostic.SA1512.severity = none
|
||||
|
||||
# S2696: Instance members should not write to "static" fields
|
||||
dotnet_diagnostic.S2696.severity = none
|
||||
|
||||
# S2245: Pseudorandom number generators (PRNGs) should not be used in security contexts
|
||||
dotnet_diagnostic.S2245.severity = none
|
||||
|
||||
# IDE0130: Namespace does not match folder structure
|
||||
dotnet_diagnostic.IDE0130.severity = none
|
||||
|
||||
# SA1633: File should have header
|
||||
dotnet_diagnostic.SA1633.severity = none
|
||||
|
||||
# SA1101: Prefix local calls with this
|
||||
dotnet_diagnostic.SA1101.severity = none
|
||||
|
||||
# SA1600: Elements should be documented
|
||||
dotnet_diagnostic.SA1600.severity = none
|
||||
|
||||
# SA1516: Elements should be separated by blank line
|
||||
dotnet_diagnostic.SA1516.severity = none
|
||||
|
||||
# SA1503: Braces should not be omitted
|
||||
dotnet_diagnostic.SA1503.severity = none
|
||||
|
||||
# SA1201: Elements should appear in the correct order
|
||||
dotnet_diagnostic.SA1201.severity = none
|
||||
|
||||
# SA1402: File may only contain a single type
|
||||
dotnet_diagnostic.SA1402.severity = none
|
||||
|
||||
# SA1204: Static elements should appear before instance elements
|
||||
dotnet_diagnostic.SA1204.severity = none
|
||||
|
||||
# SA1202: Elements should be ordered by access
|
||||
dotnet_diagnostic.SA1202.severity = none
|
||||
|
||||
# SA1649: File name should match first type name
|
||||
dotnet_diagnostic.SA1649.severity = none
|
||||
|
||||
# SA1313: Parameter names should begin with lower-case letter
|
||||
dotnet_diagnostic.SA1313.severity = none
|
||||
|
||||
# SA1636: The file header copyright text should match the copyright text from the settings
|
||||
dotnet_diagnostic.SA1636.severity = none
|
||||
|
||||
# SA1309: Field names should not begin with underscore
|
||||
dotnet_diagnostic.SA1309.severity = none
|
||||
|
||||
# SA1407: Arithmetic expressions should declare precedence
|
||||
dotnet_diagnostic.SA1407.severity = none
|
||||
|
||||
# SA1133: Each attribute should be placed in its own set of square brackets
|
||||
dotnet_diagnostic.SA1133.severity = none
|
||||
|
||||
# IDE0001: Simplify Names
|
||||
dotnet_diagnostic.IDE0001.severity = warning
|
||||
|
||||
# IDE0079: Remove unnecessary suppression
|
||||
dotnet_diagnostic.IDE0079.severity = none
|
||||
|
||||
# S3903: Types should be defined in named namespaces
|
||||
dotnet_diagnostic.S3903.severity = none
|
||||
|
||||
# IDE0045: Convert to conditional expression
|
||||
dotnet_diagnostic.IDE0045.severity = none
|
||||
|
||||
# IDE0046: Convert to conditional expression
|
||||
dotnet_diagnostic.IDE0046.severity = none
|
||||
|
||||
# S1244: Floating point numbers should not be tested for equality
|
||||
dotnet_diagnostic.S1244.severity = none
|
||||
|
||||
# S2325: Methods and properties that don't access instance data should be static
|
||||
dotnet_diagnostic.S2325.severity = none
|
||||
dotnet_diagnostic.CA1707.severity = none
|
||||
@@ -6,11 +6,11 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- uses: actions/cache@v4
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.nuget/packages
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
${{ runner.os }}-nuget-
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 8.0.x
|
||||
|
||||
@@ -29,17 +29,17 @@ jobs:
|
||||
with:
|
||||
verbosity: Diagnostic
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: MiraAPI.dll
|
||||
path: MiraAPI/bin/Release/net6.0/MiraAPI.dll
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: AllOfUs.MiraAPI.nupkg
|
||||
path: MiraAPI/bin/Release/AllOfUs.MiraAPI.*.nupkg
|
||||
|
||||
- uses: softprops/action-gh-release@v2
|
||||
- uses: softprops/action-gh-release@v1
|
||||
if: github.ref_type == 'tag'
|
||||
with:
|
||||
draft: true
|
||||
|
||||
+2
-3
@@ -1,9 +1,8 @@
|
||||
.git/
|
||||
.idea/
|
||||
.vs*/
|
||||
.vs/
|
||||
obj/
|
||||
bin/
|
||||
.qodo/
|
||||
|
||||
*.user
|
||||
*.lock.json
|
||||
*.lock.json
|
||||
+6
-6
@@ -1,14 +1,14 @@
|
||||
<Project>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Reactor" Version="2.5.0-ci.371" />
|
||||
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.735" Private="false" ExcludeAssets="runtime;native" />
|
||||
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2026.9.29" PrivateAssets="all" />
|
||||
<PackageReference Include="Reactor" Version="2.3.1" />
|
||||
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.697" Private="false" ExcludeAssets="runtime;native" />
|
||||
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2024.9.4" PrivateAssets="all" />
|
||||
|
||||
<PackageReference Include="BepInEx.AutoPlugin" Version="1.1.0" PrivateAssets="all" />
|
||||
<PackageReference Include="BepInEx.IL2CPP.MSBuild" Version="2.1.0-rc.1" PrivateAssets="all" ExcludeAssets="runtime" />
|
||||
<PackageReference Include="BepInEx.IL2CPP.MSBuild" Version="2.0.1" PrivateAssets="all" ExcludeAssets="runtime" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<Target Name="Copy" AfterTargets="Build" Condition="'$(AmongUs)' != ''">
|
||||
<Copy SourceFiles="$(TargetPath)" DestinationFolder="$(AmongUs)/BepInEx/plugins/" UseSymboliclinksIfPossible="true" />
|
||||
</Target>
|
||||
</Project>
|
||||
</Project>
|
||||
+11
-8
@@ -8,7 +8,7 @@
|
||||
|
||||
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
|
||||
|
||||
<VersionPrefix>0.5.0</VersionPrefix>
|
||||
<VersionPrefix>0.1.9</VersionPrefix>
|
||||
<VersionSuffix>dev</VersionSuffix>
|
||||
|
||||
<Authors>All Of Us, XtraCube, Angxl</Authors>
|
||||
@@ -28,15 +28,18 @@
|
||||
<AnalysisLevel>latest</AnalysisLevel>
|
||||
<AnalysisMode>recommended</AnalysisMode>
|
||||
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
|
||||
<NoWarn>$(NoWarn);SA0001</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Roslynator.Analyzers" Version="5.0.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Roslynator.Formatting.Analyzers" Version="5.0.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Roslynator.CodeAnalysis.Analyzers" Version="5.0.0" PrivateAssets="all" />
|
||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.32.0.713" PrivateAssets="all" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556" PrivateAssets="all" />
|
||||
<AdditionalFiles Include="$(MSBuildThisFileDirectory)/stylecop.json" Link="stylecop.json" Visible="false" />
|
||||
<AdditionalFiles Include="$(MSBuildThisFileDirectory)\stylecop.json" Link="stylecop.json" Visible="false" />
|
||||
|
||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.32.0.97167">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
<PropertyGroup>
|
||||
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)\stylecop.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -1,29 +0,0 @@
|
||||
<assembly name="0Harmony">
|
||||
<member name="T:HarmonyLib.HarmonyPatch">
|
||||
<attribute ctor="M:JetBrains.Annotations.MeansImplicitUseAttribute.#ctor(JetBrains.Annotations.ImplicitUseTargetFlags)">
|
||||
<argument>3</argument>
|
||||
</attribute>
|
||||
</member>
|
||||
|
||||
<member name="T:HarmonyLib.HarmonyPrefix">
|
||||
<attribute ctor="M:JetBrains.Annotations.MeansImplicitUseAttribute.#ctor" />
|
||||
</member>
|
||||
<member name="T:HarmonyLib.HarmonyPostfix">
|
||||
<attribute ctor="M:JetBrains.Annotations.MeansImplicitUseAttribute.#ctor" />
|
||||
</member>
|
||||
<member name="T:HarmonyLib.HarmonyTranspiler">
|
||||
<attribute ctor="M:JetBrains.Annotations.MeansImplicitUseAttribute.#ctor" />
|
||||
</member>
|
||||
<member name="T:HarmonyLib.HarmonyFinalizer">
|
||||
<attribute ctor="M:JetBrains.Annotations.MeansImplicitUseAttribute.#ctor" />
|
||||
</member>
|
||||
<member name="T:HarmonyLib.HarmonyPrepare">
|
||||
<attribute ctor="M:JetBrains.Annotations.MeansImplicitUseAttribute.#ctor" />
|
||||
</member>
|
||||
<member name="T:HarmonyLib.HarmonyTargetMethod">
|
||||
<attribute ctor="M:JetBrains.Annotations.MeansImplicitUseAttribute.#ctor" />
|
||||
</member>
|
||||
<member name="T:HarmonyLib.HarmonyTargetMethods">
|
||||
<attribute ctor="M:JetBrains.Annotations.MeansImplicitUseAttribute.#ctor" />
|
||||
</member>
|
||||
</assembly>
|
||||
@@ -1,7 +0,0 @@
|
||||
[*.{cs,vb}]
|
||||
|
||||
# SA1602: Enumeration items should be documented.
|
||||
dotnet_diagnostic.SA1602.severity = none
|
||||
|
||||
# SA1601: Partial elements should be documented
|
||||
dotnet_diagnostic.SA1601.severity = none
|
||||
@@ -3,23 +3,20 @@ using MiraAPI.Example.Options.Roles;
|
||||
using MiraAPI.Example.Roles;
|
||||
using MiraAPI.GameOptions;
|
||||
using MiraAPI.Hud;
|
||||
using MiraAPI.Keybinds;
|
||||
using MiraAPI.Modifiers;
|
||||
using MiraAPI.Utilities;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.Buttons.Freezer;
|
||||
|
||||
[RegisterButton]
|
||||
public class FreezeButton : CustomActionButton<PlayerControl>
|
||||
{
|
||||
public override string Name => "button.freeze";
|
||||
|
||||
public override string Name => "Freeze";
|
||||
public override float Cooldown => OptionGroupSingleton<FreezerRoleSettings>.Instance.FreezeDuration;
|
||||
public override bool PauseTimerInVent => true;
|
||||
|
||||
public override float EffectDuration => 0f;
|
||||
public override int MaxUses => (int)OptionGroupSingleton<FreezerRoleSettings>.Instance.FreezeUses;
|
||||
public override LoadableAsset<Sprite> Sprite => ExampleAssets.ExampleButton;
|
||||
public override MiraKeybind? Keybind => MiraGlobalKeybinds.PrimaryAbility;
|
||||
|
||||
protected override void OnClick()
|
||||
{
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
using MiraAPI.Example.Modifiers;
|
||||
using MiraAPI.Hud;
|
||||
using MiraAPI.Keybinds;
|
||||
using MiraAPI.Modifiers;
|
||||
using MiraAPI.Utilities;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.Buttons;
|
||||
|
||||
[RegisterButton]
|
||||
public class MeetingButton : CustomActionButton
|
||||
{
|
||||
public override string Name => "button.callMeeting";
|
||||
public override string Name => "Call Meeting";
|
||||
|
||||
public override float Cooldown => 15;
|
||||
|
||||
public override float EffectDuration => 0;
|
||||
|
||||
public override int MaxUses => 3;
|
||||
|
||||
public override LoadableAsset<Sprite> Sprite => ExampleAssets.ExampleButton;
|
||||
public override MiraKeybind? Keybind => MiraGlobalKeybinds.ModifierPrimaryAbility;
|
||||
|
||||
public override bool Enabled(RoleBehaviour? role)
|
||||
{
|
||||
@@ -28,10 +31,10 @@ public class MeetingButton : CustomActionButton
|
||||
PlayerControl.LocalPlayer.NetTransform.Halt();
|
||||
var minigame = Object.Instantiate(bt.MinigamePrefab, Camera.main!.transform, false);
|
||||
|
||||
var taskAdderGame = minigame.TryCast<TaskAdderGame>();
|
||||
if (taskAdderGame)
|
||||
var taskAdderGame = minigame as TaskAdderGame;
|
||||
if (taskAdderGame != null)
|
||||
{
|
||||
taskAdderGame!.SafePositionWorld = bt.SafePositionLocal + (Vector2)bt.transform.position;
|
||||
taskAdderGame.SafePositionWorld = bt.SafePositionLocal + (Vector2)bt.transform.position;
|
||||
}
|
||||
|
||||
minigame.transform.localPosition = new Vector3(0f, 0f, -50f);
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
using MiraAPI.Example.GameOver;
|
||||
using MiraAPI.Example.Roles;
|
||||
using MiraAPI.GameEnd;
|
||||
using MiraAPI.Hud;
|
||||
using MiraAPI.Keybinds;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.Buttons;
|
||||
|
||||
public class NeutralKillerButton : CustomActionButton
|
||||
{
|
||||
public override string Name => "button.winGame";
|
||||
public override float Cooldown => 0f;
|
||||
public override LoadableAsset<Sprite> Sprite => ExampleAssets.ExampleButton;
|
||||
public override MiraKeybind Keybind => ExampleKeybinds.NeutralWinKeybind;
|
||||
|
||||
protected override void OnClick()
|
||||
{
|
||||
CustomGameOver.Trigger<NeutralKillerGameOver>([PlayerControl.LocalPlayer.Data]);
|
||||
}
|
||||
|
||||
public override bool Enabled(RoleBehaviour? role)
|
||||
{
|
||||
return role is NeutralKillerRole;
|
||||
}
|
||||
}
|
||||
@@ -3,32 +3,29 @@ using MiraAPI.Example.Options.Roles;
|
||||
using MiraAPI.Example.Roles;
|
||||
using MiraAPI.GameOptions;
|
||||
using MiraAPI.Hud;
|
||||
using MiraAPI.Keybinds;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using Reactor.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.Buttons.Teleporter;
|
||||
|
||||
[RegisterButton]
|
||||
public class TeleportButton : CustomActionButton
|
||||
{
|
||||
public override string Name => "button.teleport";
|
||||
public override string Name => "Teleport";
|
||||
|
||||
public override float Cooldown => OptionGroupSingleton<TeleporterOptions>.Instance.TeleportCooldown.Value;
|
||||
|
||||
public override float EffectDuration => OptionGroupSingleton<TeleporterOptions>.Instance.TeleportDuration;
|
||||
public override int MaxUses => 2;
|
||||
|
||||
public override int MaxUses => 0;
|
||||
|
||||
public override LoadableAsset<Sprite> Sprite => ExampleAssets.TeleportButton;
|
||||
public override Color TextOutlineColor => new Color32(221, 176, 152, 255);
|
||||
public static bool IsZoom { get; private set; }
|
||||
public override MiraKeybind? Keybind => MiraGlobalKeybinds.PrimaryAbility;
|
||||
|
||||
public override bool Enabled(RoleBehaviour? role)
|
||||
{
|
||||
return role is TeleporterRole;
|
||||
}
|
||||
|
||||
protected override void OnClick()
|
||||
{
|
||||
Coroutines.Start(ZoomOutCoroutine());
|
||||
@@ -43,7 +40,10 @@ public class TeleportButton : CustomActionButton
|
||||
{
|
||||
base.FixedUpdate(playerControl);
|
||||
|
||||
if (!EffectActive) return;
|
||||
if (!EffectActive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Input.GetKey(KeyCode.Mouse0))
|
||||
{
|
||||
@@ -61,14 +61,11 @@ public class TeleportButton : CustomActionButton
|
||||
{
|
||||
Camera.main.orthographicSize = MeetingHud.Instance ? 3f : ft;
|
||||
ResolutionManager.ResolutionChanged.Invoke((float)Screen.width / Screen.height, Screen.width, Screen.height, Screen.fullScreen);
|
||||
foreach (var cam in Camera.allCameras)
|
||||
cam.orthographicSize = Camera.main.orthographicSize;
|
||||
|
||||
foreach (var cam in Camera.allCameras) cam.orthographicSize = Camera.main.orthographicSize;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
foreach (var cam in Camera.allCameras)
|
||||
cam.orthographicSize = zoomDistance;
|
||||
foreach (var cam in Camera.allCameras) cam.orthographicSize = zoomDistance;
|
||||
ResolutionManager.ResolutionChanged.Invoke((float)Screen.width / Screen.height, Screen.width, Screen.height, Screen.fullScreen);
|
||||
}
|
||||
|
||||
@@ -78,14 +75,12 @@ public class TeleportButton : CustomActionButton
|
||||
{
|
||||
Camera.main.orthographicSize = MeetingHud.Instance ? 3f : ft;
|
||||
ResolutionManager.ResolutionChanged.Invoke((float)Screen.width / Screen.height, Screen.width, Screen.height, Screen.fullScreen);
|
||||
foreach (var cam in Camera.allCameras)
|
||||
cam.orthographicSize = Camera.main.orthographicSize;
|
||||
foreach (var cam in Camera.allCameras) cam.orthographicSize = Camera.main.orthographicSize;
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
foreach (var cam in Camera.allCameras)
|
||||
cam.orthographicSize = 3f;
|
||||
foreach (var cam in Camera.allCameras) cam.orthographicSize = 3f;
|
||||
HudManager.Instance.ShadowQuad.gameObject.SetActive(true);
|
||||
IsZoom = false;
|
||||
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
using MiraAPI.Hud;
|
||||
using MiraAPI.Keybinds;
|
||||
using MiraAPI.Translation;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.Buttons;
|
||||
|
||||
public class ThinkButton : CustomActionButton
|
||||
{
|
||||
public override string Name => "button.think";
|
||||
public override float Cooldown => 15f;
|
||||
public override float EffectDuration => 10f;
|
||||
public override int MaxUses => 1;
|
||||
public override ButtonUsesMode UsesMode => ButtonUsesMode.PerRound;
|
||||
public override LoadableAsset<Sprite> Sprite => ExampleAssets.ExampleButton;
|
||||
public override MiraKeybind Keybind => MiraGlobalKeybinds.SecondaryAbility;
|
||||
|
||||
protected override void OnClick()
|
||||
{
|
||||
Button!.OverrideText("button.think.thinking".Translate());
|
||||
}
|
||||
|
||||
public override void OnEffectEnd()
|
||||
{
|
||||
Button!.OverrideText("button.think".Translate());
|
||||
}
|
||||
|
||||
public override bool IsEffectCancellable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool Enabled(RoleBehaviour? role)
|
||||
{
|
||||
return role != null && role.IsImpostor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Collections.Generic;
|
||||
using MiraAPI.Cosmetics;
|
||||
|
||||
namespace MiraAPI.Example.Cosmetics;
|
||||
public class ExampleCosmeticGroup : AbstractCosmeticsGroup
|
||||
{
|
||||
public override string GroupName => "Example";
|
||||
|
||||
[RegisterCustomCosmetic()]
|
||||
public List<HatData> hats { get; set; } = new();
|
||||
[RegisterCustomCosmetic()]
|
||||
public List<NamePlateData> namePlates { get; set;} = new();
|
||||
[RegisterCustomCosmetic()]
|
||||
public List<SkinData> skins { get; set; } = new();
|
||||
[RegisterCustomCosmetic()]
|
||||
public List<VisorData> visors { get; set; } = new();
|
||||
}
|
||||
@@ -5,10 +5,8 @@ namespace MiraAPI.Example;
|
||||
public static class ExampleAssets
|
||||
{
|
||||
public static LoadableResourceAsset ExampleButton { get; } = new("MiraAPI.Example.Resources.ExampleButton.png");
|
||||
public static LoadableResourceAsset CallMeetingButton { get; } = new("MiraAPI.Example.Resources.CallMeeting.png");
|
||||
|
||||
// Credit to EpicHorrors for the teleport button asset.
|
||||
public static LoadableResourceAsset TeleportButton { get; } = new("MiraAPI.Example.Resources.TeleportButton.png");
|
||||
public static LoadableResourceAsset SharpshootButton { get; } = new("MiraAPI.Example.Resources.SharpshootButton.png");
|
||||
public static LoadableResourceAsset Banner { get; } = new("MiraAPI.Example.Resources.FortniteBanner.jpeg");
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
using MiraAPI.Colors;
|
||||
using MiraAPI.Colors.ColorSpaces;
|
||||
using MiraAPI.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example;
|
||||
@@ -8,17 +6,9 @@ namespace MiraAPI.Example;
|
||||
[RegisterCustomColors]
|
||||
public static class ExampleColors
|
||||
{
|
||||
public static CustomColor Cerulean { get; } = new("color.cerulean", new Color(0.0f, 0.48f, 0.65f))
|
||||
{
|
||||
ColorBrightness = CustomColorBrightness.Lighter,
|
||||
};
|
||||
public static CustomColor Cerulean { get; } = new("Cerulean", new Color(0.0f, 0.48f, 0.65f));
|
||||
|
||||
public static CustomColor Rose { get; } = new("color.rose", new Color(0.98f, 0.26f, 0.62f));
|
||||
public static CustomColor Rose { get; } = new("Rose", new Color(0.98f, 0.26f, 0.62f));
|
||||
|
||||
public static CustomColor Gold { get; } = new("color.gold", new Color(1.0f, 0.84f, 0.0f));
|
||||
|
||||
public static VariableColor Rainbow { get; } = new("color.rainbow", t => new HsbColor(MathUtilities.PingPong(t, 1f, 0.3f), 1f, 1f))
|
||||
{
|
||||
ColorBrightness = CustomColorBrightness.Lighter,
|
||||
};
|
||||
public static CustomColor Gold { get; } = new("Gold", new Color(1.0f, 0.84f, 0.0f));
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using MiraAPI.Events;
|
||||
using MiraAPI.Events.Mira;
|
||||
using MiraAPI.Events.Vanilla.Gameplay;
|
||||
using MiraAPI.Events.Vanilla.Map;
|
||||
using MiraAPI.Events.Vanilla.Meeting;
|
||||
using MiraAPI.Events.Vanilla.Meeting.Voting;
|
||||
using MiraAPI.Events.Vanilla.Player;
|
||||
using MiraAPI.Example.Buttons.Freezer;
|
||||
using MiraAPI.Example.Roles;
|
||||
using MiraAPI.Utilities;
|
||||
using Reactor.Utilities;
|
||||
|
||||
namespace MiraAPI.Example;
|
||||
|
||||
public static class ExampleEventHandlers
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
// You can register event handlers with the MiraEventManager class
|
||||
var handle = MiraEventManager.RegisterEventHandler<BeforeMurderEvent>(@event =>
|
||||
{
|
||||
Logger<ExamplePlugin>.Info($"{@event.Source.Data.PlayerName} is about to kill {@event.Target.Data.PlayerName}");
|
||||
});
|
||||
|
||||
MiraEventManager.RegisterEventHandler<AfterMurderEvent>(@event =>
|
||||
{
|
||||
Logger<ExamplePlugin>.Info($"{@event.Source.Data.PlayerName} has killed {@event.Target.Data.PlayerName}");
|
||||
});
|
||||
|
||||
MiraEventManager.RegisterEventHandler<CompleteTaskEvent>(@event =>
|
||||
{
|
||||
Logger<ExamplePlugin>.Info($"{@event.Player.Data.PlayerName} completed {@event.Task.TaskType.ToString()}");
|
||||
});
|
||||
|
||||
// You can also unregister event handlers using the handle returned from RegisterEventHandler.
|
||||
MiraEventManager.UnregisterEventHandler(handle);
|
||||
}
|
||||
|
||||
// If you want to check vanilla buttons, use something like this!
|
||||
[RegisterEvent]
|
||||
public static void VanillaButtonClickHandler(VanillaButtonClickEvent @event)
|
||||
{
|
||||
Logger<ExamplePlugin>.Info($"{@event.Button.buttonLabelText.text} is being used!");
|
||||
if (@event.PlayerTarget != null)
|
||||
{
|
||||
Logger<ExamplePlugin>.Info($"{@event.PlayerTarget.Data.PlayerName} is being targeted!");
|
||||
}
|
||||
else if (@event.VentTarget != null)
|
||||
{
|
||||
Logger<ExamplePlugin>.Info($"Vent with id {@event.VentTarget.Id.ToString(CultureInfo.InvariantCulture)} is being targeted!");
|
||||
}
|
||||
}
|
||||
|
||||
// If you want to add extra votes to a player, do something like this.
|
||||
[RegisterEvent]
|
||||
public static void StartMeetingEvent(StartMeetingEvent _)
|
||||
{
|
||||
foreach (var plr in PlayerControl.AllPlayerControls.ToArray().Where(player => player.Data.Role is MayorRole))
|
||||
{
|
||||
plr.GetVoteData().IncreaseRemainingVotes(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Example of using the Voting API to make a role similar to the Prosecutor from Town of Us.
|
||||
[RegisterEvent(15)]
|
||||
public static void HandleVoteEvent(HandleVoteEvent @event)
|
||||
{
|
||||
if (@event.VoteData.Owner.Data.Role is not NeutralKillerRole) return;
|
||||
|
||||
@event.VoteData.SetRemainingVotes(0);
|
||||
|
||||
for (var i = 0; i < 5; i++)
|
||||
{
|
||||
@event.VoteData.VoteForPlayer(@event.TargetId);
|
||||
}
|
||||
|
||||
foreach (var plr in PlayerControl.AllPlayerControls.ToArray().Where(player => player != @event.VoteData.Owner))
|
||||
{
|
||||
plr.GetVoteData().Votes.Clear();
|
||||
plr.GetVoteData().VotesRemaining = 0;
|
||||
}
|
||||
|
||||
@event.Cancel();
|
||||
}
|
||||
|
||||
// Events can be registered using an attribute as well.
|
||||
[RegisterEvent]
|
||||
public static void UpdateSystemEventHandler(UpdateSystemEvent @event)
|
||||
{
|
||||
Logger<ExamplePlugin>.Error(@event.SystemType.ToString());
|
||||
}
|
||||
|
||||
// Example event handler
|
||||
[RegisterEvent(1)]
|
||||
public static void FreezeButtonClickHandler(MiraButtonClickEvent<FreezeButton> @event)
|
||||
{
|
||||
Logger<ExamplePlugin>.Warning("Freeze button clicked!");
|
||||
|
||||
if (PlayerControl.LocalPlayer.Data.PlayerName != "stupid") return;
|
||||
|
||||
@event.Cancel();
|
||||
@event.Button.SetTimer(15f);
|
||||
}
|
||||
|
||||
// Example event handler
|
||||
[RegisterEvent]
|
||||
public static void FreezeButtonCancelledHandler(MiraButtonCancelledEvent<FreezeButton> @event)
|
||||
{
|
||||
Logger<ExamplePlugin>.Warning("Freeze button cancelled!");
|
||||
@event.Button.OverrideName("Freeze Canceled");
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using MiraAPI.Keybinds;
|
||||
using Rewired;
|
||||
|
||||
namespace MiraAPI.Example;
|
||||
|
||||
[RegisterCustomKeybinds]
|
||||
public static class ExampleKeybinds
|
||||
{
|
||||
public static MiraKeybind NeutralWinKeybind { get; } = new("Neutral Win", KeyboardKeyCode.C, ControllerButton.RightStick, [ModifierKey.Shift]);
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
using BepInEx.Configuration;
|
||||
using MiraAPI.LocalSettings;
|
||||
using MiraAPI.LocalSettings.Attributes;
|
||||
using MiraAPI.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example;
|
||||
|
||||
public class ExampleLocalSettings(ConfigFile config) : LocalSettingsTab(config)
|
||||
{
|
||||
public override string TabName => "settings.miraExample";
|
||||
protected override bool ShouldCreateLabels => false;
|
||||
|
||||
public override LocalSettingTabAppearance TabAppearance => new()
|
||||
{
|
||||
ToggleActiveColor = Color.blue,
|
||||
ToggleInactiveColor = Color.red,
|
||||
};
|
||||
|
||||
[LocalSettingsButton]
|
||||
public LocalSettingsButton ExampleButton { get; private set; } = new("settings.miraExample.button.exampleButton", OnExampleButtonClick);
|
||||
|
||||
[LocalToggleSetting]
|
||||
public ConfigEntry<bool> ExampleToggle { get; private set; } = config.Bind("General", "Example Bool", true);
|
||||
|
||||
[LocalToggleSetting]
|
||||
public ConfigEntry<bool> ExampleToggle2 { get; private set; } = config.Bind("General", "Example Bool 2", false);
|
||||
|
||||
[LocalSliderSetting(suffixType: MiraNumberSuffixes.Percent, formatString: "0", roundValue: true)]
|
||||
public ConfigEntry<float> ExampleSlider { get; private set; } = config.Bind("General", "Slider", 50f);
|
||||
|
||||
[LocalNumberSetting]
|
||||
public ConfigEntry<float> ExampleNumber { get; private set; } = config.Bind("General", "Example Number", 4f);
|
||||
|
||||
[LocalNumberSetting(min: 0.1f, max: 2.5f, increment: 0.1f, formatString: "0.0", suffixType: MiraNumberSuffixes.Multiplier)]
|
||||
public ConfigEntry<float> ExampleFloatNumber { get; private set; } = config.Bind("General", "Example Multiplier", 1f);
|
||||
|
||||
[LocalEnumSetting]
|
||||
public ConfigEntry<ExampleEnumSetting> ExampleEnum { get; private set; } = config.Bind("General", "Example Enum", ExampleEnumSetting.Fries);
|
||||
|
||||
private static void OnExampleButtonClick()
|
||||
{
|
||||
LocalSettingsTabSingleton<MiraApiSettings>.Instance.Open();
|
||||
}
|
||||
}
|
||||
|
||||
public enum ExampleEnumSetting
|
||||
{
|
||||
Cheeseburger,
|
||||
Sandwich,
|
||||
Fries,
|
||||
ChickenNuggets,
|
||||
}
|
||||
@@ -2,8 +2,11 @@
|
||||
using BepInEx.Configuration;
|
||||
using BepInEx.Unity.IL2CPP;
|
||||
using HarmonyLib;
|
||||
using MiraAPI.Cosmetics;
|
||||
using MiraAPI.Example.Cosmetics;
|
||||
using MiraAPI.PluginLoading;
|
||||
using MiraAPI.Translation;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using MiraAPI.Utilities.Assets.Addressable;
|
||||
using Reactor;
|
||||
using Reactor.Networking;
|
||||
using Reactor.Networking.Attributes;
|
||||
@@ -17,23 +20,18 @@ namespace MiraAPI.Example;
|
||||
[ReactorModFlags(ModFlags.RequireOnAllClients)]
|
||||
public partial class ExamplePlugin : BasePlugin, IMiraPlugin
|
||||
{
|
||||
public ExamplePlugin()
|
||||
{
|
||||
MiraLocaleManager.Register("mira.example");
|
||||
}
|
||||
|
||||
public Harmony Harmony { get; } = new(Id);
|
||||
public string OptionsTitleText { get; } = "Mira API\nExample Mod";
|
||||
public string CustomOptionMenuNameTwo { get; } = "Example Options";
|
||||
|
||||
public ConfigFile GetConfigFile()
|
||||
{
|
||||
return Config;
|
||||
}
|
||||
|
||||
public string OptionsTitleText => "Mira API\nExample Mod";
|
||||
public ConfigFile GetConfigFile() => Config;
|
||||
public override void Load()
|
||||
{
|
||||
ExampleEventHandlers.Initialize();
|
||||
Harmony.PatchAll();
|
||||
AddComponent<MiraDebugWindow>();
|
||||
|
||||
new Catalog("Output".ToLocalPath()).LoadCatalog();
|
||||
CosmeticGroupSingleton<ExampleCosmeticGroup>.Instance.hats = new LoadableAddressableGroupAsset<HatData>(CatalogTools.GetResourceLocation("hatdata")).LoadAsset();
|
||||
CosmeticGroupSingleton<ExampleCosmeticGroup>.Instance.namePlates = new LoadableAddressableGroupAsset<NamePlateData>(CatalogTools.GetResourceLocation("nameplatedata")).LoadAsset();
|
||||
CosmeticGroupSingleton<ExampleCosmeticGroup>.Instance.skins = new LoadableAddressableGroupAsset<SkinData>(CatalogTools.GetResourceLocation("skindata")).LoadAsset();
|
||||
CosmeticGroupSingleton<ExampleCosmeticGroup>.Instance.visors = new LoadableAddressableGroupAsset<VisorData>(CatalogTools.GetResourceLocation("visordata")).LoadAsset();
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using MiraAPI.GameModes;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.GameModes;
|
||||
|
||||
public class ExampleMode : AbstractGameMode
|
||||
{
|
||||
public override string Name => "Example Mode";
|
||||
public override string Description => "An example gamemode.";
|
||||
public override LoadableAsset<Sprite>? Icon => ExampleAssets.ExampleButton;
|
||||
public override Color Color => Color.red;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using MiraAPI.Example.Roles;
|
||||
using MiraAPI.GameEnd;
|
||||
using MiraAPI.Translation;
|
||||
using MiraAPI.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.GameOver;
|
||||
|
||||
public class NeutralKillerGameOver : CustomGameOver
|
||||
{
|
||||
public override bool VerifyCondition(PlayerControl playerControl, NetworkedPlayerInfo[] winners)
|
||||
{
|
||||
return winners is [{ Role: NeutralKillerRole }];
|
||||
}
|
||||
|
||||
public override void AfterEndGameSetup(EndGameManager endGameManager)
|
||||
{
|
||||
endGameManager.WinText.text = "gameover.outcastKiller.win".Translate();
|
||||
endGameManager.WinText.color = Color.magenta;
|
||||
endGameManager.BackgroundBar.material.SetColor(ShaderID.Color, Color.magenta);
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using MiraAPI.Example.Roles;
|
||||
using MiraAPI.MeetingAbilities;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.MeetingAbilities;
|
||||
|
||||
public class EndMeetingButton : MeetingActionButton
|
||||
{
|
||||
public override string Name => "End Meeting";
|
||||
|
||||
public override float Cooldown => 15;
|
||||
|
||||
public override float InitialCooldown => 30;
|
||||
|
||||
public override int MaxUses => 3;
|
||||
|
||||
public override LoadableAsset<Sprite> Sprite => ExampleAssets.ExampleButton;
|
||||
|
||||
public override bool Enabled(RoleBehaviour? role)
|
||||
{
|
||||
return PlayerControl.LocalPlayer != null && role is MayorRole;
|
||||
}
|
||||
|
||||
protected override void OnClick()
|
||||
{
|
||||
MeetingHud.Instance.RpcClose();
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using MiraAPI.MeetingAbilities;
|
||||
using MiraAPI.Networking;
|
||||
using MiraAPI.Utilities;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.MeetingAbilities;
|
||||
|
||||
public class ShootButton : TargetedMeetingButton
|
||||
{
|
||||
public override string Name => "Shoot";
|
||||
|
||||
public override int MaxUses => 3;
|
||||
|
||||
public override float InitialCooldown => 5;
|
||||
|
||||
public override float Cooldown => 3;
|
||||
|
||||
public override LoadableAsset<Sprite> Sprite => ExampleAssets.SharpshootButton;
|
||||
|
||||
public override Color OutlineColor => Color.red;
|
||||
|
||||
public override bool Enabled(RoleBehaviour r)
|
||||
{
|
||||
return r.IsImpostor;
|
||||
}
|
||||
|
||||
protected override void OnClick(PlayerVoteArea playerVoteArea)
|
||||
{
|
||||
playerVoteArea.SetDisabled();
|
||||
var player = playerVoteArea.GetPlayer();
|
||||
if (player != null)
|
||||
{
|
||||
PlayerControl.LocalPlayer.RpcCustomMurder(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
using MiraAPI.MeetingAbilities;
|
||||
using MiraAPI.Networking;
|
||||
using MiraAPI.Utilities;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.MeetingAbilities;
|
||||
|
||||
public class ShotgunButton : MultiTargetMeetingButton
|
||||
{
|
||||
public override string Name => "Shotgun";
|
||||
|
||||
public override int MaxUses => 3;
|
||||
|
||||
public override float InitialCooldown => 5;
|
||||
|
||||
public override float Cooldown => 3;
|
||||
|
||||
public override LoadableAsset<Sprite> Sprite => ExampleAssets.SharpshootButton;
|
||||
|
||||
public override Color OutlineColor => Color.red;
|
||||
|
||||
public override bool Enabled(RoleBehaviour r)
|
||||
{
|
||||
return r.IsImpostor;
|
||||
}
|
||||
|
||||
protected override void OnClick(PlayerVoteArea playerVoteArea)
|
||||
{
|
||||
// Emptu because it only triggers the actual kills once all meeting abilities have been used.
|
||||
}
|
||||
|
||||
public override LoadableAsset<Sprite> SpriteActive => ExampleAssets.CallMeetingButton;
|
||||
|
||||
public override int TargetsCount => 4;
|
||||
|
||||
protected override void OnSelect(PlayerVoteArea playerVoteArea, bool toggle)
|
||||
{
|
||||
HudManager.Instance.PlayerCam.ShakeScreen(0.5f, 2);
|
||||
}
|
||||
|
||||
public override void OnFinish()
|
||||
{
|
||||
foreach (var playerVoteArea in Targets.Keys)
|
||||
{
|
||||
playerVoteArea.SetDisabled();
|
||||
var player = playerVoteArea.GetPlayer();
|
||||
if (player != null)
|
||||
{
|
||||
PlayerControl.LocalPlayer.RpcCustomMurder(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<Version>1.0.0</Version>
|
||||
<Description>Example mod for Mira API</Description>
|
||||
<Authors>Author Name</Authors>
|
||||
<NoWarn>$(NoWarn);EnableGenerateDocumentationFile</NoWarn>
|
||||
<Authors>Angxl, XtraCube</Authors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MiraAPI\MiraAPI.csproj" /> <!-- You typically would use the nuget package here: AllOfUs.MiraAPI -->
|
||||
<ProjectReference Include="..\MiraAPI\MiraAPI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\**\*.*" />
|
||||
<EmbeddedResource Include="Resources\ExampleButton.png" />
|
||||
<EmbeddedResource Include="Resources\FortniteBanner.jpeg" />
|
||||
<EmbeddedResource Include="Resources\TeleportButton.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\AmongUs.props" />
|
||||
|
||||
@@ -1,35 +1,20 @@
|
||||
using MiraAPI.Example.Options.Modifiers;
|
||||
using MiraAPI.GameOptions;
|
||||
using MiraAPI.Modifiers;
|
||||
using MiraAPI.Modifiers;
|
||||
using MiraAPI.Modifiers.Types;
|
||||
using MiraAPI.Translation;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.Modifiers;
|
||||
|
||||
[RegisterModifier]
|
||||
public class CaptainModifier : GameModifier
|
||||
{
|
||||
public override string ModifierName => MiraLocaleManager.Get("modifier.captain");
|
||||
public override LoadableAsset<Sprite>? ModifierIcon => ExampleAssets.CallMeetingButton;
|
||||
public override string ModifierName => "Captain";
|
||||
|
||||
public override void OnDeath(DeathReason reason)
|
||||
public override int GetAmountPerGame()
|
||||
{
|
||||
Player.RemoveModifier(this);
|
||||
}
|
||||
|
||||
public override string GetDescription()
|
||||
{
|
||||
return MiraLocaleManager.Get("modifier.captain.TabDescription");
|
||||
return 1;
|
||||
}
|
||||
|
||||
public override int GetAssignmentChance()
|
||||
{
|
||||
return (int)OptionGroupSingleton<CaptainModifierSettings>.Instance.Chance;
|
||||
}
|
||||
|
||||
public override int GetAmountPerGame()
|
||||
{
|
||||
return (int)OptionGroupSingleton<CaptainModifierSettings>.Instance.Amount;
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,15 @@
|
||||
using MiraAPI.Example.Roles;
|
||||
using Il2CppSystem;
|
||||
using MiraAPI.Example.Roles;
|
||||
using MiraAPI.Modifiers;
|
||||
using MiraAPI.Modifiers.Types;
|
||||
using MiraAPI.Translation;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.Modifiers.Freezer;
|
||||
|
||||
[RegisterModifier]
|
||||
public class FreezeModifier : TimedModifier
|
||||
{
|
||||
public override string ModifierName => MiraLocaleManager.Get("modifier.freezed");
|
||||
public override string ModifierName => "Freezed";
|
||||
public override bool HideOnUi => false;
|
||||
public override float Duration => 15f;
|
||||
public override bool AutoStart => true;
|
||||
@@ -15,7 +17,7 @@ public class FreezeModifier : TimedModifier
|
||||
|
||||
public override void OnActivate()
|
||||
{
|
||||
if (Player.AmOwner)
|
||||
if (Player?.AmOwner == true)
|
||||
{
|
||||
Player.moveable = false;
|
||||
}
|
||||
@@ -25,15 +27,15 @@ public class FreezeModifier : TimedModifier
|
||||
{
|
||||
base.FixedUpdate();
|
||||
|
||||
if (Player.AmOwner || PlayerControl.LocalPlayer.Data.Role is FreezerRole)
|
||||
if (Player?.AmOwner == true || PlayerControl.LocalPlayer.Data.Role is FreezerRole)
|
||||
{
|
||||
Player.cosmetics.SetOutline(true, new Il2CppSystem.Nullable<Color>(Palette.LightBlue));
|
||||
Player?.cosmetics.SetOutline(true, new Nullable<Color>(Palette.LightBlue));
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnTimerComplete()
|
||||
{
|
||||
if (Player.AmOwner)
|
||||
if (Player?.AmOwner == true)
|
||||
{
|
||||
Player.moveable = true;
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
using MiraAPI.Modifiers.Types;
|
||||
using MiraAPI.Translation;
|
||||
|
||||
namespace MiraAPI.Example.Modifiers;
|
||||
|
||||
public class HighPriorityModifier : GameModifier
|
||||
{
|
||||
public override string ModifierName => MiraLocaleManager.Get("modifier.highPriority");
|
||||
|
||||
public override string GetDescription()
|
||||
{
|
||||
return MiraLocaleManager.Get("modifier.highPriority.TabDescription");
|
||||
}
|
||||
|
||||
public override int GetAssignmentChance()
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
public override int GetAmountPerGame()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public override int Priority()
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
@@ -1,88 +1,31 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using MiraAPI.GameOptions;
|
||||
using MiraAPI.GameOptions;
|
||||
using MiraAPI.GameOptions.Attributes;
|
||||
using MiraAPI.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.Options;
|
||||
|
||||
[SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "Demo.")]
|
||||
[SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "Read above.")]
|
||||
[SuppressMessage("Minor Code Smell", "S3400:Methods should not return constants", Justification = "Read above.")]
|
||||
public class ExampleOptions : AbstractOptionGroup
|
||||
{
|
||||
public override string GroupName => "options.exampleOptions1";
|
||||
public override string GroupName => "Example Options 1";
|
||||
public override Color GroupColor => Color.green;
|
||||
public override bool ShowInMatchInfoGuide => true;
|
||||
|
||||
[ModdedToggleOption("options.exampleOptions1.toggleOpt1")]
|
||||
[ModdedOptionVisibility] // Automatically resolves to using ToggleOpt1Visibility, can also target toggle options
|
||||
public bool ToggleOpt1 { get; set; } = false;
|
||||
[ModdedToggleOption("Toggle Opt 1")]
|
||||
public bool ToggleOpt { get; set; } = false;
|
||||
|
||||
[ModdedToggleOption("options.exampleOptions1.toggleOpt2")]
|
||||
[ModdedOptionVisibility(nameof(ToggleOpt1))] // ToggleOpt2 will be visible only when ToggleOpt1 is true
|
||||
[ModdedToggleOption("Toggle Opt 2")]
|
||||
public bool ToggleOpt2 { get; set; } = true;
|
||||
|
||||
[ModdedNumberOption("options.exampleOptions1.numberOpt", min: 0, max: 10, increment: .25f, formatString: "0.00", suffixType: MiraNumberSuffixes.Percent)]
|
||||
[ModdedOptionVisibility(nameof(NumberOptVisibility))] // Can also target static methods
|
||||
[ModdedNumberOption("Number Opt", min: 0, max: 10, suffixType: MiraNumberSuffixes.Percent)]
|
||||
public float NumberOpt { get; set; } = 4f;
|
||||
|
||||
[ModdedNumberOption("options.exampleOptions1.numberOpt", min: 0, max: 10, suffixType: MiraNumberSuffixes.Distance)]
|
||||
public int NumberOpt2 { get; set; } = 4; // Can also be int!
|
||||
|
||||
[ModdedEnumOption("options.exampleOptions1.bestApi", typeof(Api), ["Mira API", "Mitochondria", "Reactor"])]
|
||||
public Api BestApi { get; set; } = Api.MiraAPI;
|
||||
|
||||
[ModdedEnumOption<Api>("options.exampleOptions1.worstApi", ["Mira API", "Mitochondria", "Reactor"])]
|
||||
|
||||
// These three can target both instance and static methods
|
||||
[ModdedOptionGetter(nameof(GetApi))] // Can also automatically resolve to {Option Name}Getter
|
||||
[ModdedOptionSetter(nameof(SetApi))] // Can also automatically resolve to {Option Name}Setter
|
||||
[ModdedOptionChanged(nameof(ApiChanged))] // Can also automatically resolve to {Option Name}Changed
|
||||
public Api WorstApi { get; set; } = Api.MiraAPI;
|
||||
|
||||
[ModdedEnumOptionList<ValueState>("Value State {0}", ["None", "Primary", "Secondary"])]
|
||||
public ModdedArray<ValueState> ValueStates { get; set; } = [ValueState.Primary, ValueState.Secondary, ValueState.None, ValueState.None, ValueState.None];
|
||||
|
||||
[ModdedPlayerOption("options.exampleOptions1.players")]
|
||||
public NetworkedPlayerInfo PlayerSelected { get; set; }
|
||||
|
||||
public bool ToggleOpt1Visibility()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool NumberOptVisibility()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Api GetApi(Api currentValue)
|
||||
{
|
||||
return currentValue;
|
||||
}
|
||||
|
||||
public static Api SetApi(Api newValue, Api oldValue)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
public static void ApiChanged(Api currentValue)
|
||||
{
|
||||
// Something
|
||||
}
|
||||
[ModdedEnumOption("Best API", typeof(BestApi), ["Mira API", "Mitochondria", "Reactor"])]
|
||||
public BestApi Opt { get; set; } = BestApi.MiraAPI;
|
||||
}
|
||||
|
||||
public enum Api
|
||||
public enum BestApi
|
||||
{
|
||||
MiraAPI,
|
||||
Mitochondria,
|
||||
Reactor,
|
||||
}
|
||||
|
||||
public enum ValueState
|
||||
{
|
||||
None,
|
||||
Primary,
|
||||
Secondary,
|
||||
}
|
||||
@@ -6,32 +6,24 @@ namespace MiraAPI.Example.Options;
|
||||
|
||||
public class ExampleOptions2 : AbstractOptionGroup
|
||||
{
|
||||
public override string GroupName => "options.exampleOptions2";
|
||||
public override string GroupName => "Example Options 2";
|
||||
|
||||
public override uint GroupPriority => 0; // This group will be displayed first. The default value is uint.MaxValue.
|
||||
public override MenuCategory ParentMenu => MenuCategory.CustomTwo;
|
||||
public override bool ShowInMatchInfoGuide => true;
|
||||
|
||||
public ModdedPlayerOption PlayerOption2 { get; } = new("options.exampleOptions2.youMustChoseAPlayer", false);
|
||||
public ModdedPlayerOption PlayerOption { get; } = new("options.exampleOptions2.ehWhatever");
|
||||
public ModdedToggleOption ToggleOpt1 { get; } = new("options.exampleOptions2.toggleOption1", false);
|
||||
public ModdedToggleOption ToggleOpt1 { get; } = new("Toggle Option 1", false);
|
||||
|
||||
public ModdedOptionList<ModdedNumberOption> PlayerNums { get; } = new(5, i =>
|
||||
new($"PlayerNum{i}", 2, 0, 5, 1, Utilities.MiraNumberSuffixes.None));
|
||||
|
||||
public ModdedToggleOption ToggleOpt2 { get; } = new("options.exampleOptions2.toggleOption2", false)
|
||||
public ModdedToggleOption ToggleOpt2 { get; } = new("Toggle Option 2", false)
|
||||
{
|
||||
Visible = () => OptionGroupSingleton<ExampleOptions2>.Instance.ToggleOpt1, // implicit cast from ModdedToggleOption to bool
|
||||
Visible = () => OptionGroupSingleton<ExampleOptions2>.Instance.ToggleOpt1.Value,
|
||||
};
|
||||
|
||||
public ModdedEnumOption<TestingData> EnumOpt { get; } = new("options.exampleOptions2.enumOpt", 0)
|
||||
public ModdedEnumOption EnumOpt { get; } = new("Enum Opt", 0, typeof(TestingData))
|
||||
{
|
||||
ChangedEvent = x => Logger<ExamplePlugin>.Info($"changed Enum Opt to {x}"),
|
||||
Getter = currentValue => currentValue,
|
||||
Setter = (newValue, oldValue) => newValue,
|
||||
};
|
||||
}
|
||||
|
||||
public enum TestingData : ulong
|
||||
public enum TestingData
|
||||
{
|
||||
Happy,
|
||||
Sad,
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
using MiraAPI.Example.Modifiers;
|
||||
using MiraAPI.GameOptions;
|
||||
using MiraAPI.GameOptions.Attributes;
|
||||
|
||||
namespace MiraAPI.Example.Options.Modifiers;
|
||||
|
||||
public class CaptainModifierSettings : AbstractOptionGroup<CaptainModifier>
|
||||
{
|
||||
public override string GroupName => "options.captainSettings";
|
||||
|
||||
[ModdedNumberOption("options.captainSettings.amount", 0, 5)]
|
||||
public float Amount { get; set; } = 1;
|
||||
|
||||
[ModdedNumberOption("options.captainSettings.chance", 0, 100, 10)]
|
||||
public float Chance { get; set; } = 50;
|
||||
|
||||
[ModdedNumberOption("options.captainSettings.uses", 1, 5)]
|
||||
public float NumUses { get; set; } = 3;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using MiraAPI.Example.Modifiers.Freezer;
|
||||
using MiraAPI.GameOptions;
|
||||
using MiraAPI.GameOptions.Attributes;
|
||||
|
||||
namespace MiraAPI.Example.Options.Modifiers;
|
||||
|
||||
public class FreezeModifierSettings : AbstractOptionGroup<FreezeModifier>
|
||||
{
|
||||
public override string GroupName => "options.freezeModifierSettings";
|
||||
|
||||
[ModdedToggleOption("options.freezeModifierSettings.useColor")]
|
||||
public bool UseColor { get; set; } = true;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using MiraAPI.GameOptions;
|
||||
using MiraAPI.GameOptions.Attributes;
|
||||
|
||||
namespace MiraAPI.Example.Options.Modifiers;
|
||||
|
||||
public class GeneralModifierOptions : AbstractOptionGroup
|
||||
{
|
||||
public override string GroupName => "options.generalModifier";
|
||||
public override uint GroupPriority => 0;
|
||||
public override MenuCategory ParentMenu => MenuCategory.Modifiers;
|
||||
|
||||
[ModdedToggleOption("options.generalModifier.someBooleanOption")]
|
||||
public bool SomeBooleanOption { get; set; } = true;
|
||||
|
||||
[ModdedNumberOption("options.generalModifier.numberOption", 0, 10)]
|
||||
public float NumberOption { get; set; } = 5;
|
||||
}
|
||||
@@ -1,23 +1,20 @@
|
||||
using MiraAPI.Example.Roles;
|
||||
using System;
|
||||
using MiraAPI.Example.Roles;
|
||||
using MiraAPI.GameOptions;
|
||||
using MiraAPI.GameOptions.Attributes;
|
||||
using MiraAPI.Utilities;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
|
||||
namespace MiraAPI.Example.Options.Roles;
|
||||
|
||||
public class FreezerRoleSettings : AbstractOptionGroup<FreezerRole>
|
||||
public class FreezerRoleSettings : AbstractOptionGroup
|
||||
{
|
||||
public override OptionNotifConfiguration Configuration => new(
|
||||
Palette.Blue,
|
||||
TmpSpriteUtils.CreateSpriteAsset(
|
||||
MiraAssets.ImpostorFile.LoadAsset(),
|
||||
"ApiExample.Role.Impostor.FreezerRole"));
|
||||
public override string GroupName => "ApiExample.Role.Freezer";
|
||||
public override string GroupName => "Custom Role";
|
||||
|
||||
[ModdedNumberOption("ApiExample.Role.Freezer.Settings.FreezeDuration", 1, 15, 1, MiraNumberSuffixes.Seconds)]
|
||||
public override Type AdvancedRole => typeof(FreezerRole);
|
||||
|
||||
[ModdedNumberOption("Freeze Duration", 1, 15, 1, MiraNumberSuffixes.Seconds)]
|
||||
public float FreezeDuration { get; set; } = 5;
|
||||
|
||||
[ModdedNumberOption("ApiExample.Role.Freezer.Settings.FreezeUses", 1, 5)]
|
||||
[ModdedNumberOption("Freeze Uses", 1, 5)]
|
||||
public float FreezeUses { get; set; } = 1;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using MiraAPI.Example.Roles;
|
||||
using System;
|
||||
using MiraAPI.Example.Roles;
|
||||
using MiraAPI.GameOptions;
|
||||
using MiraAPI.GameOptions.Attributes;
|
||||
using MiraAPI.GameOptions.OptionTypes;
|
||||
@@ -6,15 +7,17 @@ using MiraAPI.Utilities;
|
||||
|
||||
namespace MiraAPI.Example.Options.Roles;
|
||||
|
||||
public class TeleporterOptions : AbstractRoleOptionGroup<TeleporterRole>
|
||||
public class TeleporterOptions : AbstractOptionGroup
|
||||
{
|
||||
public override string GroupName => "ApiExample.Role.Teleporter";
|
||||
public override string GroupName => "Teleporter";
|
||||
|
||||
public ModdedNumberOption TeleportCooldown { get; set; } = new("ApiExample.Role.Teleporter.Settings.TeleportCooldown", 10, 5, 60, 2.5f, MiraNumberSuffixes.Seconds);
|
||||
public override Type AdvancedRole => typeof(TeleporterRole);
|
||||
|
||||
[ModdedNumberOption("ApiExample.Role.Teleporter.Settings.TeleportDuration", 5, 25, 1, MiraNumberSuffixes.Seconds)]
|
||||
public ModdedNumberOption TeleportCooldown { get; set; } = new("Teleport Cooldown", 10, 5, 60, 2.5f, MiraNumberSuffixes.Seconds);
|
||||
|
||||
[ModdedNumberOption("Teleport Duration", 5, 25, 1, MiraNumberSuffixes.Seconds)]
|
||||
public float TeleportDuration { get; set; } = 10;
|
||||
|
||||
[ModdedNumberOption("ApiExample.Role.Teleporter.Settings.ZoomDistance", 4, 15)]
|
||||
[ModdedNumberOption("Zoom Distance", 4, 15)]
|
||||
public float ZoomDistance { get; set; } = 6;
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 36 KiB |
@@ -1,86 +0,0 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<resources>
|
||||
<string name="ApiExample.Role.Crewmate.Teleporter">Teleporter</string>
|
||||
<string name="ApiExample.Role.Crewmate.Teleporter.IntroBlurb">Zoom out and teleport across the map!</string>
|
||||
<string name="ApiExample.Role.Crewmate.Teleporter.MedDescription">Zoom out and teleport across the map!</string>
|
||||
<string name="ApiExample.Role.Crewmate.Teleporter.TabDescription">Zoom out and teleport across the map!</string>
|
||||
<string name="ApiExample.Role.Crewmate.Teleporter.WikiDescription">The Teleporter is a Crewmate role that can move around the map using their dope-ass ability.</string>
|
||||
<string name="ApiExample.Role.Impostor.Freezer">Freezer</string>
|
||||
<string name="ApiExample.Role.Impostor.Freezer.IntroBlurb">Get iced, nerd.</string>
|
||||
<string name="ApiExample.Role.Impostor.Freezer.MedDescription">Freeze others for a duration of time.</string>
|
||||
<string name="ApiExample.Role.Impostor.Freezer.TabDescription">Freeze another player for a duration of time.</string>
|
||||
<string name="ApiExample.Role.Impostor.Freezer.WikiDescription">The Freezer is an Impostor role that can freeze players. Or something along those lines.</string>
|
||||
<string name="ApiExample.Role.Crewmate.Mayor">Mayor</string>
|
||||
<string name="ApiExample.Role.Crewmate.Mayor.IntroBlurb">Democracy is the best policy.</string>
|
||||
<string name="ApiExample.Role.Crewmate.Mayor.MedDescription">Vote out the Impostors with more votes.
|
||||
Your votes have double the power.</string>
|
||||
<string name="ApiExample.Role.Crewmate.Mayor.TabDescription">You get one extra vote in the meeting!</string>
|
||||
<string name="ApiExample.Role.Crewmate.Mayor.WikiDescription">The Mayor is a Crewmate role that gets two votes in the meeting, instead of the singular vote other Crewmates get.</string>
|
||||
<string name="ApiExample.Role.Crewmate.Chameleon">Chameleon</string>
|
||||
<string name="ApiExample.Role.Crewmate.Chameleon.IntroBlurb">Become one with the environment.</string>
|
||||
<string name="ApiExample.Role.Crewmate.Chameleon.MedDescription">Fade out of everyone's vision by not moving.</string>
|
||||
<string name="ApiExample.Role.Crewmate.Chameleon.TabDescription">Stay invisible while not moving.</string>
|
||||
<string name="ApiExample.Role.Crewmate.Chameleon.WikiDescription">The Chameleon is a Crewmate role that slowly becomes invisible while standing still.</string>
|
||||
<string name="ApiExample.Role.Outcast.OutcastKiller">Outcast Killer</string>
|
||||
<string name="ApiExample.Role.Outcast.OutcastKiller.IntroBlurb">Kill everyone else.</string>
|
||||
<string name="ApiExample.Role.Outcast.OutcastKiller.MedDescription">Be the last outcast standing.
|
||||
Eliminate every other faction.</string>
|
||||
<string name="ApiExample.Role.Outcast.OutcastKiller.TabDescription">Outcast who can kill.</string>
|
||||
<string name="ApiExample.Role.Outcast.OutcastKiller.WikiDescription">The Outcast Killer is an Outcast role that can kill, like some sort of neutral killer...</string>
|
||||
<string name="outcast">Outcast</string>
|
||||
<string name="outcast.group">Outcast Roles</string>
|
||||
<string name="outcast.roleTitle">OUTCAST</string>
|
||||
<string name="outcast.teamIntroDescription">You are an Outcast. You do not have a team.</string>
|
||||
<string name="button.think">Think</string>
|
||||
<string name="button.think.thinking">Thinking...</string>
|
||||
<string name="button.freeze">Freeze</string>
|
||||
<string name="button.teleport">Teleport</string>
|
||||
<string name="button.callMeeting">Call Meeting</string>
|
||||
<string name="button.winGame">Win Game</string>
|
||||
<string name="modifier.captain">Captain</string>
|
||||
<string name="modifier.captain.TabDescription">You can call a meeting from anywhere on the map.</string>
|
||||
<string name="modifier.freezed">Freezed</string>
|
||||
<string name="modifier.highPriority">High Priority</string>
|
||||
<string name="modifier.highPriority.TabDescription">You are high priority! Idrk what this means either tbh...</string>
|
||||
<string name="options.exampleOptions1">Example Options 1</string>
|
||||
<string name="options.exampleOptions1.toggleOpt1">Toggle Opt 1</string>
|
||||
<string name="options.exampleOptions1.toggleOpt2">Toggle Opt 2</string>
|
||||
<string name="options.exampleOptions1.numberOpt">Number Opt</string>
|
||||
<string name="options.exampleOptions1.bestApi">Best API</string>
|
||||
<string name="options.exampleOptions1.worstApi">Worst API</string>
|
||||
<string name="options.exampleOptions1.players">Choose A Player</string>
|
||||
<string name="options.exampleOptions2">Example Options 2</string>
|
||||
<string name="options.exampleOptions2.youMustChoseAPlayer">YOU MUST CHOSE A PLAYER</string>
|
||||
<string name="options.exampleOptions2.ehWhatever">Eh whatever</string>
|
||||
<string name="options.exampleOptions2.toggleOption1">Toggle Option 1</string>
|
||||
<string name="options.exampleOptions2.toggleOption2">Toggle Option 2</string>
|
||||
<string name="options.exampleOptions2.enumOpt">Enum Opt</string>
|
||||
<string name="options.captainSettings">Captain Settings</string>
|
||||
<string name="options.captainSettings.amount">Amount</string>
|
||||
<string name="options.captainSettings.chance">Chance</string>
|
||||
<string name="options.captainSettings.uses">Uses</string>
|
||||
<string name="options.freezeModifierSettings">Freeze</string>
|
||||
<string name="options.freezeModifierSettings.useColor">Use Color</string>
|
||||
<string name="options.generalModifier">General</string>
|
||||
<string name="options.generalModifier.someBooleanOption">Some Boolean Option</string>
|
||||
<string name="options.generalModifier.numberOption">Number Option</string>
|
||||
<string name="options.freezerRoleSettings">Custom Role</string>
|
||||
<string name="ApiExample.Role.Freezer.Settings.FreezeDuration">Freeze Duration</string>
|
||||
<string name="ApiExample.Role.Freezer.Settings.FreezeUses">Freeze Uses</string>
|
||||
<string name="ApiExample.Role.Teleporter.Settings.TeleportCooldown">Teleport Cooldown</string>
|
||||
<string name="ApiExample.Role.Teleporter.Settings.TeleportDuration">Teleport Duration</string>
|
||||
<string name="ApiExample.Role.Teleporter.Settings.ZoomDistance">Zoom Distance</string>
|
||||
<string name="settings.miraExample">Mira Example</string>
|
||||
<string name="settings.miraExample.exampleBool">Example Bool</string>
|
||||
<string name="settings.miraExample.exampleBool2">Example Bool 2</string>
|
||||
<string name="settings.miraExample.slider">Slider</string>
|
||||
<string name="settings.miraExample.exampleNumber">Example Number</string>
|
||||
<string name="settings.miraExample.exampleMultiplier">Example Multiplier</string>
|
||||
<string name="settings.miraExample.exampleEnum">Example Enum</string>
|
||||
<string name="settings.miraExample.button.exampleButton">Example Button</string>
|
||||
<string name="gameover.outcastKiller.win">Outcast Killer Wins!</string>
|
||||
<string name="color.cerulean">Cerulean</string>
|
||||
<string name="color.rose">Rose</string>
|
||||
<string name="color.gold">Gold</string>
|
||||
<string name="color.rainbow">Rainbow</string>
|
||||
</resources>
|
||||
@@ -1,66 +0,0 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<resources>
|
||||
<string name="ApiExample.Role.Teleporter">传送者</string>
|
||||
<string name="ApiExample.Role.Teleporter.IntroBlurb">缩小视野并在地图上传送!</string>
|
||||
<string name="ApiExample.Role.Teleporter.MedDescription">缩小视野并在地图上传送!</string>
|
||||
<string name="ApiExample.Role.Teleporter.TabDescription">缩小视野并在地图上传送!</string>
|
||||
<string name="ApiExample.Role.Freezer">冰冻者</string>
|
||||
<string name="ApiExample.Role.Freezer.TabDescription">将其他玩家冰冻一段时间。</string>
|
||||
<string name="ApiExample.Role.Crewmate.Mayor">市长</string>
|
||||
<string name="ApiExample.Role.Crewmate.Mayor.TabDescription">你拥有额外投票权!</string>
|
||||
<string name="ApiExample.Role.Crewmate.Chamelon">变色龙</string>
|
||||
<string name="ApiExample.Role.Crewmate.Chamelon.TabDescription">静止不动时保持隐身。</string>
|
||||
<string name="ApiExample.Role.Outcast.OutcastKiller">流放杀手</string>
|
||||
<string name="ApiExample.Role.Outcast.OutcastKiller.TabDescription">可以击杀的流放者。</string>
|
||||
<string name="outcast">流放者</string>
|
||||
<string name="outcast.roleTitle">流放者</string>
|
||||
<string name="outcast.teamIntroDescription">你是流放者,你没有队伍。</string>
|
||||
<string name="button.think">思考</string>
|
||||
<string name="button.think.thinking">思考中...</string>
|
||||
<string name="button.freeze">冰冻</string>
|
||||
<string name="button.teleport">传送</string>
|
||||
<string name="button.callMeeting">召集会议</string>
|
||||
<string name="button.winGame">赢得游戏</string>
|
||||
<string name="modifier.captain">队长</string>
|
||||
<string name="modifier.captain.TabDescription">你可以在地图上任意位置召集会议。</string>
|
||||
<string name="modifier.freezed">已被冰冻</string>
|
||||
<string name="modifier.highPriority">高优先级</string>
|
||||
<string name="modifier.highPriority.TabDescription">你是高优先级!老实说我也不太清楚这是什么意思……</string>
|
||||
<string name="options.exampleOptions1">示例选项组 1</string>
|
||||
<string name="options.exampleOptions1.toggleOpt1">开关选项 1</string>
|
||||
<string name="options.exampleOptions1.toggleOpt2">开关选项 2</string>
|
||||
<string name="options.exampleOptions1.numberOpt">数字选项</string>
|
||||
<string name="options.exampleOptions1.bestApi">谁是最好的API</string>
|
||||
<string name="options.exampleOptions2">示例选项组 2</string>
|
||||
<string name="options.exampleOptions2.youMustChoseAPlayer">你必须选择一个玩家</string>
|
||||
<string name="options.exampleOptions2.ehWhatever">咕咕嘎嘎</string>
|
||||
<string name="options.exampleOptions2.toggleOption1">开关选项 1</string>
|
||||
<string name="options.exampleOptions2.toggleOption2">开关选项 2</string>
|
||||
<string name="options.exampleOptions2.enumOpt">枚举选项</string>
|
||||
<string name="options.captainSettings">队长设置</string>
|
||||
<string name="options.captainSettings.amount">数量</string>
|
||||
<string name="options.captainSettings.chance">概率</string>
|
||||
<string name="options.captainSettings.uses">使用次数</string>
|
||||
<string name="options.freezeModifierSettings">冰冻</string>
|
||||
<string name="options.freezeModifierSettings.useColor">使用颜色</string>
|
||||
<string name="options.generalModifier">通用</string>
|
||||
<string name="options.generalModifier.someBooleanOption">某个布尔选项</string>
|
||||
<string name="options.generalModifier.numberOption">数字选项</string>
|
||||
<string name="ApiExample.Role.Freezer.Settings.FreezeDuration">冰冻时长</string>
|
||||
<string name="ApiExample.Role.Freezer.Settings.FreezeUses">冰冻次数</string>
|
||||
<string name="ApiExample.Role.Teleporter.Settings.TeleportCooldown">传送冷却</string>
|
||||
<string name="ApiExample.Role.Teleporter.Settings.TeleportDuration">传送持续时间</string>
|
||||
<string name="ApiExample.Role.Teleporter.Settings.ZoomDistance">缩放距离</string>
|
||||
<string name="settings.miraExample">Mira 示例插件</string>
|
||||
<string name="settings.miraExample.exampleBool">示例布尔</string>
|
||||
<string name="settings.miraExample.exampleBool2">示例布尔 2</string>
|
||||
<string name="settings.miraExample.slider">滑块</string>
|
||||
<string name="settings.miraExample.exampleNumber">示例数字</string>
|
||||
<string name="settings.miraExample.exampleMultiplier">示例倍数</string>
|
||||
<string name="settings.miraExample.exampleEnum">示例枚举</string>
|
||||
<string name="settings.miraExample.button.exampleButton">示例按钮</string>
|
||||
<string name="gameover.outcastKiller.win">流放杀手获胜!</string>
|
||||
<string name="color.cerulean">天蓝</string>
|
||||
<string name="color.rose">玫瑰红</string>
|
||||
<string name="color.gold">金色</string>
|
||||
</resources>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 5.7 KiB |
@@ -1,88 +1,47 @@
|
||||
using AmongUs.GameOptions;
|
||||
using MiraAPI.Patches.Stubs;
|
||||
using MiraAPI.Roles;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using Reactor.Utilities;
|
||||
using MiraAPI.Roles;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.Roles;
|
||||
|
||||
public class ChameleonRole : CrewmateRole, ICustomRole
|
||||
[RegisterCustomRole]
|
||||
public class ChameloenRole : CrewmateRole, ICustomRole
|
||||
{
|
||||
private bool shouldHide;
|
||||
|
||||
public string IdPart => "Chameleon";
|
||||
public string IdPrefix => "ApiExample.Role.Crewmate";
|
||||
public string RoleName => "Chamelon";
|
||||
public string RoleLongDescription => "Stay invisible while not moving.";
|
||||
public string RoleDescription => RoleLongDescription;
|
||||
public Color RoleColor => Palette.AcceptedGreen;
|
||||
public ModdedRoleTeams Team => ModdedRoleTeams.Crewmate;
|
||||
|
||||
public CustomRoleConfiguration Configuration => new(this)
|
||||
public CustomRoleConfiguration Configuration => new CustomRoleConfiguration(this)
|
||||
{
|
||||
OptionsScreenshot = ExampleAssets.Banner,
|
||||
Icon = MiraAssets.CrewmateFile,
|
||||
IconTmp = TmpSpriteUtils.CreateSpriteAsset(
|
||||
MiraAssets.CrewmateFile.LoadAsset(),
|
||||
"ApiExample.Role.Impostor.ChameleonRole"),
|
||||
IntroSound = CustomRoleUtils.GetIntroSound(RoleTypes.Shapeshifter),
|
||||
};
|
||||
|
||||
public override void Initialize(PlayerControl player)
|
||||
public void PlayerControlFixedUpdate(PlayerControl playerControl)
|
||||
{
|
||||
Logger<ExamplePlugin>.Info("Initializing ChameleonRole for player: " + player.PlayerId);
|
||||
RoleBehaviourStubs.Initialize(this, player);
|
||||
shouldHide = true;
|
||||
}
|
||||
|
||||
public void FixedUpdate()
|
||||
{
|
||||
if (!Player || !shouldHide)
|
||||
if (playerControl.MyPhysics.Velocity.magnitude > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Player.MyPhysics.Velocity.magnitude > 0)
|
||||
{
|
||||
var rend = Player.cosmetics.currentBodySprite.BodySprite;
|
||||
var tmp = Player.cosmetics.nameText;
|
||||
var rend = playerControl.cosmetics.currentBodySprite.BodySprite;
|
||||
var tmp = playerControl.cosmetics.nameText;
|
||||
tmp.color = Color.Lerp(tmp.color, new Color(tmp.color.r, tmp.color.g, tmp.color.b, 1), Time.deltaTime * 4f);
|
||||
rend.color = Color.Lerp(rend.color, new Color(1, 1, 1, 1), Time.deltaTime * 4f);
|
||||
|
||||
foreach (var cosmetic in Player.cosmetics.transform.GetComponentsInChildren<SpriteRenderer>())
|
||||
foreach (var cosmetic in playerControl.cosmetics.transform.GetComponentsInChildren<SpriteRenderer>())
|
||||
{
|
||||
cosmetic.color = Color.Lerp(cosmetic.color, new Color(1, 1, 1, 1), Time.deltaTime * 4f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var rend = Player.cosmetics.currentBodySprite.BodySprite;
|
||||
var tmp = Player.cosmetics.nameText;
|
||||
tmp.color = Color.Lerp(
|
||||
tmp.color,
|
||||
new Color(tmp.color.r, tmp.color.g, tmp.color.b, Player.AmOwner ? 0.3f : 0),
|
||||
Time.deltaTime * 4f);
|
||||
rend.color = Color.Lerp(rend.color, new Color(1, 1, 1, Player.AmOwner ? 0.3f : 0), Time.deltaTime * 4f);
|
||||
var rend = playerControl.cosmetics.currentBodySprite.BodySprite;
|
||||
var tmp = playerControl.cosmetics.nameText;
|
||||
tmp.color = Color.Lerp(tmp.color, new Color(tmp.color.r, tmp.color.g, tmp.color.b, playerControl.AmOwner ? 0.3f : 0), Time.deltaTime * 4f);
|
||||
rend.color = Color.Lerp(rend.color, new Color(1, 1, 1, playerControl.AmOwner ? 0.3f : 0), Time.deltaTime * 4f);
|
||||
|
||||
foreach (var cosmetic in Player.cosmetics.transform.GetComponentsInChildren<SpriteRenderer>())
|
||||
foreach (var cosmetic in playerControl.cosmetics.transform.GetComponentsInChildren<SpriteRenderer>())
|
||||
{
|
||||
cosmetic.color = Color.Lerp(
|
||||
cosmetic.color,
|
||||
new Color(1, 1, 1, Player.AmOwner ? 0.3f : 0),
|
||||
Time.deltaTime * 4f);
|
||||
cosmetic.color = Color.Lerp(cosmetic.color, new Color(1, 1, 1, playerControl.AmOwner ? 0.3f : 0), Time.deltaTime * 4f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Deinitialize(PlayerControl targetPlayer)
|
||||
{
|
||||
Logger<ExamplePlugin>.Info("Deinitializing ChameleonRole for player: " + targetPlayer.PlayerId);
|
||||
RoleBehaviourStubs.Deinitialize(this, targetPlayer);
|
||||
shouldHide = false;
|
||||
foreach (var cosmetic in Player.cosmetics.transform.GetComponentsInChildren<SpriteRenderer>(true))
|
||||
{
|
||||
cosmetic.color = Color.white;
|
||||
}
|
||||
|
||||
Player.cosmetics.currentBodySprite.BodySprite.color = Color.white;
|
||||
Player.cosmetics.nameText.color = Color.white;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,19 @@
|
||||
using MiraAPI.Roles;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.Roles;
|
||||
|
||||
[RegisterCustomRole]
|
||||
public class FreezerRole : ImpostorRole, ICustomRole
|
||||
{
|
||||
public string IdPart => "Freezer";
|
||||
public string IdPrefix => "ApiExample.Role.Impostor";
|
||||
public string RoleName => "Freezer";
|
||||
public string RoleLongDescription => "Freeze another player for a duration of time.";
|
||||
public string RoleDescription => RoleLongDescription;
|
||||
public Color RoleColor => Palette.Blue;
|
||||
public ModdedRoleTeams Team => ModdedRoleTeams.Impostor;
|
||||
|
||||
public CustomRoleConfiguration Configuration => new(this)
|
||||
public CustomRoleConfiguration Configuration => new CustomRoleConfiguration(this)
|
||||
{
|
||||
Icon = MiraAssets.ImpostorFile,
|
||||
IconTmp = TmpSpriteUtils.CreateSpriteAsset(MiraAssets.ImpostorFile.LoadAsset(), "ApiExample.Role.Impostor.Freezer"),
|
||||
OptionsScreenshot = ExampleAssets.Banner,
|
||||
MaxRoleCount = 2,
|
||||
};
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
using MiraAPI.Roles;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.Roles;
|
||||
|
||||
public class MayorRole : CrewmateRole, ICustomRole
|
||||
{
|
||||
public string IdPart => "Mayor";
|
||||
public string IdPrefix => "ApiExample.Role.Crewmate";
|
||||
public Color RoleColor => new Color32(221, 176, 152, 255);
|
||||
public ModdedRoleTeams Team => ModdedRoleTeams.Crewmate;
|
||||
public CustomRoleConfiguration Configuration => new(this);
|
||||
}
|
||||
@@ -1,33 +1,24 @@
|
||||
using Il2CppInterop.Runtime.Attributes;
|
||||
using MiraAPI.Example.GameOver;
|
||||
using MiraAPI.GameEnd;
|
||||
using MiraAPI.Roles;
|
||||
using MiraAPI.Roles;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.Roles;
|
||||
|
||||
[RegisterCustomRole]
|
||||
public class NeutralKillerRole : ImpostorRole, ICustomRole
|
||||
{
|
||||
public string IdPart => "OutcastKiller";
|
||||
public string IdPrefix => "ApiExample.Role.Outcast";
|
||||
public string RoleName => "Neutral Killer";
|
||||
public string RoleDescription => "Neutral who can kill.";
|
||||
public string RoleLongDescription => RoleDescription;
|
||||
public Color RoleColor => Color.magenta;
|
||||
public ModdedRoleTeams Team => ModdedRoleTeams.Custom;
|
||||
public ModdedRoleTeams Team => ModdedRoleTeams.Neutral;
|
||||
|
||||
public CustomRoleConfiguration Configuration => new(this)
|
||||
public CustomRoleConfiguration Configuration => new CustomRoleConfiguration(this)
|
||||
{
|
||||
UseVanillaKillButton = true,
|
||||
CanGetKilled = true,
|
||||
CanUseVent = true,
|
||||
};
|
||||
|
||||
public RoleOptionsGroup RoleOptionsGroup { get; } = new("outcast.group", Color.gray);
|
||||
|
||||
[HideFromIl2Cpp]
|
||||
public TeamIntroConfiguration? IntroConfiguration { get; } = new(
|
||||
Color.gray,
|
||||
"outcast.roleTitle",
|
||||
"outcast.teamIntroDescription");
|
||||
|
||||
public override void SpawnTaskHeader(PlayerControl playerControl)
|
||||
{
|
||||
// remove existing task header.
|
||||
@@ -35,6 +26,6 @@ public class NeutralKillerRole : ImpostorRole, ICustomRole
|
||||
|
||||
public override bool DidWin(GameOverReason gameOverReason)
|
||||
{
|
||||
return gameOverReason == CustomGameOver.GameOverReason<NeutralKillerGameOver>();
|
||||
return GameManager.Instance.DidHumansWin(gameOverReason);
|
||||
}
|
||||
}
|
||||
@@ -3,23 +3,20 @@ using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.Roles;
|
||||
|
||||
[RegisterCustomRole]
|
||||
public class TeleporterRole : CrewmateRole, ICustomRole
|
||||
{
|
||||
public string IdPart => "Teleporter";
|
||||
public string IdPrefix => "ApiExample.Role.Crewmate";
|
||||
public string RoleName => "Teleporter";
|
||||
public string RoleLongDescription => "Zoom out and teleport across the map!";
|
||||
public string RoleDescription => RoleLongDescription;
|
||||
public Color RoleColor => new Color32(221, 176, 152, 255);
|
||||
public ModdedRoleTeams Team => ModdedRoleTeams.Crewmate;
|
||||
|
||||
public CustomRoleConfiguration Configuration => new(this)
|
||||
public CustomRoleConfiguration Configuration => new CustomRoleConfiguration(this)
|
||||
{
|
||||
OptionsScreenshot = ExampleAssets.Banner,
|
||||
CanModifyChance = false,
|
||||
DefaultChance = 73,
|
||||
DefaultRoleCount = 4,
|
||||
};
|
||||
|
||||
public bool CanLocalPlayerSeeRole(PlayerControl player)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using MiraAPI.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Colors.ColorSpaces;
|
||||
|
||||
/// <summary>
|
||||
/// A struct that denotes the CMYK (Cyan, Magenta, Yellow, Key) color space.
|
||||
/// </summary>
|
||||
/// <param name="c">The cyan component.</param>
|
||||
/// <param name="m">The magenta component.</param>
|
||||
/// <param name="y">The yellow component.</param>
|
||||
/// <param name="k">The key component.</param>
|
||||
/// <param name="a">The alpha component.</param>
|
||||
[Serializable]
|
||||
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "Unity parity.")]
|
||||
public record struct CmykColor(float c, float m, float y, float k, float a = 1f)
|
||||
{
|
||||
/// <summary>
|
||||
/// Implicitly converts a <see cref="CmykColor"/> to a Unity <see cref="Color"/>.
|
||||
/// </summary>
|
||||
/// <param name="c">The color being converted.</param>
|
||||
public static implicit operator Color(CmykColor c)
|
||||
{
|
||||
return ToColor(c);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicitly converts a Unity <see cref="Color"/> to a <see cref="CmykColor"/>.
|
||||
/// </summary>
|
||||
/// <param name="c">The color being converted.</param>
|
||||
public static implicit operator CmykColor(Color c)
|
||||
{
|
||||
return FromColor(c);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="CmykColor"/> to a standard Unity RGB <see cref="Color"/>.
|
||||
/// </summary>
|
||||
/// <param name="cmyk">The CMYK color to convert.</param>
|
||||
/// <returns>A Unity <see cref="Color"/> representing the same visual color.</returns>
|
||||
public static Color ToColor(CmykColor cmyk)
|
||||
{
|
||||
var key = 1f - cmyk.k;
|
||||
|
||||
var r = (1f - cmyk.c) * key;
|
||||
var g = (1f - cmyk.m) * key;
|
||||
var b = (1f - cmyk.y) * key;
|
||||
|
||||
return new Color(MathUtilities.Clamp01(r), MathUtilities.Clamp01(g), MathUtilities.Clamp01(b), cmyk.a);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a standard Unity RGB <see cref="Color"/> to a <see cref="CmykColor"/>.
|
||||
/// </summary>
|
||||
/// <param name="color">The Unity Color to convert.</param>
|
||||
/// <returns>A <see cref="CmykColor"/> representing the same visual color.</returns>
|
||||
public static CmykColor FromColor(Color color)
|
||||
{
|
||||
var r = color.r;
|
||||
var g = color.g;
|
||||
var b = color.b;
|
||||
|
||||
var k = 1f - MathF.Max(r, MathF.Max(g, b));
|
||||
|
||||
if (k >= 1f)
|
||||
return new CmykColor(0f, 0f, 0f, 1f, color.a);
|
||||
|
||||
var invK = 1f / (1f - k);
|
||||
|
||||
var c = (1f - r - k) * invK;
|
||||
var m = (1f - g - k) * invK;
|
||||
var y = (1f - b - k) * invK;
|
||||
|
||||
return new CmykColor(MathUtilities.Clamp01(c), MathUtilities.Clamp01(m), MathUtilities.Clamp01(y), MathUtilities.Clamp01(k), color.a);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Linearly interpolates between two <see cref="CmykColor"/> values.
|
||||
/// </summary>
|
||||
/// <param name="a">The starting color.</param>
|
||||
/// <param name="b">The ending color.</param>
|
||||
/// <param name="t">The interpolation value between the two colors, clamped to a 0 to 1 range.</param>
|
||||
/// <returns>The interpolated <see cref="CmykColor"/>.</returns>
|
||||
public static CmykColor Lerp(CmykColor a, CmykColor b, float t)
|
||||
{
|
||||
return LerpUnclamped(a, b, MathUtilities.Clamp01(t));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Linearly interpolates between two <see cref="CmykColor"/> values without clamping the interpolant.
|
||||
/// </summary>
|
||||
/// <param name="a">The starting color.</param>
|
||||
/// <param name="b">The ending color.</param>
|
||||
/// <param name="t">The interpolation value between the two colors.</param>
|
||||
/// <returns>The interpolated <see cref="CmykColor"/>.</returns>
|
||||
public static CmykColor LerpUnclamped(CmykColor a, CmykColor b, float t)
|
||||
{
|
||||
return new CmykColor(
|
||||
MathUtilities.LerpUnclamped(a.c, b.c, t),
|
||||
MathUtilities.LerpUnclamped(a.m, b.m, t),
|
||||
MathUtilities.LerpUnclamped(a.y, b.y, t),
|
||||
MathUtilities.LerpUnclamped(a.k, b.k, t),
|
||||
MathUtilities.LerpUnclamped(a.a, b.a, t));
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using MiraAPI.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Colors.ColorSpaces;
|
||||
|
||||
/// <summary>
|
||||
/// A struct that denotes the HSB (Hue, Saturation, Brightness) color space.
|
||||
/// </summary>
|
||||
/// <param name="h">The hue component.</param>
|
||||
/// <param name="s">The saturation component.</param>
|
||||
/// <param name="b">The brightness component.</param>
|
||||
/// <param name="a">The alpha component.</param>
|
||||
[Serializable]
|
||||
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "Unity parity.")]
|
||||
public record struct HsbColor(float h, float s, float b, float a = 1f)
|
||||
{
|
||||
/// <summary>
|
||||
/// Implicitly converts an <see cref="HsbColor"/> to a Unity <see cref="Color"/>.
|
||||
/// </summary>
|
||||
/// <param name="c">The color being converted.</param>
|
||||
public static implicit operator Color(HsbColor c)
|
||||
{
|
||||
return ToColor(c);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicitly converts a Unity <see cref="Color"/> to an <see cref="HsbColor"/>.
|
||||
/// </summary>
|
||||
/// <param name="c">The color being converted.</param>
|
||||
public static implicit operator HsbColor(Color c)
|
||||
{
|
||||
return FromColor(c);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an <see cref="HsbColor"/> to a standard Unity RGB <see cref="Color"/>.
|
||||
/// </summary>
|
||||
/// <param name="hsb">The HSB color to convert.</param>
|
||||
/// <returns>A Unity <see cref="Color"/> representing the same visual color.</returns>
|
||||
public static Color ToColor(HsbColor hsb)
|
||||
{
|
||||
if (hsb.s <= float.Epsilon)
|
||||
return new Color(MathUtilities.Clamp01(hsb.b), MathUtilities.Clamp01(hsb.b), MathUtilities.Clamp01(hsb.b), hsb.a);
|
||||
|
||||
var c = hsb.b * hsb.s;
|
||||
var hPrime = hsb.h * 6f;
|
||||
var x = c * (1f - MathF.Abs((hPrime % 2f) - 1f));
|
||||
var m = hsb.b - c;
|
||||
|
||||
var (r, g, b) = hPrime switch
|
||||
{
|
||||
< 1f => (c, x, 0f),
|
||||
< 2f => (x, c, 0f),
|
||||
< 3f => (0f, c, x),
|
||||
< 4f => (0f, x, c),
|
||||
< 5f => (x, 0f, c),
|
||||
<= 6f => (c, 0f, x),
|
||||
_ => (0f, 0f, 0f),
|
||||
};
|
||||
|
||||
return new Color(
|
||||
MathUtilities.Clamp01(r + m),
|
||||
MathUtilities.Clamp01(g + m),
|
||||
MathUtilities.Clamp01(b + m),
|
||||
hsb.a);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a standard Unity RGB <see cref="Color"/> to an <see cref="HsbColor"/>.
|
||||
/// </summary>
|
||||
/// <param name="color">The Unity Color to convert.</param>
|
||||
/// <returns>An <see cref="HsbColor"/> representing the same visual color.</returns>
|
||||
public static HsbColor FromColor(Color color)
|
||||
{
|
||||
var max = MathF.Max(color.r, MathF.Max(color.g, color.b));
|
||||
var min = MathF.Min(color.r, MathF.Min(color.g, color.b));
|
||||
var delta = max - min;
|
||||
|
||||
var h = 0f;
|
||||
|
||||
if (delta > 0f)
|
||||
{
|
||||
if (max == color.r)
|
||||
h = (color.g - color.b) / delta % 6f;
|
||||
else if (max == color.g)
|
||||
h = (color.b - color.r) / delta + 2f;
|
||||
else
|
||||
h = (color.r - color.g) / delta + 4f;
|
||||
|
||||
h /= 6f;
|
||||
|
||||
if (h < 0f)
|
||||
h += 1f;
|
||||
}
|
||||
|
||||
var s = max == 0f ? 0f : delta / max;
|
||||
var b = max;
|
||||
|
||||
return new HsbColor(h, s, b, color.a);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Linearly interpolates between two <see cref="HsbColor"/> values, using the shortest path for the hue.
|
||||
/// </summary>
|
||||
/// <param name="a">The starting color.</param>
|
||||
/// <param name="b">The ending color.</param>
|
||||
/// <param name="t">The interpolation value between the two colors, clamped to a 0 to 1 range.</param>
|
||||
/// <returns>The interpolated <see cref="HsbColor"/>.</returns>
|
||||
public static HsbColor Lerp(HsbColor a, HsbColor b, float t)
|
||||
{
|
||||
return LerpUnclamped(a, b, MathUtilities.Clamp01(t));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Linearly interpolates between two <see cref="HsbColor"/> values without clamping the interpolant.
|
||||
/// </summary>
|
||||
/// <param name="a">The starting color.</param>
|
||||
/// <param name="b">The ending color.</param>
|
||||
/// <param name="t">The interpolation value between the two colors.</param>
|
||||
/// <returns>The interpolated <see cref="HsbColor"/>.</returns>
|
||||
public static HsbColor LerpUnclamped(HsbColor a, HsbColor b, float t)
|
||||
{
|
||||
var hueDifference = MathUtilities.Repeat(b.h - a.h, 1f);
|
||||
|
||||
if (hueDifference > 0.5f)
|
||||
hueDifference -= 1f;
|
||||
|
||||
return new HsbColor(
|
||||
MathUtilities.Repeat(a.h + (hueDifference * t), 1f),
|
||||
MathUtilities.LerpUnclamped(a.s, b.s, t),
|
||||
MathUtilities.LerpUnclamped(a.b, b.b, t),
|
||||
MathUtilities.LerpUnclamped(a.a, b.a, t));
|
||||
}
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using MiraAPI.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Colors.ColorSpaces;
|
||||
|
||||
/// <summary>
|
||||
/// A struct that denotes the HSL (Hue, Saturation, Lightness) color space.
|
||||
/// </summary>
|
||||
/// <param name="h">The hue component.</param>
|
||||
/// <param name="s">The saturation component.</param>
|
||||
/// <param name="l">The lightness component.</param>
|
||||
/// <param name="a">The alpha component.</param>
|
||||
[Serializable]
|
||||
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "Unity parity.")]
|
||||
public record struct HslColor(float h, float s, float l, float a = 1f)
|
||||
{
|
||||
/// <summary>
|
||||
/// Implicitly converts an <see cref="HslColor"/> to a Unity <see cref="Color"/>.
|
||||
/// </summary>
|
||||
/// <param name="c">The color being converted.</param>
|
||||
public static implicit operator Color(HslColor c)
|
||||
{
|
||||
return ToColor(c);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicitly converts a Unity <see cref="Color"/> to an <see cref="HslColor"/>.
|
||||
/// </summary>
|
||||
/// <param name="c">The color being converted.</param>
|
||||
public static implicit operator HslColor(Color c)
|
||||
{
|
||||
return FromColor(c);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an <see cref="HslColor"/> to a standard Unity RGB <see cref="Color"/>.
|
||||
/// </summary>
|
||||
/// <param name="hsl">The HSL color to convert.</param>
|
||||
/// <returns>A Unity <see cref="Color"/> representing the same visual color.</returns>
|
||||
public static Color ToColor(HslColor hsl)
|
||||
{
|
||||
if (hsl.s <= float.Epsilon)
|
||||
return new Color(MathUtilities.Clamp01(hsl.l), MathUtilities.Clamp01(hsl.l), MathUtilities.Clamp01(hsl.l), hsl.a);
|
||||
|
||||
var c = (1f - MathF.Abs(2f * hsl.l - 1f)) * hsl.s;
|
||||
var hPrime = hsl.h * 6f;
|
||||
var x = c * (1f - MathF.Abs((hPrime % 2f) - 1f));
|
||||
var m = hsl.l - c / 2f;
|
||||
|
||||
var (r, g, b) = hPrime switch
|
||||
{
|
||||
< 1f => (c, x, 0f),
|
||||
< 2f => (x, c, 0f),
|
||||
< 3f => (0f, c, x),
|
||||
< 4f => (0f, x, c),
|
||||
< 5f => (x, 0f, c),
|
||||
<= 6f => (c, 0f, x),
|
||||
_ => (0f, 0f, 0f),
|
||||
};
|
||||
|
||||
return new Color(MathUtilities.Clamp01(r + m), MathUtilities.Clamp01(g + m), MathUtilities.Clamp01(b + m), hsl.a);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a standard Unity RGB <see cref="Color"/> to an <see cref="HslColor"/>.
|
||||
/// </summary>
|
||||
/// <param name="color">The Unity Color to convert.</param>
|
||||
/// <returns>An <see cref="HslColor"/> representing the same visual color.</returns>
|
||||
public static HslColor FromColor(Color color)
|
||||
{
|
||||
var max = MathF.Max(color.r, MathF.Max(color.g, color.b));
|
||||
var min = MathF.Min(color.r, MathF.Min(color.g, color.b));
|
||||
var l = (max + min) / 2f;
|
||||
var delta = max - min;
|
||||
|
||||
var s = delta == 0f ? 0f : delta / (1f - MathF.Abs((2f * l) - 1f));
|
||||
|
||||
var h = 0f;
|
||||
|
||||
if (delta > 0f)
|
||||
{
|
||||
if (max == color.r)
|
||||
h = (color.g - color.b) / delta % 6f;
|
||||
else if (max == color.g)
|
||||
h = (color.b - color.r) / delta + 2f;
|
||||
else
|
||||
h = (color.r - color.g) / delta + 4f;
|
||||
|
||||
h /= 6f;
|
||||
|
||||
if (h < 0f)
|
||||
h += 1f;
|
||||
}
|
||||
|
||||
return new HslColor(h, s, l, color.a);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Linearly interpolates between two <see cref="HslColor"/> values, using the shortest path for the hue.
|
||||
/// </summary>
|
||||
/// <param name="a">The starting color.</param>
|
||||
/// <param name="b">The ending color.</param>
|
||||
/// <param name="t">The interpolation value between the two colors, clamped to a 0 to 1 range.</param>
|
||||
/// <returns>The interpolated <see cref="HslColor"/>.</returns>
|
||||
public static HslColor Lerp(HslColor a, HslColor b, float t)
|
||||
{
|
||||
return LerpUnclamped(a, b, MathUtilities.Clamp01(t));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Linearly interpolates between two <see cref="HslColor"/> values without clamping the interpolant.
|
||||
/// </summary>
|
||||
/// <param name="a">The starting color.</param>
|
||||
/// <param name="b">The ending color.</param>
|
||||
/// <param name="t">The interpolation value between the two colors.</param>
|
||||
/// <returns>The interpolated <see cref="HslColor"/>.</returns>
|
||||
public static HslColor LerpUnclamped(HslColor a, HslColor b, float t)
|
||||
{
|
||||
var hueDifference = MathUtilities.Repeat(b.h - a.h, 1f);
|
||||
|
||||
if (hueDifference > 0.5f)
|
||||
hueDifference -= 1f;
|
||||
|
||||
return new HslColor(
|
||||
MathUtilities.Repeat(a.h + (hueDifference * t), 1f),
|
||||
MathUtilities.LerpUnclamped(a.s, b.s, t),
|
||||
MathUtilities.LerpUnclamped(a.l, b.l, t),
|
||||
MathUtilities.LerpUnclamped(a.a, b.a, t));
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using MiraAPI.Translation;
|
||||
using MiraAPI.Utilities;
|
||||
using MiraAPI.Utilities;
|
||||
using Reactor.Localization.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Colors;
|
||||
@@ -11,87 +10,35 @@ namespace MiraAPI.Colors;
|
||||
/// <param name="name">The name of the option.</param>
|
||||
/// <param name="mainColor">The main color.</param>
|
||||
/// <param name="shadowColor">The shadow color.</param>
|
||||
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Internal code.")]
|
||||
[SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1513:Closing brace should be followed by blank line", Justification = "Looks weird.")]
|
||||
public class CustomColor(StringNames name, Color32 mainColor, Color32 shadowColor)
|
||||
public sealed class CustomColor(StringNames name, Color32 mainColor, Color32 shadowColor)
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the main color.
|
||||
/// Gets the main color.
|
||||
/// </summary>
|
||||
public Color32 MainColor
|
||||
{
|
||||
get;
|
||||
set
|
||||
{
|
||||
field = value;
|
||||
InternalMainColor = value;
|
||||
}
|
||||
}
|
||||
= mainColor;
|
||||
public Color32 MainColor { get; } = mainColor;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the shadow color.
|
||||
/// Gets the shadow color.
|
||||
/// </summary>
|
||||
public Color32 ShadowColor
|
||||
{
|
||||
get;
|
||||
set
|
||||
{
|
||||
field = value;
|
||||
InternalShadowColor = value;
|
||||
}
|
||||
}
|
||||
= shadowColor;
|
||||
public Color32 ShadowColor { get; } = shadowColor;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the color.
|
||||
/// Gets the name of the color.
|
||||
/// </summary>
|
||||
public StringNames Name { get; set; } = name;
|
||||
public StringNames Name { get; } = name;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether the color is lighter or darker. Can be used to help with colorblind stuff.
|
||||
/// </summary>
|
||||
public CustomColorBrightness ColorBrightness { get; set; } = CustomColorBrightness.Darker;
|
||||
|
||||
internal Color InternalMainColor = mainColor;
|
||||
internal Color InternalShadowColor = shadowColor;
|
||||
|
||||
/// <inheritdoc cref="CustomColor"/>
|
||||
public CustomColor(StringNames name, Color32 mainColor)
|
||||
: this(name, mainColor, mainColor.GetShadowColor(60))
|
||||
/// <inheritdoc />
|
||||
public CustomColor(StringNames name, Color32 mainColor) : this(name, mainColor, mainColor.GetShadowColor(60))
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="CustomColor"/>
|
||||
public CustomColor(string name, Color32 mainColor)
|
||||
: this(name, mainColor, mainColor.GetShadowColor(60))
|
||||
/// <inheritdoc />
|
||||
public CustomColor(string name, Color32 mainColor) : this(name, mainColor, mainColor.GetShadowColor(60))
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="CustomColor"/>
|
||||
public CustomColor(string name, Color32 mainColor, Color32 shadowColor)
|
||||
: this(MiraLocaleManager.GetOrCreateLocaleString(name), mainColor, shadowColor)
|
||||
/// <inheritdoc />
|
||||
public CustomColor(string name, Color32 mainColor, Color32 shadowColor) : this(CustomStringName.CreateAndRegister(name), mainColor, shadowColor)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Can be used to help with colorblind stuff.
|
||||
/// </summary>
|
||||
public enum CustomColorBrightness
|
||||
{
|
||||
/// <summary>
|
||||
/// An invalid color.
|
||||
/// </summary>
|
||||
Invalid = -1,
|
||||
|
||||
/// <summary>
|
||||
/// A lighter color.
|
||||
/// </summary>
|
||||
Lighter,
|
||||
|
||||
/// <summary>
|
||||
/// A darker color.
|
||||
/// </summary>
|
||||
Darker,
|
||||
}
|
||||
@@ -1,52 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Colors;
|
||||
|
||||
/// <summary>
|
||||
/// Used to register and track <see cref="CustomColor"/>s.
|
||||
/// Used to register and track custom colors.
|
||||
/// </summary>
|
||||
public static class PaletteManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets all registered <see cref="CustomColor"/>s.
|
||||
/// Gets all registered custom colors.
|
||||
/// </summary>
|
||||
public static CustomColor[] RegisteredColors => [.. CustomColors];
|
||||
|
||||
internal static readonly List<CustomColor> CustomColors = [];
|
||||
internal static readonly HashSet<StringNames> VariableColorNames = [];
|
||||
|
||||
private static readonly CustomColorBrightness[] ColorBrightnessMap =
|
||||
[
|
||||
CustomColorBrightness.Darker, // Red
|
||||
CustomColorBrightness.Darker, // Blue
|
||||
CustomColorBrightness.Darker, // Green
|
||||
CustomColorBrightness.Lighter, // Pink
|
||||
CustomColorBrightness.Lighter, // Orange
|
||||
CustomColorBrightness.Lighter, // Yellow
|
||||
CustomColorBrightness.Darker, // Black
|
||||
CustomColorBrightness.Lighter, // White
|
||||
CustomColorBrightness.Darker, // Purple
|
||||
CustomColorBrightness.Darker, // Brown
|
||||
CustomColorBrightness.Lighter, // Cyan
|
||||
CustomColorBrightness.Lighter, // Lime
|
||||
CustomColorBrightness.Darker, // Maroon
|
||||
CustomColorBrightness.Lighter, // Rose
|
||||
CustomColorBrightness.Lighter, // Banana
|
||||
CustomColorBrightness.Darker, // Gray
|
||||
CustomColorBrightness.Darker, // Tan
|
||||
CustomColorBrightness.Lighter, // Coral
|
||||
];
|
||||
|
||||
private static int originalLength;
|
||||
|
||||
internal static void RegisterAllColors()
|
||||
{
|
||||
originalLength = Palette.PlayerColors.Length;
|
||||
|
||||
var colors = CustomColors.Select(x => x.MainColor).ToArray();
|
||||
var shadowColors = CustomColors.Select(x => x.ShadowColor).ToArray();
|
||||
var stringNames = CustomColors.Select(x => x.Name).ToArray();
|
||||
@@ -58,90 +29,4 @@ public static class PaletteManager
|
||||
Palette.TextColors = Palette.TextColors.ToArray().AddRangeToArray(colors);
|
||||
Palette.TextOutlineColors = Palette.TextOutlineColors.ToArray().AddRangeToArray(shadowColors);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks to see if the provided color ID belongs to a variable color.
|
||||
/// </summary>
|
||||
/// <param name="colorId">The id of the color.</param>
|
||||
/// <returns><c>true</c> if the color is a variable color; <c>false</c> otherwise.</returns>
|
||||
public static bool IsVariable(int colorId)
|
||||
{
|
||||
if ((uint)colorId >= (uint)Palette.ColorNames.Length)
|
||||
return false;
|
||||
|
||||
return VariableColorNames.Contains(Palette.ColorNames[colorId]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks to see if the provided color ID belongs to a custom color.
|
||||
/// </summary>
|
||||
/// <param name="colorId">The ID of the color.</param>
|
||||
/// <returns><c>true</c> if the color is a custom color; <c>false</c> otherwise.</returns>
|
||||
public static bool IsCustomColor(int colorId)
|
||||
{
|
||||
return (uint)(colorId - originalLength) < (uint)CustomColors.Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the main color of the provided color ID.
|
||||
/// </summary>
|
||||
/// <param name="colorId">The id of the color.</param>
|
||||
/// <returns>The main color associated with the provided ID.</returns>
|
||||
public static Color GetMainColor(int colorId)
|
||||
{
|
||||
if ((uint)colorId >= (uint)Palette.ColorNames.Length)
|
||||
return Color.white;
|
||||
|
||||
return !TryGetCustomColor(colorId, out var custom)
|
||||
? Palette.PlayerColors[colorId]
|
||||
: (custom is VariableColor variable
|
||||
? variable.EvaluateMainColor(Time.time)
|
||||
: custom.InternalMainColor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the shadow color of the provided color ID.
|
||||
/// </summary>
|
||||
/// <param name="colorId">The ID of the color.</param>
|
||||
/// <returns>The shadow color associated with the provided ID.</returns>
|
||||
public static Color GetShadowColor(int colorId)
|
||||
{
|
||||
if ((uint)colorId >= (uint)Palette.ColorNames.Length)
|
||||
return Color.white;
|
||||
|
||||
return !TryGetCustomColor(colorId, out var custom)
|
||||
? Palette.ShadowColors[colorId]
|
||||
: (custom is VariableColor variable
|
||||
? variable.EvaluateShadowColor(Time.time)
|
||||
: custom.InternalShadowColor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the brightness type of the color associated with the provided ID.
|
||||
/// </summary>
|
||||
/// <param name="colorId">The ID of the color.</param>
|
||||
/// <returns>The brightness type of the provided ID.</returns>
|
||||
public static CustomColorBrightness GetBrightness(int colorId)
|
||||
{
|
||||
if ((uint)colorId >= (uint)Palette.ColorNames.Length)
|
||||
return CustomColorBrightness.Invalid;
|
||||
|
||||
return TryGetCustomColor(colorId, out var custom)
|
||||
? custom.ColorBrightness
|
||||
: ColorBrightnessMap[colorId];
|
||||
}
|
||||
|
||||
internal static bool TryGetCustomColor(int colorId, [NotNullWhen(true)] out CustomColor? custom)
|
||||
{
|
||||
var index = colorId - originalLength;
|
||||
|
||||
if ((uint)index >= (uint)CustomColors.Count)
|
||||
{
|
||||
custom = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
custom = CustomColors[index];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace MiraAPI.Colors;
|
||||
|
||||
/// <summary>
|
||||
/// Used to mark a class for <see cref="CustomColor"/> registration.
|
||||
/// Used to mark a class for custom colors registration.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class RegisterCustomColorsAttribute : Attribute;
|
||||
@@ -1,72 +0,0 @@
|
||||
using System;
|
||||
using MiraAPI.LocalSettings;
|
||||
using MiraAPI.Translation;
|
||||
using MiraAPI.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Colors;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a dynamic custom color that changes over time.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the color.</param>
|
||||
/// <param name="mainEvaluator">The function to evaluate the dynamic main color.</param>
|
||||
/// <param name="shadowEvaluator">The function to evaluate the dynamic shadow color.</param>
|
||||
/// <param name="mainColor">The static main color used when dynamic colors are disabled.</param>
|
||||
/// <param name="shadowColor">The static shadow color used when dynamic colors are disabled.</param>
|
||||
/// <param name="defaultTime">The default time that is used to automatically fill in the static colors when the latter is not provided.</param>
|
||||
public sealed class VariableColor(StringNames name, Func<float, Color> mainEvaluator, Func<float, Color>? shadowEvaluator, Color32? mainColor = null, Color32? shadowColor = null, float defaultTime = 0f)
|
||||
: CustomColor(name, mainColor ?? mainEvaluator(defaultTime), shadowColor ?? shadowEvaluator?.Invoke(defaultTime) ?? (mainColor ?? mainEvaluator(defaultTime)).GetShadowColor(60))
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a delegate that takes in a time value and returns the dynamic main color.
|
||||
/// </summary>
|
||||
public Func<float, Color> MainEvaluator { get; set; } = mainEvaluator;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a delegate that takes in a time value and returns the dynamic shadow color.
|
||||
/// </summary>
|
||||
public Func<float, Color> ShadowEvaluator { get; set; } = shadowEvaluator ?? (t => mainEvaluator(t).GetShadowColor(0.24f));
|
||||
|
||||
/// <inheritdoc cref="VariableColor"/>
|
||||
public VariableColor(StringNames name, Func<float, Color> mainEvaluator, Color32? mainColor = null, float defaultTime = 0f)
|
||||
: this(name, mainEvaluator, null, mainColor, null, defaultTime)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="VariableColor"/>
|
||||
public VariableColor(string name, Func<float, Color> mainEvaluator, Color32? mainColor = null, float defaultTime = 0f)
|
||||
: this(name, mainEvaluator, null, mainColor, null, defaultTime)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="VariableColor"/>
|
||||
public VariableColor(string name, Func<float, Color> mainEvaluator, Func<float, Color>? shadowEvaluator, Color32? mainColor = null, Color32? shadowColor = null, float defaultTime = 0f)
|
||||
: this(MiraLocaleManager.GetOrCreateLocaleString(name), mainEvaluator, shadowEvaluator, mainColor, shadowColor, defaultTime)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates the dynamic main color based on the provided time value.
|
||||
/// </summary>
|
||||
/// <param name="time">The time to evaluate the color against.</param>
|
||||
/// <returns>The dynamically evaluated color, or the static <see cref="CustomColor.MainColor"/> if static variable colors are enabled in the user's settings.</returns>
|
||||
public Color EvaluateMainColor(float time)
|
||||
{
|
||||
return LocalSettingsTabSingleton<MiraApiSettings>.Instance.EnableVariableColors.Value
|
||||
? MainEvaluator(time)
|
||||
: InternalMainColor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates the dynamic shadow color based on the provided time value.
|
||||
/// </summary>
|
||||
/// <param name="time">The time to evaluate the color against.</param>
|
||||
/// <returns>The dynamically evaluated color, or the static <see cref="CustomColor.ShadowColor"/> if static variable colors are enabled in the user's settings.</returns>
|
||||
public Color EvaluateShadowColor(float time)
|
||||
{
|
||||
return LocalSettingsTabSingleton<MiraApiSettings>.Instance.EnableVariableColors.Value
|
||||
? ShadowEvaluator(time)
|
||||
: InternalShadowColor;
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Il2CppInterop.Runtime.Attributes;
|
||||
using MiraAPI.Colors;
|
||||
using MiraAPI.Utilities;
|
||||
using Reactor.Utilities.Attributes;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI;
|
||||
|
||||
/// <summary>
|
||||
/// The base class for variable color behaviour on <see cref="SpriteRenderer"/>s.
|
||||
/// </summary>
|
||||
[SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity methods.")]
|
||||
[SuppressMessage("Design", "CA1051:Do not declare visible instance fields", Justification = "Unity fields.")]
|
||||
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Read above.")]
|
||||
public abstract class BaseVariableColorBehaviour : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="VariableColor"/> to apply.
|
||||
/// </summary>
|
||||
protected VariableColor? color;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current variable color.
|
||||
/// </summary>
|
||||
/// <param name="newColor">The new <see cref="VariableColor"/>.</param>
|
||||
[HideFromIl2Cpp]
|
||||
public void SetColor(VariableColor? newColor)
|
||||
{
|
||||
color = newColor;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A mono script that adjusts the material colors of a <see cref="Renderer"/> component that it's attached to based on the provided variable color.
|
||||
/// </summary>
|
||||
[RegisterInIl2Cpp]
|
||||
[SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity methods.")]
|
||||
public sealed class VariableColorBehaviour : BaseVariableColorBehaviour
|
||||
{
|
||||
private Renderer? rend;
|
||||
|
||||
private static readonly Color VisorColor = Palette.VisorColor;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the new <see cref="Renderer"/> target.
|
||||
/// </summary>
|
||||
/// <param name="newRend">The new <see cref="Renderer"/> that the script must target.</param>
|
||||
public void SetRend(Renderer? newRend)
|
||||
{
|
||||
rend = newRend;
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
rend = GetComponent<Renderer>();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (color == null || rend == null)
|
||||
return;
|
||||
|
||||
var time = Time.time;
|
||||
var material = rend.material;
|
||||
|
||||
material.SetColor(ShaderID.VisorColor, VisorColor);
|
||||
|
||||
material.SetColor(ShaderID.BodyColor, color.EvaluateMainColor(time));
|
||||
material.SetColor(ShaderID.BackColor, color.EvaluateShadowColor(time));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A mono script that adjusts the graphic colors of a <see cref="SpriteRenderer"/> component that it's attached to based on the provided variable color.
|
||||
/// </summary>
|
||||
[RegisterInIl2Cpp]
|
||||
[SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity methods.")]
|
||||
public sealed class BasicVariableColorBehaviour : BaseVariableColorBehaviour
|
||||
{
|
||||
private SpriteRenderer? rend;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the new <see cref="SpriteRenderer"/> target.
|
||||
/// </summary>
|
||||
/// <param name="newRend">The new <see cref="SpriteRenderer"/> that the script must target.</param>
|
||||
public void SetRend(SpriteRenderer? newRend)
|
||||
{
|
||||
rend = newRend;
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
rend = GetComponent<SpriteRenderer>();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (color != null && rend != null)
|
||||
rend.color = color.EvaluateMainColor(Time.time);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MiraAPI.Cosmetics;
|
||||
public abstract class AbstractCosmeticsGroup
|
||||
{
|
||||
public List<HatData> Hats { get; } = [];
|
||||
public List<SkinData> Skins { get; } = [];
|
||||
public List<VisorData> Visors { get; } = [];
|
||||
public List<NamePlateData> Nameplates { get; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the group. Visible in options menu.
|
||||
/// </summary>
|
||||
public abstract string GroupName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a function that determines whether the group should be visible or not.
|
||||
/// </summary>
|
||||
public virtual Func<bool> GroupVisible => () => true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sorting mode of individual hats within this group.
|
||||
/// </summary>
|
||||
public virtual SortingMode SortingMode => SortingMode.AlphabeticName;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the priority of a group for sorting groups.
|
||||
/// </summary>
|
||||
public virtual int SortingPriority { get; }
|
||||
}
|
||||
|
||||
public enum SortingMode
|
||||
{
|
||||
Priority,
|
||||
AlphabeticProductId,
|
||||
AlphabeticStoreName,
|
||||
AlphabeticName,
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MiraAPI.Cosmetics;
|
||||
internal sealed class AbstractCosmeticsGroupComparer : Comparer<AbstractCosmeticsGroup>
|
||||
{
|
||||
public override int Compare(AbstractCosmeticsGroup? x, AbstractCosmeticsGroup? y)
|
||||
{
|
||||
switch (x)
|
||||
{
|
||||
case not null when y is null:
|
||||
return 1;
|
||||
case null when y is null:
|
||||
return 0;
|
||||
case null:
|
||||
return -1;
|
||||
}
|
||||
|
||||
var p = x.SortingPriority - y.SortingPriority;
|
||||
return p == 0 ? StringComparer.InvariantCultureIgnoreCase.Compare(x.GroupName, y.GroupName) : p;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace MiraAPI.Cosmetics;
|
||||
internal sealed class CosmeticComparer(AbstractCosmeticsGroup group) : Comparer<CosmeticData>
|
||||
{
|
||||
internal static readonly string[] NoCosmetics = ["hat_NoHat", "skin_None", "nameplate_NoPlate", "visor_EmptyVisor"];
|
||||
public override int Compare(CosmeticData? x, CosmeticData? y)
|
||||
{
|
||||
if (NoCosmetics.Contains(x?.ProdId))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (NoCosmetics.Contains(y?.ProdId))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return group.SortingMode switch
|
||||
{
|
||||
SortingMode.AlphabeticProductId => StringComparer.InvariantCultureIgnoreCase.Compare(x?.ProductId, y?.ProductId),
|
||||
SortingMode.Priority => CustomCosmeticManager.CosmeticToPriority[x!] - CustomCosmeticManager.CosmeticToPriority[y!],
|
||||
SortingMode.AlphabeticStoreName => x switch
|
||||
{
|
||||
HatData h1 when y is HatData h2 => StringComparer.InvariantCultureIgnoreCase.Compare(
|
||||
h1.StoreName,
|
||||
h2.StoreName),
|
||||
SkinData s1 when y is SkinData s2 => StringComparer.InvariantCultureIgnoreCase.Compare(
|
||||
s1.StoreName,
|
||||
s2.StoreName),
|
||||
_ => StringComparer.InvariantCultureIgnoreCase.Compare(x?.GetItemName(), y?.GetItemName()),
|
||||
},
|
||||
_ => StringComparer.InvariantCultureIgnoreCase.Compare(x?.GetItemName(), y?.GetItemName()),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Linq;
|
||||
|
||||
namespace MiraAPI.Cosmetics;
|
||||
|
||||
/// <summary>
|
||||
/// Used to get access to a CosmeticGroup.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type.</typeparam>
|
||||
public static class CosmeticGroupSingleton<T> where T : AbstractCosmeticsGroup
|
||||
{
|
||||
private static T? _instance;
|
||||
|
||||
/// <summary>
|
||||
/// Gets instance of the cosmetic group.
|
||||
/// </summary>
|
||||
#pragma warning disable CA1000
|
||||
public static T Instance => _instance ??= CustomCosmeticManager.Groups.OfType<T>().Single();
|
||||
#pragma warning restore CA1000
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using HarmonyLib;
|
||||
using MiraAPI.PluginLoading;
|
||||
using MonoMod.Utils;
|
||||
using Reactor.Utilities;
|
||||
|
||||
namespace MiraAPI.Cosmetics;
|
||||
public static class CustomCosmeticManager
|
||||
{
|
||||
private static readonly Dictionary<PropertyInfo, RegisterCustomCosmeticAttribute> OptionAttributes = [];
|
||||
private static readonly Dictionary<Type, AbstractCosmeticsGroup> TypeToGroup = [];
|
||||
internal static readonly Dictionary<CosmeticData, int> CosmeticToPriority = [];
|
||||
internal static readonly Dictionary<CosmeticData, AbstractCosmeticsGroup> CosmeticToGroup = [];
|
||||
|
||||
internal static readonly List<AbstractCosmeticsGroup> Groups = [];
|
||||
|
||||
internal static void RegisterVanilla()
|
||||
{
|
||||
if (Activator.CreateInstance(typeof(VanillaCosmeticsGroup)) is not AbstractCosmeticsGroup group)
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Failed to create group from Vanilla");
|
||||
return;
|
||||
}
|
||||
if (TypeToGroup.ContainsKey(typeof(VanillaCosmeticsGroup)))
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Vanilla group already exists.");
|
||||
return;
|
||||
}
|
||||
|
||||
Groups.Add(group);
|
||||
TypeToGroup.Add(typeof(VanillaCosmeticsGroup), group);
|
||||
}
|
||||
|
||||
internal static bool RegisterGroup(Type type, MiraPluginInfo pluginInfo)
|
||||
{
|
||||
if (Activator.CreateInstance(type) is not AbstractCosmeticsGroup group)
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Failed to create group from {type.Name}");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (TypeToGroup.ContainsKey(type))
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Group {type.Name} already exists.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Groups.Add(group);
|
||||
TypeToGroup.Add(type, group);
|
||||
pluginInfo.CosmeticGroups.Add(group);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static void RegisterAttributeOption(Type type, RegisterCustomCosmeticAttribute attribute, PropertyInfo property, MiraPluginInfo pluginInfo)
|
||||
{
|
||||
if (OptionAttributes.ContainsKey(property))
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Property {property.Name} already has an attribute registered.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TypeToGroup.TryGetValue(type, out var group))
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Failed to get group for {type.Name}");
|
||||
return;
|
||||
}
|
||||
|
||||
OptionAttributes.Add(property, attribute);
|
||||
}
|
||||
|
||||
internal static void LoadCosmetic(PropertyInfo property, RegisterCustomCosmeticAttribute attribute)
|
||||
{
|
||||
if (!TypeToGroup.TryGetValue(property.DeclaringType, out var group))
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Failed to get group for {property.DeclaringType.Name}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (property.PropertyType.IsAssignableTo(typeof(IEnumerable<HatData>)))
|
||||
{
|
||||
group.Hats.AddRange((IEnumerable<HatData>)property.GetValue(group));
|
||||
}
|
||||
else if (property.PropertyType.IsAssignableTo(typeof(IEnumerable<SkinData>)))
|
||||
{
|
||||
group.Skins.AddRange((IEnumerable<SkinData>)property.GetValue(group));
|
||||
}
|
||||
else if (property.PropertyType.IsAssignableTo(typeof(IEnumerable<VisorData>)))
|
||||
{
|
||||
group.Visors.AddRange((IEnumerable<VisorData>)property.GetValue(group));
|
||||
}
|
||||
else if (property.PropertyType.IsAssignableTo(typeof(IEnumerable<NamePlateData>)))
|
||||
{
|
||||
group.Nameplates.AddRange((IEnumerable<NamePlateData>)property.GetValue(group));
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Failed to get enumerable for {property.Name}");
|
||||
return;
|
||||
}
|
||||
|
||||
CosmeticToPriority.AddRange(((IEnumerable<CosmeticData>)property.GetValue(group)).ToDictionary(y => y, x => attribute.Priority));
|
||||
CosmeticToGroup.AddRange(((IEnumerable<CosmeticData>)property.GetValue(group)).ToDictionary(y => y, x => group));
|
||||
}
|
||||
|
||||
internal static bool Registered { get; set; }
|
||||
internal static void LoadAll()
|
||||
{
|
||||
CosmeticGroupSingleton<VanillaCosmeticsGroup>.Instance.runtimeRegister();
|
||||
if (Registered || !CosmeticGroupSingleton<VanillaCosmeticsGroup>.Instance.registered)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Registered = true;
|
||||
CosmeticToPriority.AddRange(CosmeticGroupSingleton<VanillaCosmeticsGroup>.Instance.Cosmetics.ToDictionary(y => y, x => 0));
|
||||
CosmeticToGroup.AddRange(CosmeticGroupSingleton<VanillaCosmeticsGroup>.Instance.Cosmetics.ToDictionary(y => y, x => CosmeticGroupSingleton<VanillaCosmeticsGroup>.Instance));
|
||||
OptionAttributes.Do(x => LoadCosmetic(x.Key, x.Value));
|
||||
DestroyableSingleton<HatManager>.Instance.allHats = CosmeticToGroup.Keys.OfType<HatData>().ToArray();
|
||||
DestroyableSingleton<HatManager>.Instance.allVisors = CosmeticToGroup.Keys.OfType<VisorData>().ToArray();
|
||||
DestroyableSingleton<HatManager>.Instance.allSkins = CosmeticToGroup.Keys.OfType<SkinData>().ToArray();
|
||||
DestroyableSingleton<HatManager>.Instance.allNamePlates = CosmeticToGroup.Keys.OfType<NamePlateData>().ToArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace MiraAPI.Cosmetics;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class RegisterCustomCosmeticAttribute(int priority = 0) : Attribute
|
||||
{
|
||||
public int Priority { get; } = priority;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MiraAPI.Cosmetics;
|
||||
public class VanillaCosmeticsGroup : AbstractCosmeticsGroup
|
||||
{
|
||||
public override string GroupName => "Vanilla";
|
||||
internal static HatData[] VanillaHats => DestroyableSingleton<HatManager>.Instance.allHats;
|
||||
internal static VisorData[] VanillaVisors => DestroyableSingleton<HatManager>.Instance.allVisors;
|
||||
internal static SkinData[] VanillaSkins => DestroyableSingleton<HatManager>.Instance.allSkins;
|
||||
internal static NamePlateData[] VanillaNameplates => DestroyableSingleton<HatManager>.Instance.allNamePlates;
|
||||
|
||||
internal List<CosmeticData> Cosmetics { get; } = [];
|
||||
|
||||
internal bool registered { get; set; }
|
||||
internal bool runtimeRegister()
|
||||
{
|
||||
if (registered)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!DestroyableSingleton<HatManager>.InstanceExists || VanillaHats.Length == 0
|
||||
|| VanillaVisors.Length == 0 || VanillaSkins.Length == 0
|
||||
|| VanillaNameplates.Length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
registered = true;
|
||||
Hats.AddRange(VanillaHats);
|
||||
Visors.AddRange(VanillaVisors);
|
||||
Skins.AddRange(VanillaSkins);
|
||||
Nameplates.AddRange(VanillaNameplates);
|
||||
Cosmetics.AddRange(Hats);
|
||||
Cosmetics.AddRange(Visors);
|
||||
Cosmetics.AddRange(Skins);
|
||||
Cosmetics.AddRange(Nameplates);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using MiraAPI.Hud;
|
||||
|
||||
namespace MiraAPI.Events.Mira;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when a <see cref="CustomActionButton"/> click is cancelled. Do not use for vanilla <see cref="AbilityButton"/>s.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The <see cref="CustomActionButton"/> type.</typeparam>
|
||||
/// <param name="button">The <see cref="CustomActionButton"/> whose click was cancelled.</param>
|
||||
public sealed class MiraButtonCancelledEvent<T>(T button) : MiraEvent
|
||||
where T : CustomActionButton
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="CustomActionButton"/> whose click was cancelled.
|
||||
/// </summary>
|
||||
public T Button { get; } = button;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when a <see cref="CustomActionButton"/> click is cancelled. Do not use for vanilla <see cref="AbilityButton"/>s.
|
||||
/// </summary>
|
||||
/// <param name="button">The <see cref="CustomActionButton"/> whose click was cancelled.</param>
|
||||
public sealed class MiraButtonCancelledEvent(CustomActionButton button) : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="CustomActionButton"/> whose click was cancelled.
|
||||
/// </summary>
|
||||
public CustomActionButton Button { get; } = button;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
using MiraAPI.Hud;
|
||||
|
||||
namespace MiraAPI.Events.Mira;
|
||||
|
||||
/// <summary>
|
||||
/// Button click event for <see cref="CustomActionButton"/>s only. Do not use for vanilla <see cref="AbilityButton"/>s.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The <see cref="CustomActionButton"/> type.</typeparam>
|
||||
/// <param name="button">The <see cref="CustomActionButton"/> that was clicked.</param>
|
||||
/// <param name="genericClickEvent">The generic <see cref="MiraButtonClickEvent"/> invoked before button-specific events.</param>
|
||||
public class MiraButtonClickEvent<T>(T button, MiraButtonClickEvent genericClickEvent) : MiraCancelableEvent
|
||||
where T : CustomActionButton
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="CustomActionButton"/> that was clicked.
|
||||
/// </summary>
|
||||
public T Button { get; } = button;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the generic <see cref="MiraButtonClickEvent"/> that is invoked before this button-specific event.
|
||||
/// </summary>
|
||||
public MiraButtonClickEvent GenericClickEvent { get; } = genericClickEvent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Button click event for <see cref="CustomActionButton"/>s only. Do not use for vanilla <see cref="AbilityButton"/>s.
|
||||
/// </summary>
|
||||
/// <param name="button">The <see cref="CustomActionButton"/> that was clicked.</param>
|
||||
public class MiraButtonClickEvent(CustomActionButton button) : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="CustomActionButton"/> that was clicked.
|
||||
/// </summary>
|
||||
public CustomActionButton Button { get; } = button;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Events.Mira;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired by Mira API to adjust the UI buttons at the top right of the screen.
|
||||
/// </summary>
|
||||
/// <param name="topUiRow">The <see cref="GameObject"/> for the top UI row.</param>
|
||||
/// <param name="secondUiRow">The <see cref="GameObject"/> for the second UI row.</param>
|
||||
public class UiButtonPostResetEvent(GameObject topUiRow, GameObject secondUiRow) : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="GameObject"/> parent for the very top UI row.
|
||||
/// </summary>
|
||||
public GameObject MainTopUiRow { get; } = topUiRow;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="GameObject"/> parent for the second top UI row.
|
||||
/// </summary>
|
||||
public GameObject SecondTopUiRow { get; } = secondUiRow;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
namespace MiraAPI.Events.Mira;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired by Mira API prior to adjusting the UI buttons at the top right of the screen.
|
||||
/// </summary>
|
||||
public class UiButtonResetEvent : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UiButtonResetEvent"/> class.
|
||||
/// </summary>
|
||||
public UiButtonResetEvent()
|
||||
{
|
||||
// nothing!
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using MiraAPI.PluginLoading;
|
||||
|
||||
namespace MiraAPI.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Abstract class for Mira Events that can be cancelled.
|
||||
/// </summary>
|
||||
[MiraIgnore]
|
||||
public abstract class MiraCancelableEvent : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the event is cancelled.
|
||||
/// </summary>
|
||||
public bool IsCancelled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Cancels the event.
|
||||
/// </summary>
|
||||
public void Cancel()
|
||||
{
|
||||
IsCancelled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uncancels the event.
|
||||
/// </summary>
|
||||
public void UnCancel()
|
||||
{
|
||||
IsCancelled = false;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using MiraAPI.PluginLoading;
|
||||
|
||||
namespace MiraAPI.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Abstract class for Mira Events.
|
||||
/// </summary>
|
||||
[MiraIgnore]
|
||||
public abstract class MiraEvent;
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace MiraAPI.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Event handle to use when unregistering a <see cref="MiraEvent"/>.
|
||||
/// </summary>
|
||||
public class MiraEventHandle
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the type of event.
|
||||
/// </summary>
|
||||
public Type EventType { get; }
|
||||
|
||||
internal MiraEventWrapper EventWrapper { get; }
|
||||
|
||||
internal MiraEventHandle(Type type, MiraEventWrapper eventWrapper)
|
||||
{
|
||||
EventType = type;
|
||||
EventWrapper = eventWrapper;
|
||||
}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace MiraAPI.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Mira Event manager.
|
||||
/// </summary>
|
||||
public static class MiraEventManager
|
||||
{
|
||||
private static readonly Dictionary<Type, List<MiraEventWrapper>> EventWrappers = [];
|
||||
|
||||
/// <summary>
|
||||
/// Invoke a <see cref="MiraEvent"/>.
|
||||
/// </summary>
|
||||
/// <param name="eventInstance">The <typeparamref name="T"/> instance.</param>
|
||||
/// <typeparam name="T">Type of Event.</typeparam>
|
||||
/// <returns>If there was an event handler invoked for this event, return <see langword="true"/>. Otherwise, return <see langword="false"/>.</returns>
|
||||
public static bool InvokeEvent<T>(this T eventInstance)
|
||||
where T : MiraEvent
|
||||
{
|
||||
EventWrappers.TryGetValue(typeof(T), out var handlers);
|
||||
|
||||
if (handlers == null || handlers.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var handler in handlers)
|
||||
{
|
||||
try
|
||||
{
|
||||
((Action<T>)handler.EventHandler).Invoke(eventInstance);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Error($"Error invoking event handler for {typeof(T).Name}: {ex.ToString()}");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoke a <see cref="MiraEvent"/> and use a specific type to find the handlers.
|
||||
/// </summary>
|
||||
/// <param name="eventInstance">The <see cref="MiraEvent"/> instance.</param>
|
||||
/// <param name="type">The type to use for handler lookup.</param>
|
||||
/// <returns>If there was an event handler invoked for this event, return <see langword="true"/>. Otherwise, return <see langword="false"/>.</returns>
|
||||
public static bool InvokeEvent(this MiraEvent eventInstance, Type type)
|
||||
{
|
||||
EventWrappers.TryGetValue(type, out var handlers);
|
||||
|
||||
if (handlers == null || handlers.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var handler in handlers)
|
||||
{
|
||||
try
|
||||
{
|
||||
handler.EventHandler.DynamicInvoke(eventInstance);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Error($"Error invoking event handler for {type.Name}: {ex.ToString()}");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a <see cref="MiraEvent"/> handler.
|
||||
/// </summary>
|
||||
/// <param name="type">The type of <see cref="MiraEvent"/> event.</param>
|
||||
/// <param name="methodInfo">The <see cref="MethodInfo"/> of the event handler.</param>
|
||||
/// <param name="priority">The priority of the event handler. Lower values are called first.</param>
|
||||
/// <returns>A <see cref="MiraEventHandle"/> to use when unregistering the event.</returns>
|
||||
public static MiraEventHandle RegisterEventHandler(Type type, MethodInfo methodInfo, int priority = 0)
|
||||
{
|
||||
if (!type.IsSubclassOf(typeof(MiraEvent)))
|
||||
{
|
||||
throw new InvalidOperationException($"Type must be a subclass of MiraEvent: {type.FullName}");
|
||||
}
|
||||
|
||||
EventWrappers.TryAdd(type, []);
|
||||
var handlers = EventWrappers[type];
|
||||
|
||||
var @delegate = Delegate.CreateDelegate(typeof(Action<>).MakeGenericType(type), methodInfo);
|
||||
var eventWrapper = new MiraEventWrapper(@delegate, priority);
|
||||
|
||||
var index = handlers.BinarySearch(eventWrapper, Comparer<MiraEventWrapper>.Create((a, b) => a.Priority.CompareTo(b.Priority)));
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
index = ~index;
|
||||
}
|
||||
|
||||
handlers.Insert(index, eventWrapper);
|
||||
return new MiraEventHandle(type, eventWrapper);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a <typeparamref name="T"/> handler.
|
||||
/// </summary>
|
||||
/// <param name="handler">The callback method/handler for the event.</param>
|
||||
/// <param name="priority">The priority of the event handler. Lower values are called first.</param>
|
||||
/// <typeparam name="T">Type of <see cref="MiraEvent"/> event.</typeparam>
|
||||
/// <returns>A <see cref="MiraEventHandle"/> to use when unregistering the event.</returns>
|
||||
public static MiraEventHandle RegisterEventHandler<T>(Action<T> handler, int priority = 0)
|
||||
where T : MiraEvent
|
||||
{
|
||||
EventWrappers.TryAdd(typeof(T), []);
|
||||
|
||||
var handlers = EventWrappers[typeof(T)];
|
||||
var eventWrapper = new MiraEventWrapper(handler, priority);
|
||||
|
||||
var index = handlers.BinarySearch(eventWrapper, Comparer<MiraEventWrapper>.Create((a, b) => a.Priority.CompareTo(b.Priority)));
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
index = ~index;
|
||||
}
|
||||
|
||||
handlers.Insert(index, eventWrapper);
|
||||
return new MiraEventHandle(typeof(T), eventWrapper);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregister a <see cref="MiraEvent"/> handler using the <see cref="MiraEventHandle"/>.
|
||||
/// </summary>
|
||||
/// <param name="eventHandle">A handle to the event.</param>
|
||||
/// <returns><see langword="true"/> if the event was unregistered successfully, <see langword="false"/> otherwise.</returns>
|
||||
public static bool UnregisterEventHandler(MiraEventHandle eventHandle)
|
||||
{
|
||||
if (!EventWrappers.TryGetValue(eventHandle.EventType, out var handlers))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!handlers.Remove(eventHandle.EventWrapper))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (handlers.Count == 0)
|
||||
{
|
||||
EventWrappers.Remove(eventHandle.EventType);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace MiraAPI.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper for <see cref="MiraEvent"/> handlers.
|
||||
/// </summary>
|
||||
/// <param name="eventHandler">The action for the event handler.</param>
|
||||
/// <param name="priority">The priority of the handler.</param>
|
||||
public class MiraEventWrapper(Delegate eventHandler, int priority)
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the event handler delegate.
|
||||
/// </summary>
|
||||
public Delegate EventHandler { get; } = eventHandler;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the priority of the handler. Lower values are called first.
|
||||
/// </summary>
|
||||
public int Priority { get; } = priority;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace MiraAPI.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Register a <see cref="MiraEvent"/> handler.
|
||||
/// </summary>
|
||||
/// <param name="priority">The priority of the event. Lower values are called first.</param>
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class RegisterEventAttribute(int priority = 0) : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the priority of the event. Lower values are called first.
|
||||
/// </summary>
|
||||
public int Priority { get; } = priority;
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Gameplay;
|
||||
|
||||
/// <summary>
|
||||
/// Event that is invoked after a player is murdered. Only called after a successful murder. This event is not cancelable.
|
||||
/// </summary>
|
||||
/// <param name="source">The <see cref="PlayerControl"/> that killed the <paramref name="target"/>.</param>
|
||||
/// <param name="target">The <see cref="PlayerControl"/> that was killed.</param>
|
||||
/// <param name="framed">The <see cref="PlayerControl"/> that was framed.</param>
|
||||
/// <param name="deadBody">The <paramref name="target"/>'s <see cref="global::DeadBody"/>, if it exists.</param>
|
||||
/// <param name="isIndirect">Whether the murder was caused indirectly.</param>
|
||||
/// <param name="ignoreDefense">Whether the murder ignored protection.</param>
|
||||
public class AfterMurderEvent(PlayerControl source, PlayerControl target, PlayerControl? framed, DeadBody? deadBody, bool isIndirect = true, bool ignoreDefense = false) : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="PlayerControl"/> that killed the <see cref="Target"/>.
|
||||
/// </summary>
|
||||
public PlayerControl Source { get; } = source;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="PlayerControl"/> that was killed.
|
||||
/// </summary>
|
||||
public PlayerControl Target { get; } = target;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="PlayerControl"/> that was framed, if any.
|
||||
/// </summary>
|
||||
public PlayerControl? Framed { get; } = framed;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the murder was done indirectly.
|
||||
/// This is commonly used to prevent the <see cref="Source"/> <see cref="PlayerControl"/> from being killed.
|
||||
/// </summary>
|
||||
public bool IsIndirectAttack { get; } = isIndirect;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the murder was able to bypass protective roles or general defense, such as <see cref="GuardianAngelRole"/>.
|
||||
/// </summary>
|
||||
public bool IgnoreDefense { get; } = ignoreDefense;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Target"/>'s <see cref="DeadBody"/>, if it exists.
|
||||
/// </summary>
|
||||
public DeadBody? DeadBody { get; } = deadBody;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AfterMurderEvent"/> class.
|
||||
/// </summary>
|
||||
/// <param name="source">The <see cref="PlayerControl"/> that killed the <paramref name="target"/>.</param>
|
||||
/// <param name="target">The <see cref="PlayerControl"/> that was killed.</param>
|
||||
/// <param name="deadBody">The <paramref name="target"/>'s <see cref="DeadBody"/>, if it exists.</param>
|
||||
/// <param name="isIndirect">Whether the murder was caused indirectly.</param>
|
||||
/// <param name="ignoreDefense">Whether the murder ignored protection.</param>
|
||||
public AfterMurderEvent(PlayerControl source, PlayerControl target, DeadBody? deadBody, bool isIndirect, bool ignoreDefense = false)
|
||||
: this(source, target, null, deadBody, isIndirect, ignoreDefense)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AfterMurderEvent"/> class.
|
||||
/// </summary>
|
||||
/// <param name="source">The <see cref="PlayerControl"/> that killed the <paramref name="target"/>.</param>
|
||||
/// <param name="target">The <see cref="PlayerControl"/> that was killed.</param>
|
||||
/// <param name="deadBody">The <paramref name="target"/>'s <see cref="DeadBody"/>, if it exists.</param>
|
||||
public AfterMurderEvent(PlayerControl source, PlayerControl target, DeadBody? deadBody)
|
||||
: this(source, target, null, deadBody)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Gameplay;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked before <see cref="GameManager.RpcEndGame"/> is called, allowing cancellation of the game end entirely.
|
||||
/// </summary>
|
||||
/// <param name="reason">The reason for the game end.</param>
|
||||
public class BeforeGameEndEvent(GameOverReason reason) : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the reason for the game end.
|
||||
/// </summary>
|
||||
public GameOverReason Reason { get; } = reason;
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
using MiraAPI.Networking;
|
||||
|
||||
namespace MiraAPI.Events.Vanilla.Gameplay;
|
||||
|
||||
/// <summary>
|
||||
/// Event that is invoked before a player is murdered. This event is cancelable.
|
||||
/// </summary>
|
||||
/// <param name="source">The <see cref="PlayerControl"/> that is killing the <paramref name="target"/>.</param>
|
||||
/// <param name="target">The <see cref="PlayerControl"/> that is being killed.</param>
|
||||
/// <param name="framed">The <see cref="PlayerControl"/> that is being framed.</param>
|
||||
/// <param name="isIndirect">Whether the murder is caused indirectly.</param>
|
||||
/// <param name="ignoreDefense">Whether the murder should ignore protection.</param>
|
||||
/// <param name="inMeeting">Whether the murder is intended to be triggered in a meeting.</param>
|
||||
public sealed class BeforeMurderEvent(PlayerControl source, PlayerControl target, PlayerControl? framed, bool isIndirect = true, bool ignoreDefense = false, MeetingCheck inMeeting = MeetingCheck.Ignore)
|
||||
: MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="PlayerControl"/> that is killing the <see cref="Target"/>.
|
||||
/// </summary>
|
||||
public PlayerControl Source { get; } = source;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="PlayerControl"/> that is being killed.
|
||||
/// </summary>
|
||||
public PlayerControl Target { get; } = target;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="PlayerControl"/> that is being framed, if any.
|
||||
/// </summary>
|
||||
public PlayerControl? Framed { get; } = framed;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the murder is done indirectly.
|
||||
/// This is commonly used to prevent the <see cref="Source"/> <see cref="PlayerControl"/> from being killed.
|
||||
/// </summary>
|
||||
public bool IsIndirectAttack { get; set; } = isIndirect;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the murder should bypass protective roles or general defense, such as <see cref="GuardianAngelRole"/>.
|
||||
/// </summary>
|
||||
public bool IgnoreDefense { get; set; } = ignoreDefense;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the murder was meant to be done in a meeting, via an enum.
|
||||
/// </summary>
|
||||
public MeetingCheck InMeeting { get; } = inMeeting;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BeforeMurderEvent"/> class.
|
||||
/// </summary>
|
||||
/// <param name="source">The <see cref="PlayerControl"/> that is killing the <paramref name="target"/>.</param>
|
||||
/// <param name="target">The <see cref="PlayerControl"/> that is being killed.</param>
|
||||
/// <param name="inMeeting">Whether the murder is intended to be triggered in a meeting.</param>
|
||||
public BeforeMurderEvent(PlayerControl source, PlayerControl target, MeetingCheck inMeeting = MeetingCheck.Ignore)
|
||||
: this(source, target, false, false, inMeeting)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BeforeMurderEvent"/> class.
|
||||
/// </summary>
|
||||
/// <param name="source">The <see cref="PlayerControl"/> that is killing the <paramref name="target"/>.</param>
|
||||
/// <param name="target">The <see cref="PlayerControl"/> that is being killed.</param>
|
||||
/// <param name="isIndirect">Whether the murder is caused indirectly.</param>
|
||||
/// <param name="ignoreDefense">Whether the murder should ignore protection.</param>
|
||||
/// <param name="inMeeting">Whether the murder is intended to be triggered in a meeting.</param>
|
||||
public BeforeMurderEvent(PlayerControl source, PlayerControl target, bool isIndirect, bool ignoreDefense = false, MeetingCheck inMeeting = MeetingCheck.Ignore)
|
||||
: this(source, target, null, isIndirect, ignoreDefense, inMeeting)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Gameplay;
|
||||
|
||||
/// <summary>
|
||||
/// Event invoked on <see cref="IntroCutscene.OnDestroy"/> and <see cref="ExileController.WrapUp"/> to determine if it should run the <see cref="RoundStartEvent"/> event or not.
|
||||
/// </summary>
|
||||
/// <param name="triggeredByIntro">Whether the event was triggered by the intro or not.</param>
|
||||
public class BeforeRoundStartEvent(bool triggeredByIntro) : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the event was triggered by the <see cref="IntroCutscene"/> or <see cref="ExileController"/>.
|
||||
/// </summary>
|
||||
public bool TriggeredByIntro { get; } = triggeredByIntro;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Gameplay;
|
||||
|
||||
/// <summary>
|
||||
/// The event that is invoked when the end game screen is shown. Non-cancelable.
|
||||
/// </summary>
|
||||
/// <param name="manager">The <see cref="global::EndGameManager"/> instance.</param>
|
||||
public class GameEndEvent(EndGameManager manager) : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="global::EndGameManager"/> instance.
|
||||
/// </summary>
|
||||
public EndGameManager EndGameManager { get; } = manager;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Gameplay;
|
||||
|
||||
/// <summary>
|
||||
/// The event that is invoked when the intro cutscene is shown. Non-cancelable.
|
||||
/// </summary>
|
||||
/// <param name="introCutscene">The intro cutscene.</param>
|
||||
public class IntroBeginEvent(IntroCutscene introCutscene) : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="global::IntroCutscene"/> instance.
|
||||
/// </summary>
|
||||
public IntroCutscene IntroCutscene { get; } = introCutscene;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Gameplay;
|
||||
|
||||
/// <summary>
|
||||
/// The event that is invoked when the intro cutscene has finished playing.
|
||||
/// </summary>
|
||||
/// <param name="introCutscene">The intro cutscene.</param>
|
||||
public class IntroEndEvent(IntroCutscene introCutscene) : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="global::IntroCutscene"/> instance.
|
||||
/// </summary>
|
||||
public IntroCutscene IntroCutscene { get; } = introCutscene;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Gameplay;
|
||||
|
||||
/// <summary>
|
||||
/// The event that is invoked when the player's role is shown on the intro cutscene. Non-cancelable.
|
||||
/// </summary>
|
||||
/// <param name="introCutscene">The intro cutscene.</param>
|
||||
public class IntroRoleRevealEvent(IntroCutscene introCutscene) : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="global::IntroCutscene"/> instance.
|
||||
/// </summary>
|
||||
public IntroCutscene IntroCutscene { get; } = introCutscene;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Gameplay;
|
||||
|
||||
/// <summary>
|
||||
/// Start Round event, invoked on <see cref="IntroCutscene.OnDestroy"/> and <see cref="ExileController.WrapUp"/>
|
||||
/// if the <see cref="BeforeRoundStartEvent"/> isn't cancelled.
|
||||
/// </summary>
|
||||
/// <param name="triggeredByIntro">Whether the event was triggered by the intro or not.</param>
|
||||
public class RoundStartEvent(bool triggeredByIntro) : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the event was triggered by the <see cref="IntroCutscene"/> or <see cref="ExileController"/>.
|
||||
/// </summary>
|
||||
public bool TriggeredByIntro { get; } = triggeredByIntro;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using AmongUs.GameOptions;
|
||||
|
||||
namespace MiraAPI.Events.Vanilla.Gameplay;
|
||||
|
||||
/// <summary>
|
||||
/// Event that is invoked after a player's role is set. This event is not cancelable.
|
||||
/// </summary>
|
||||
/// <param name="player">The player.</param>
|
||||
/// <param name="role">The new role.</param>
|
||||
public class SetRoleEvent(PlayerControl player, RoleTypes role) : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="PlayerControl"/> whose role was changed.
|
||||
/// </summary>
|
||||
public PlayerControl Player { get; } = player;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the role that the player was set to.
|
||||
/// </summary>
|
||||
public RoleTypes Role { get; } = role;
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using MiraAPI.Hud;
|
||||
|
||||
namespace MiraAPI.Events.Vanilla.Gameplay;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when a Vanilla <see cref="AbilityButton"/> click is cancelled. Do not use for <see cref="CustomActionButton"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The vanilla <see cref="AbilityButton"/> type.</typeparam>
|
||||
/// <param name="button">The vanilla <see cref="AbilityButton"/> whose click was cancelled.</param>
|
||||
public sealed class VanillaButtonCancelledEvent<T>(T button) : MiraEvent
|
||||
where T : AbilityButton
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the Vanilla <see cref="AbilityButton"/> whose click was cancelled.
|
||||
/// </summary>
|
||||
public T Button { get; } = button;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when a Vanilla <see cref="AbilityButton"/> click is cancelled. Do not use for <see cref="CustomActionButton"/>s.
|
||||
/// </summary>
|
||||
/// <param name="button">The vanilla <see cref="AbilityButton"/> whose click was cancelled.</param>
|
||||
public sealed class VanillaButtonCancelledEvent(AbilityButton button) : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the Vanilla <see cref="AbilityButton"/> whose click was cancelled.
|
||||
/// </summary>
|
||||
public AbilityButton Button { get; } = button;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
using MiraAPI.Hud;
|
||||
|
||||
namespace MiraAPI.Events.Vanilla.Gameplay;
|
||||
|
||||
/// <summary>
|
||||
/// Button click event for Vanilla <see cref="AbilityButton"/>s only. Do not use for <see cref="CustomActionButton"/>s.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The vanilla <see cref="AbilityButton"/> type.</typeparam>
|
||||
/// <param name="button">The vanilla <see cref="AbilityButton"/> that was clicked.</param>
|
||||
/// <param name="genericClickEvent">The generic <see cref="VanillaButtonClickEvent"/> invoked before button-specific events.</param>
|
||||
public sealed class VanillaButtonClickEvent<T>(T button, VanillaButtonClickEvent genericClickEvent) : MiraCancelableEvent
|
||||
where T : AbilityButton
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the vanilla <see cref="AbilityButton"/> that was clicked.
|
||||
/// </summary>
|
||||
public T Button { get; } = button;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the generic <see cref="VanillaButtonClickEvent"/> that is invoked before this button-specific event.
|
||||
/// </summary>
|
||||
public VanillaButtonClickEvent GenericClickEvent { get; } = genericClickEvent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Button click event for Vanilla <see cref="AbilityButton"/> only. Do not use for <see cref="CustomActionButton"/>s.
|
||||
/// </summary>
|
||||
/// <param name="button">The Vanilla <see cref="AbilityButton"/> that was clicked.</param>
|
||||
/// <param name="playerTarget">The <see cref="PlayerControl"/> target, if any.</param>
|
||||
/// <param name="ventTarget">The <see cref="Vent"/> target, if any.</param>
|
||||
public sealed class VanillaButtonClickEvent(AbilityButton button, PlayerControl? playerTarget = null, Vent? ventTarget = null) : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the Vanilla <see cref="AbilityButton"/> that was clicked.
|
||||
/// </summary>
|
||||
public AbilityButton Button { get; } = button;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the target <see cref="PlayerControl"/>, if any, of the Vanilla <see cref="AbilityButton"/> that was clicked.
|
||||
/// </summary>
|
||||
public PlayerControl? PlayerTarget { get; } = playerTarget;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the target <see cref="Vent"/>, if any, of the Vanilla <see cref="AbilityButton"/> that was clicked.
|
||||
/// </summary>
|
||||
public Vent? VentTarget { get; } = ventTarget;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Map;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when a player closes the doors in a room.
|
||||
/// </summary>
|
||||
/// <param name="room">The room that was closed.</param>
|
||||
public class CloseDoorsEvent(SystemTypes room) : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the room that the doors were closed in.
|
||||
/// </summary>
|
||||
public SystemTypes Room { get; } = room;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Map;
|
||||
|
||||
/// <summary>
|
||||
/// Sabotage from Vanilla Among Us.
|
||||
/// </summary>
|
||||
/// <param name="mapBehaviour">The <see cref="global::MapBehaviour"/>.</param>
|
||||
public class PlayerOpenSabotageEvent(MapBehaviour mapBehaviour) : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="global::MapBehaviour"/>.
|
||||
/// </summary>
|
||||
public MapBehaviour MapBehaviour { get; } = mapBehaviour;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Map;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="MiraCancelableEvent"/> that is invoked before a system is updated. Usually used for sabotage events.
|
||||
/// </summary>
|
||||
/// <param name="systemType">The <see cref="SystemTypes"/> being updated.</param>
|
||||
/// <param name="player">The <see cref="PlayerControl"/> that is updating the system.</param>
|
||||
/// <param name="amount">Amount to update System to.</param>
|
||||
public class UpdateSystemEvent(SystemTypes systemType, PlayerControl player, byte amount) : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the type of system that will be updated.
|
||||
/// </summary>
|
||||
public SystemTypes SystemType { get; } = systemType;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="PlayerControl"/> that is updating the system.
|
||||
/// </summary>
|
||||
public PlayerControl Player { get; } = player;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte amount the system is being updated by.
|
||||
/// </summary>
|
||||
public byte Amount { get; } = amount;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Meeting;
|
||||
|
||||
/// <summary>
|
||||
/// The event that is invoked when a player is ejected. Non-cancelable.
|
||||
/// </summary>
|
||||
/// <param name="controller">The <see cref="global::ExileController"/> instance.</param>
|
||||
public class EjectionEvent(ExileController controller) : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="global::ExileController"/> instance.
|
||||
/// </summary>
|
||||
public ExileController ExileController { get; } = controller;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Meeting;
|
||||
|
||||
/// <summary>
|
||||
/// The event that is invoked when the meeting has ended.
|
||||
/// </summary>
|
||||
public class EndMeetingEvent(MeetingHud meetingHud) : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="global::MeetingHud"/> instance.
|
||||
/// </summary>
|
||||
public MeetingHud MeetingHud { get; } = meetingHud;
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Meeting;
|
||||
|
||||
/// <summary>
|
||||
/// The event that is invoked when a body is reported.<br/>
|
||||
/// This is invoked in <see cref="PlayerControl.CmdReportDeadBody(NetworkedPlayerInfo)"/>.
|
||||
/// </summary>
|
||||
/// <param name="reporter">The player who reported the body.</param>
|
||||
/// <param name="target">The player being reported.</param>
|
||||
/// <param name="body">The <see cref="DeadBody"/> being reported.</param>
|
||||
public class ReportBodyEvent(PlayerControl reporter, NetworkedPlayerInfo? target, DeadBody? body) : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the player that is reporting the body.
|
||||
/// </summary>
|
||||
public PlayerControl Reporter { get; } = reporter;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the player that is being reported. Will be <see langword="null"/> for emergency meeting.
|
||||
/// </summary>
|
||||
public NetworkedPlayerInfo? Target { get; } = target;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="DeadBody"/> that is being reported. Will be <see langword="null"/> for emergency meeting.
|
||||
/// </summary>
|
||||
public DeadBody? Body { get; } = body;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Meeting;
|
||||
|
||||
/// <summary>
|
||||
/// The event that is invoked when a meeting is called. This event is not cancelable.
|
||||
/// This event is called after Mira resets votes, so if you plan on adding votes to a specific player, do it with this event.
|
||||
/// </summary>
|
||||
/// <param name="meetingHud">The <see cref="global::MeetingHud"/> instance.</param>
|
||||
public class StartMeetingEvent(MeetingHud meetingHud) : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="global::MeetingHud"/> instance.
|
||||
/// </summary>
|
||||
public MeetingHud MeetingHud { get; } = meetingHud;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Meeting.Voting;
|
||||
|
||||
/// <summary>
|
||||
/// Event that is invoked after the local player successfully votes a player or skips. This event is not cancelable.
|
||||
/// </summary>
|
||||
/// <param name="playerVoteArea">The <see cref="PlayerVoteArea"/> that was voted on.</param>
|
||||
/// <param name="voter">The player who voted.</param>
|
||||
public class AfterVoteEvent(PlayerVoteArea playerVoteArea, PlayerControl voter) : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the instance of the voter's <see cref="PlayerVoteArea"/>.
|
||||
/// </summary>
|
||||
public PlayerVoteArea VoteArea { get; } = playerVoteArea;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the player who voted.
|
||||
/// </summary>
|
||||
public PlayerControl Player { get; } = voter;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Meeting.Voting;
|
||||
|
||||
/// <summary>
|
||||
/// Event that is invoked before the local player confirms a vote on a player or when skipping. This event is cancelable.
|
||||
/// </summary>
|
||||
/// <param name="playerVoteArea">The <see cref="PlayerVoteArea"/> that was voted on.</param>
|
||||
/// <param name="voter">The player who voted.</param>
|
||||
public class BeforeVoteEvent(PlayerVoteArea playerVoteArea, PlayerControl voter) : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the instance of the voter's <see cref="PlayerVoteArea"/>.
|
||||
/// </summary>
|
||||
public PlayerVoteArea VoteArea { get; } = playerVoteArea;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the player who voted.
|
||||
/// </summary>
|
||||
public PlayerControl Player { get; } = voter;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Meeting.Voting;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if voting is complete. If canceled, the default end voting logic will be skipped.
|
||||
/// </summary>
|
||||
/// <param name="isVotingComplete"><see langword="true"/> if voting is complete, <see langword="false"/> otherwise.</param>
|
||||
public class CheckForEndVotingEvent(bool isVotingComplete) : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether default voting logic determines that voting is complete.
|
||||
/// </summary>
|
||||
public bool IsVotingComplete { get; } = isVotingComplete;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the voting should be forced to end, regardless of the default logic.
|
||||
/// </summary>
|
||||
public bool ForceEndVoting { get; set; }
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
using System;
|
||||
using MiraAPI.Utilities;
|
||||
using MiraAPI.Voting;
|
||||
|
||||
namespace MiraAPI.Events.Vanilla.Meeting.Voting;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked before the dummy selects their vote. If canceled, the dummy won't vote.
|
||||
/// </summary>
|
||||
/// <param name="dummy">The voting dummy.</param>
|
||||
public class DummyVoteEvent(DummyBehaviour dummy) : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the dummy that needs to vote.
|
||||
/// </summary>
|
||||
public DummyBehaviour Dummy { get; } = dummy;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instance of the dummy's <see cref="PlayerVoteData"/>.
|
||||
/// </summary>
|
||||
public PlayerVoteData VoteData { get; } = dummy.myPlayer.GetVoteData();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the dummy can vote to skip the meeting.
|
||||
/// </summary>
|
||||
public bool CanSkip { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a predicate for validating whether the dummy can vote on a player.
|
||||
/// By default, excludes dead and disconnected players.
|
||||
/// </summary>
|
||||
public Predicate<PlayerControl> PlayerIsValid { get; set; } = x => !x.Data.IsDead && !x.Data.Disconnected;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
using MiraAPI.Voting;
|
||||
|
||||
namespace MiraAPI.Events.Vanilla.Meeting.Voting;
|
||||
|
||||
/// <summary>
|
||||
/// The event that is invoked when Mira handles a vote. This is invoked before Mira's behaviour, so be cautious.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you intend on adding custom vote behaviour, cancel the event and do so.<br/>
|
||||
/// If you are NOT canceling the event, keep in mind that Mira automatically removes a vote and adds the suspect to the <see cref="PlayerVoteData.Votes"/> list after this event is invoked.
|
||||
/// </remarks>
|
||||
/// <param name="playerVoteData">The voter's <see cref="PlayerVoteData"/>.</param>
|
||||
/// <param name="targetId">The target's playerId.</param>
|
||||
/// <param name="isOverruling">Whether the vote is actually for a Judge.</param>
|
||||
public class HandleVoteEvent(PlayerVoteData playerVoteData, byte targetId, bool isOverruling = false) : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the instance of the voter's <see cref="PlayerVoteData"/>.
|
||||
/// </summary>
|
||||
public PlayerVoteData VoteData { get; } = playerVoteData;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the player who voted.
|
||||
/// </summary>
|
||||
public PlayerControl Player { get; } = playerVoteData.Owner;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the player id of the target.
|
||||
/// </summary>
|
||||
public byte TargetId { get; } = targetId;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to prevent the vote from commencing.
|
||||
/// </summary>
|
||||
public bool PreventVote { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="NetworkedPlayerInfo"/> of the target.
|
||||
/// </summary>
|
||||
public NetworkedPlayerInfo TargetPlayerInfo { get; } = GameData.Instance.GetPlayerById(targetId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the vote event is an Overrule caused by a Judge.
|
||||
/// </summary>
|
||||
public bool IsOverruling { get; set; } = isOverruling;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using MiraAPI.Voting;
|
||||
|
||||
namespace MiraAPI.Events.Vanilla.Meeting.Voting;
|
||||
|
||||
/// <summary>
|
||||
/// The event that is invoked when the player tries to select another player to vote.
|
||||
/// </summary>
|
||||
/// <param name="playerVoteData">The voter's <see cref="PlayerVoteData"/>.</param>
|
||||
/// <param name="targetId">The target's playerId.</param>
|
||||
/// <param name="allowSelect">Whether the player is allowed to select the target.</param>
|
||||
public class MeetingSelectEvent(PlayerVoteData playerVoteData, int targetId, bool allowSelect) : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the instance of the voter's <see cref="PlayerVoteData"/>.
|
||||
/// </summary>
|
||||
public PlayerVoteData VoteData { get; } = playerVoteData;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the player id of the target.
|
||||
/// </summary>
|
||||
public int TargetId { get; } = targetId;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="NetworkedPlayerInfo"/> of the target.
|
||||
/// </summary>
|
||||
public NetworkedPlayerInfo TargetPlayerInfo { get; } = GameData.Instance.GetPlayerById((byte)targetId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the player is allowed to select the target.
|
||||
/// </summary>
|
||||
public bool AllowSelect { get; set; } = allowSelect;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using MiraAPI.Voting;
|
||||
|
||||
namespace MiraAPI.Events.Vanilla.Meeting.Voting;
|
||||
|
||||
/// <summary>
|
||||
/// Called in <see cref="VotingUtils.HandlePopulateResults"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Cancelling is NOT advised but if you do plan on cancelling, please ensure you account for displaying ALL player's votes.
|
||||
/// </remarks>
|
||||
/// <param name="votes">The list of <see cref="CustomVote"/>s.</param>
|
||||
public class PopulateResultsEvent(List<CustomVote> votes) : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a list of networked <see cref="CustomVote"/>s.
|
||||
/// </summary>
|
||||
public List<CustomVote> Votes { get; } = votes;
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using MiraAPI.Voting;
|
||||
|
||||
namespace MiraAPI.Events.Vanilla.Meeting.Voting;
|
||||
|
||||
/// <summary>
|
||||
/// Ran after calculating votes and before displaying the results. Only ran on the host.
|
||||
/// </summary>
|
||||
/// <param name="votes">The list of <see cref="CustomVote"/>s that are being processed.</param>
|
||||
/// <param name="exiledPlayer">The player to be exiled. Will be <see langword="null"/> if no player is to be exiled.</param>
|
||||
public class ProcessVotesEvent(List<CustomVote> votes, NetworkedPlayerInfo? exiledPlayer = null) : MiraEvent
|
||||
{
|
||||
private readonly List<CustomVote> originalVotes = [.. votes];
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the exiled player has been modified by the event.
|
||||
/// </summary>
|
||||
public bool ExiledPlayerModified { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the votes have been modified by the event.
|
||||
/// </summary>
|
||||
public bool VotesModified => !Votes.SequenceEqual(originalVotes);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of <see cref="CustomVote"/>s that are being processed.
|
||||
/// </summary>
|
||||
public List<CustomVote> Votes { get; } = votes;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether an overruling was done. Normally set by judge but can be overwritten.
|
||||
/// </summary>
|
||||
public bool OverruledVote { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value specifically to determine which Judge (if any) caused the overruling. Normally set by judge but can be overwritten.
|
||||
/// </summary>
|
||||
public ushort OverruledNonce { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the player to be exiled. Will be <see langword="null"/> if no player is to be exiled.
|
||||
/// </summary>
|
||||
[SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1513:Closing brace should be followed by blank line", Justification = "Looks weird.")]
|
||||
public NetworkedPlayerInfo? ExiledPlayer
|
||||
{
|
||||
get;
|
||||
set
|
||||
{
|
||||
field = value;
|
||||
ExiledPlayerModified = true;
|
||||
}
|
||||
}
|
||||
= exiledPlayer;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Meeting.Voting;
|
||||
|
||||
/// <summary>
|
||||
/// The event that is invoked when the voting phase of a meeting is complete.
|
||||
/// </summary>
|
||||
/// <param name="meetingHud">The <see cref="global::MeetingHud"/> instance.</param>
|
||||
public class VotingCompleteEvent(MeetingHud meetingHud) : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="global::MeetingHud"/> instance.
|
||||
/// </summary>
|
||||
public MeetingHud MeetingHud { get; } = meetingHud;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Player;
|
||||
|
||||
/// <summary>
|
||||
/// The event that is invoked when a player completes a task within Hide and Seek. Non-cancelable.
|
||||
/// </summary>
|
||||
/// <param name="hnsManager">The <see cref="HideAndSeekManager"/> currently active.</param>
|
||||
/// <param name="player">The player who completed the task.</param>
|
||||
/// <param name="task">The task that the player completed.</param>
|
||||
public class CompleteHnsTaskEvent(HideAndSeekManager hnsManager, PlayerControl player, PlayerTask task) : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the instance of the <see cref="PlayerControl"/>.
|
||||
/// </summary>
|
||||
public PlayerControl Player { get; } = player;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instance of the <see cref="PlayerTask"/> that the player completed.
|
||||
/// </summary>
|
||||
public PlayerTask Task { get; } = task;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instance of the <see cref="HideAndSeekManager"/> attached to the game.
|
||||
/// </summary>
|
||||
public HideAndSeekManager HnsManager { get; } = hnsManager;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Player;
|
||||
|
||||
/// <summary>
|
||||
/// The event that is invoked when a player completes a task. Non-cancelable.
|
||||
/// </summary>
|
||||
/// <param name="player">The player who completed the task.</param>
|
||||
/// <param name="task">The task that the player completed.</param>
|
||||
public class CompleteTaskEvent(PlayerControl player, PlayerTask task) : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the instance of the <see cref="PlayerControl"/>.
|
||||
/// </summary>
|
||||
public PlayerControl Player { get; } = player;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instance of the <see cref="PlayerTask"/> that the player completed.
|
||||
/// </summary>
|
||||
public PlayerTask Task { get; } = task;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
namespace MiraAPI.Events.Vanilla.Player;
|
||||
|
||||
/// <summary>
|
||||
/// Event that is invoked when a player dies. Non-cancelable.
|
||||
/// </summary>
|
||||
/// <param name="player">The player who died.</param>
|
||||
/// <param name="reason">The reason the player died.</param>
|
||||
/// <param name="deadBody">The player's <see cref="global::DeadBody"/>, if it exists.</param>
|
||||
public class PlayerDeathEvent(PlayerControl player, DeathReason reason, DeadBody? deadBody) : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the player who died.
|
||||
/// </summary>
|
||||
public PlayerControl Player { get; } = player;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the reason the player died.
|
||||
/// </summary>
|
||||
public DeathReason DeathReason { get; } = reason;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="global::DeadBody"/> associated with the player, if any.
|
||||
/// </summary>
|
||||
public DeadBody? DeadBody { get; } = deadBody;
|
||||
}
|
||||
Loaded 100 of 476 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user