mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-20 01:46:25 +00:00
152 lines
6.7 KiB
C#
152 lines
6.7 KiB
C#
using HarmonyLib;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
|
|
namespace EHR
|
|
{
|
|
internal class HotPotatoManager
|
|
{
|
|
private static OptionItem Time;
|
|
private static OptionItem HolderSpeed;
|
|
private static OptionItem Chat;
|
|
private static OptionItem Range;
|
|
|
|
private static (byte HolderID, byte LastHolderID, int TimeLeft, int RoundNum) HotPotatoState;
|
|
private static Dictionary<byte, int> SurvivalTimes;
|
|
private static float DefaultSpeed;
|
|
|
|
public static (byte HolderID, byte LastHolderID, int TimeLeft, int RoundNum) GetState() => HotPotatoState;
|
|
|
|
public static bool IsChatDuringGame => Chat.GetBool();
|
|
|
|
public static void SetupCustomOption()
|
|
{
|
|
Time = IntegerOptionItem.Create(69_213_001, "HotPotato_Time", new(1, 90, 1), 20, TabGroup.GameSettings, false)
|
|
.SetHeader(true)
|
|
.SetGameMode(CustomGameMode.HotPotato)
|
|
.SetValueFormat(OptionFormat.Seconds)
|
|
.SetColor(new Color32(232, 205, 70, byte.MaxValue));
|
|
HolderSpeed = FloatOptionItem.Create(69_213_002, "HotPotato_HolderSpeed", new(0.1f, 5f, 0.1f), 1.5f, TabGroup.GameSettings, false)
|
|
.SetGameMode(CustomGameMode.HotPotato)
|
|
.SetValueFormat(OptionFormat.Multiplier)
|
|
.SetColor(new Color32(232, 205, 70, byte.MaxValue));
|
|
Chat = BooleanOptionItem.Create(69_213_003, "FFA_ChatDuringGame", false, TabGroup.GameSettings, false)
|
|
.SetGameMode(CustomGameMode.HotPotato)
|
|
.SetColor(new Color32(232, 205, 70, byte.MaxValue));
|
|
Range = FloatOptionItem.Create(69_213_004, "HotPotato_Range", new(0.25f, 5f, 0.25f), 1f, TabGroup.GameSettings, false)
|
|
.SetGameMode(CustomGameMode.HotPotato)
|
|
.SetValueFormat(OptionFormat.Multiplier)
|
|
.SetColor(new Color32(232, 205, 70, byte.MaxValue));
|
|
}
|
|
|
|
public static void Init()
|
|
{
|
|
FixedUpdatePatch.Return = true;
|
|
|
|
HotPotatoState = (byte.MaxValue, byte.MaxValue, Time.GetInt() + 20, 1);
|
|
SurvivalTimes = [];
|
|
foreach (var pc in Main.AllPlayerControls) SurvivalTimes[pc.PlayerId] = 0;
|
|
|
|
DefaultSpeed = Main.AllPlayerSpeed[0];
|
|
}
|
|
|
|
public static void OnGameStart()
|
|
{
|
|
_ = new LateTask(() => { FixedUpdatePatch.Return = false; }, 7f, log: false);
|
|
HotPotatoState = (byte.MaxValue, byte.MaxValue, Time.GetInt() + 5, 1);
|
|
}
|
|
|
|
public static int GetSurvivalTime(byte id) => SurvivalTimes.GetValueOrDefault(id, 0);
|
|
public static string GetIndicator(byte id) => HotPotatoState.HolderID == id ? " ★ " : string.Empty;
|
|
public static string GetSuffixText(byte id) => $"{(HotPotatoState.HolderID == id ? $"{Translator.GetString("HotPotato_HoldingNotify")}\n" : string.Empty)}{Translator.GetString("HotPotato_TimeLeftSuffix")}{HotPotatoState.TimeLeft}s";
|
|
|
|
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.FixedUpdate))]
|
|
class FixedUpdatePatch
|
|
{
|
|
private static float UpdateDelay;
|
|
private static long LastFixedUpdate;
|
|
public static bool Return;
|
|
|
|
public static void Postfix(PlayerControl __instance)
|
|
{
|
|
if (Options.CurrentGameMode != CustomGameMode.HotPotato || Return || !AmongUsClient.Instance.AmHost || !GameStates.IsInTask) return;
|
|
|
|
PlayerControl Holder = Utils.GetPlayerById(HotPotatoState.HolderID);
|
|
if (Holder == null || Holder.Data.Disconnected || !Holder.IsAlive())
|
|
{
|
|
PassHotPotato();
|
|
return;
|
|
}
|
|
|
|
long now = Utils.TimeStamp;
|
|
if (now > LastFixedUpdate)
|
|
{
|
|
HotPotatoState.TimeLeft--;
|
|
LastFixedUpdate = now;
|
|
Utils.NotifyRoles();
|
|
}
|
|
|
|
if (HotPotatoState.TimeLeft <= 0)
|
|
{
|
|
Holder.Suicide();
|
|
SurvivalTimes[HotPotatoState.HolderID] = Time.GetInt() * (HotPotatoState.RoundNum - 1);
|
|
PassHotPotato();
|
|
return;
|
|
}
|
|
|
|
if (HotPotatoState.HolderID != __instance.PlayerId || !Main.AllAlivePlayerControls.Any(x => x.PlayerId != HotPotatoState.HolderID && (x.PlayerId != HotPotatoState.LastHolderID || Main.AllAlivePlayerControls.Length == 2) && Vector2.Distance(x.Pos(), Holder.Pos()) <= Range.GetFloat())) return;
|
|
|
|
UpdateDelay += UnityEngine.Time.fixedDeltaTime;
|
|
if (UpdateDelay < 0.3f) return;
|
|
UpdateDelay = 0;
|
|
|
|
var Target = Main.AllAlivePlayerControls.OrderBy(x => Vector2.Distance(x.Pos(), Holder.Pos())).FirstOrDefault(x => x.PlayerId != HotPotatoState.HolderID && (x.PlayerId != HotPotatoState.LastHolderID || Main.AllAlivePlayerControls.Length == 2));
|
|
if (Target == null) return;
|
|
|
|
PassHotPotato(Target, resetTime: false);
|
|
}
|
|
|
|
private static void PassHotPotato(PlayerControl target = null, bool resetTime = true)
|
|
{
|
|
if (Return || Main.AllAlivePlayerControls.Length < 2) return;
|
|
|
|
if (resetTime)
|
|
{
|
|
HotPotatoState.TimeLeft = Time.GetInt();
|
|
HotPotatoState.RoundNum++;
|
|
}
|
|
|
|
try
|
|
{
|
|
target ??= Main.AllAlivePlayerControls[IRandom.Instance.Next(0, Main.AllAlivePlayerControls.Length)];
|
|
|
|
HotPotatoState.LastHolderID = HotPotatoState.HolderID;
|
|
HotPotatoState.HolderID = target.PlayerId;
|
|
|
|
Main.AllPlayerSpeed[target.PlayerId] = HolderSpeed.GetFloat();
|
|
target.MarkDirtySettings();
|
|
|
|
PlayerControl LastHolder = Utils.GetPlayerById(HotPotatoState.LastHolderID);
|
|
if (LastHolder != null)
|
|
{
|
|
Main.AllPlayerSpeed[HotPotatoState.LastHolderID] = DefaultSpeed;
|
|
LastHolder.MarkDirtySettings();
|
|
Utils.NotifyRoles(SpecifyTarget: LastHolder);
|
|
}
|
|
|
|
Logger.Info($"Hot Potato Passed: {LastHolder.GetRealName()} => {target.GetRealName()}", "HotPotato");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.Exception(ex, "HotPotatoManager.FixedUpdatePatch.PassHotPotato");
|
|
}
|
|
finally
|
|
{
|
|
Utils.NotifyRoles(SpecifyTarget: target);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |