mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-20 01:46:25 +00:00
133 lines
5.1 KiB
C#
133 lines
5.1 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using AmongUs.GameOptions;
|
|
using EHR.Modules;
|
|
using HarmonyLib;
|
|
using UnityEngine;
|
|
|
|
namespace EHR
|
|
{
|
|
public class SpeedrunManager
|
|
{
|
|
private static OptionItem TaskFinishWins;
|
|
private static OptionItem TimeStacksUp;
|
|
private static OptionItem TimeLimit;
|
|
|
|
public static HashSet<byte> CanKill = [];
|
|
|
|
private static Dictionary<byte, int> Timers = [];
|
|
|
|
public static void SetupCustomOption()
|
|
{
|
|
const int id = 69_214_001;
|
|
Color color = Utils.GetRoleColor(CustomRoles.Speedrunner);
|
|
|
|
TaskFinishWins = new BooleanOptionItem(id, "Speedrun_TaskFinishWins", false, TabGroup.GameSettings)
|
|
.SetGameMode(CustomGameMode.Speedrun)
|
|
.SetColor(color);
|
|
|
|
TimeStacksUp = new BooleanOptionItem(id + 1, "Speedrun_TimeStacksUp", false, TabGroup.GameSettings)
|
|
.SetGameMode(CustomGameMode.Speedrun)
|
|
.SetColor(color);
|
|
|
|
TimeLimit = new IntegerOptionItem(id + 2, "Speedrun_TimeLimit", new(1, 90, 1), 20, TabGroup.GameSettings)
|
|
.SetGameMode(CustomGameMode.Speedrun)
|
|
.SetValueFormat(OptionFormat.Seconds)
|
|
.SetColor(color);
|
|
}
|
|
|
|
public static void Init()
|
|
{
|
|
CanKill = [];
|
|
Timers = Main.AllAlivePlayerControls.ToDictionary(x => x.PlayerId, _ => TimeLimit.GetInt());
|
|
}
|
|
|
|
public static void ResetTimer(PlayerControl pc)
|
|
{
|
|
if (TimeStacksUp.GetBool()) Timers[pc.PlayerId] += TimeLimit.GetInt();
|
|
else Timers[pc.PlayerId] = TimeLimit.GetInt();
|
|
}
|
|
|
|
public static void OnTaskFinish(PlayerControl pc)
|
|
{
|
|
if (TaskFinishWins.GetBool()) return;
|
|
|
|
CanKill.Add(pc.PlayerId);
|
|
pc.ChangeRoleBasis(RoleTypes.Impostor);
|
|
pc.Notify(Translator.GetString("Speedrun_CompletedTasks"));
|
|
}
|
|
|
|
public static string GetTaskBarText()
|
|
{
|
|
return string.Join('\n', Main.PlayerStates
|
|
.Join(Main.AllAlivePlayerControls, x => x.Key, x => x.PlayerId, (kvp, pc) => (
|
|
Name: Utils.ColorString(Main.PlayerColors.GetValueOrDefault(kvp.Key, Color.white), pc.GetRealName()),
|
|
CompletedTasks: kvp.Value.TaskState.CompletedTasksCount,
|
|
AllTasks: kvp.Value.TaskState.AllTasksCount))
|
|
.Select(x => $"{x.Name}: {x.CompletedTasks}/{x.AllTasks}"));
|
|
}
|
|
|
|
public static string GetSuffixText(PlayerControl pc)
|
|
{
|
|
int time = Timers[pc.PlayerId];
|
|
int alive = Main.AllAlivePlayerControls.Length;
|
|
int apc = Main.AllPlayerControls.Length;
|
|
int killers = CanKill.Count;
|
|
|
|
// ReSharper disable once ConvertIfStatementToReturnStatement
|
|
if (CanKill.Contains(pc.PlayerId)) return string.Format(Translator.GetString("Speedrun_CanKillSuffixInfo"), alive, apc, killers - 1, time);
|
|
return string.Format(Translator.GetString("Speedrun_DoTasksSuffixInfo"), pc.GetTaskState().RemainingTasksCount, alive, apc, killers, time);
|
|
}
|
|
|
|
public static bool CheckForGameEnd(out GameOverReason reason)
|
|
{
|
|
if (TaskFinishWins.GetBool())
|
|
{
|
|
var player = Main.AllAlivePlayerControls.FirstOrDefault(x => x.GetTaskState().IsTaskFinished);
|
|
if (player != null)
|
|
{
|
|
CustomWinnerHolder.WinnerIds = [player.PlayerId];
|
|
reason = GameOverReason.HumansByTask;
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (Main.AllAlivePlayerControls.Length)
|
|
{
|
|
case 1:
|
|
CustomWinnerHolder.WinnerIds = [Main.AllAlivePlayerControls[0].PlayerId];
|
|
reason = GameOverReason.ImpostorByKill;
|
|
return true;
|
|
case 0:
|
|
CustomWinnerHolder.WinnerIds = [];
|
|
reason = GameOverReason.HumansDisconnect;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
reason = GameOverReason.ImpostorByKill;
|
|
return false;
|
|
}
|
|
|
|
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.FixedUpdate))]
|
|
class FixedUpdatePatch
|
|
{
|
|
private static long LastUpdate;
|
|
|
|
public static void Postfix(PlayerControl __instance)
|
|
{
|
|
if (!AmongUsClient.Instance.AmHost || !GameStates.IsInTask || Options.CurrentGameMode != CustomGameMode.Speedrun || Main.HasJustStarted) return;
|
|
|
|
if (Timers[__instance.PlayerId] <= 0) __instance.Suicide();
|
|
|
|
long now = Utils.TimeStamp;
|
|
if (LastUpdate == now) return;
|
|
LastUpdate = now;
|
|
|
|
Timers.Keys.ToArray().Do(x => Timers[x]--);
|
|
Utils.NotifyRoles();
|
|
}
|
|
}
|
|
}
|
|
} |