mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-19 15:51:58 +00:00
262 lines
10 KiB
C#
262 lines
10 KiB
C#
using System.Collections.Generic;
|
|
using AmongUs.GameOptions;
|
|
using EHR.Modules;
|
|
using UnityEngine;
|
|
using static EHR.Options;
|
|
|
|
namespace EHR.Roles;
|
|
|
|
internal class Revolutionist : RoleBase
|
|
{
|
|
public static Dictionary<(byte, byte), bool> IsDraw = [];
|
|
public static Dictionary<byte, (PlayerControl Player, float Timer)> RevolutionistTimer = [];
|
|
public static Dictionary<byte, long> RevolutionistStart = [];
|
|
public static Dictionary<byte, long> RevolutionistLastTime = [];
|
|
public static Dictionary<byte, int> RevolutionistCountdown = [];
|
|
public static byte CurrentDrawTarget = byte.MaxValue;
|
|
|
|
public static bool On;
|
|
private static Color32 ShadeColor;
|
|
|
|
public static OptionItem RevolutionistDrawTime;
|
|
public static OptionItem RevolutionistCooldown;
|
|
public static OptionItem RevolutionistDrawCount;
|
|
public static OptionItem RevolutionistKillProbability;
|
|
public static OptionItem RevolutionistVentCountDown;
|
|
public override bool IsEnable => On;
|
|
|
|
public override void SetupCustomOption()
|
|
{
|
|
SetupRoleOptions(18400, TabGroup.NeutralRoles, CustomRoles.Revolutionist);
|
|
|
|
RevolutionistDrawTime = new FloatOptionItem(18410, "RevolutionistDrawTime", new(0f, 90f, 1f), 3f, TabGroup.NeutralRoles)
|
|
.SetParent(CustomRoleSpawnChances[CustomRoles.Revolutionist])
|
|
.SetValueFormat(OptionFormat.Seconds);
|
|
|
|
RevolutionistCooldown = new FloatOptionItem(18411, "RevolutionistCooldown", new(0f, 100f, 1f), 10f, TabGroup.NeutralRoles)
|
|
.SetParent(CustomRoleSpawnChances[CustomRoles.Revolutionist])
|
|
.SetValueFormat(OptionFormat.Seconds);
|
|
|
|
RevolutionistDrawCount = new IntegerOptionItem(18412, "RevolutionistDrawCount", new(1, 14, 1), 6, TabGroup.NeutralRoles)
|
|
.SetParent(CustomRoleSpawnChances[CustomRoles.Revolutionist])
|
|
.SetValueFormat(OptionFormat.Players);
|
|
|
|
RevolutionistKillProbability = new IntegerOptionItem(18413, "RevolutionistKillProbability", new(0, 100, 5), 15, TabGroup.NeutralRoles)
|
|
.SetParent(CustomRoleSpawnChances[CustomRoles.Revolutionist])
|
|
.SetValueFormat(OptionFormat.Percent);
|
|
|
|
RevolutionistVentCountDown = new FloatOptionItem(18414, "RevolutionistVentCountDown", new(0.5f, 180f, 0.5f), 15f, TabGroup.NeutralRoles)
|
|
.SetParent(CustomRoleSpawnChances[CustomRoles.Revolutionist])
|
|
.SetValueFormat(OptionFormat.Seconds);
|
|
}
|
|
|
|
|
|
public override void Add(byte playerId)
|
|
{
|
|
On = true;
|
|
ShadeColor = Utils.GetRoleColor(CustomRoles.Revolutionist).ShadeColor(0.25f);
|
|
foreach (PlayerControl ar in Main.CachedAllPlayerControls())
|
|
IsDraw.Add((playerId, ar.PlayerId), false);
|
|
}
|
|
|
|
public override void Init()
|
|
{
|
|
On = false;
|
|
}
|
|
|
|
public override bool CanUseKillButton(PlayerControl pc)
|
|
{
|
|
return !pc.IsDrawDone();
|
|
}
|
|
|
|
public override bool CanUseImpostorVentButton(PlayerControl pc)
|
|
{
|
|
return pc.IsDrawDone();
|
|
}
|
|
|
|
public override bool CanUseSabotage(PlayerControl pc)
|
|
{
|
|
return pc.Is(CustomRoles.Mischievous);
|
|
}
|
|
|
|
public override void SetKillCooldown(byte id)
|
|
{
|
|
Main.AllPlayerKillCooldown[id] = RevolutionistCooldown.GetFloat();
|
|
}
|
|
|
|
public override void ApplyGameOptions(IGameOptions opt, byte playerId)
|
|
{
|
|
opt.SetVision(false);
|
|
}
|
|
|
|
public override void GetProgressText(byte playerId, bool comms, StringBuilder resultText)
|
|
{
|
|
(int, int) draw = Utils.GetDrawPlayerCount(playerId, out _);
|
|
Color32 color = ShadeColor;
|
|
|
|
resultText.Append(Utils.ColorPrefix(color))
|
|
.Append("<color=#777777>-</color> ")
|
|
.Append(draw.Item1)
|
|
.Append('/')
|
|
.Append(draw.Item2)
|
|
.Append("</color>");
|
|
}
|
|
|
|
public override void SetButtonTexts(HudManager hud, byte id)
|
|
{
|
|
hud.KillButton?.OverrideText(Translator.GetString("RevolutionistDrawButtonText"));
|
|
hud.ImpostorVentButton.buttonLabelText.text = Translator.GetString("RevolutionistVentButtonText");
|
|
|
|
hud.SabotageButton?.ToggleVisible(false);
|
|
hud.AbilityButton?.ToggleVisible(false);
|
|
hud.ImpostorVentButton?.ToggleVisible(false);
|
|
}
|
|
|
|
public override bool OnCheckMurder(PlayerControl killer, PlayerControl target)
|
|
{
|
|
killer.SetKillCooldown(RevolutionistDrawTime.GetFloat());
|
|
|
|
if (!IsDraw[(killer.PlayerId, target.PlayerId)] && !RevolutionistTimer.ContainsKey(killer.PlayerId))
|
|
{
|
|
RevolutionistTimer.TryAdd(killer.PlayerId, (target, 0f));
|
|
Utils.NotifyRoles(SpecifySeer: killer, SpecifyTarget: target, ForceLoop: true);
|
|
RPC.SetCurrentDrawTarget(killer.PlayerId, target.PlayerId);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public override void OnReportDeadBody()
|
|
{
|
|
foreach (KeyValuePair<byte, long> x in RevolutionistStart)
|
|
{
|
|
PlayerControl tar = Utils.GetPlayerById(x.Key);
|
|
if (tar == null || tar.Is(CustomRoles.Pestilence)) continue;
|
|
|
|
Main.PlayerStates[tar.PlayerId].deathReason = PlayerState.DeathReason.Sacrifice;
|
|
tar.RpcExileV2();
|
|
tar.Data.IsDead = true;
|
|
Main.PlayerStates[tar.PlayerId].SetDead();
|
|
Utils.AfterPlayerDeathTasks(tar, true);
|
|
}
|
|
|
|
RevolutionistTimer.Clear();
|
|
RevolutionistStart.Clear();
|
|
RevolutionistLastTime.Clear();
|
|
}
|
|
|
|
public override void OnFixedUpdate(PlayerControl player)
|
|
{
|
|
byte playerId = player.PlayerId;
|
|
if (RevolutionistTimer.TryGetValue(playerId, out var value))
|
|
{
|
|
PlayerControl rvTarget = value.Player;
|
|
|
|
if (!player.IsAliveWithConditions())
|
|
{
|
|
RevolutionistTimer.Remove(playerId);
|
|
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: rvTarget, ForceLoop: true);
|
|
RPC.ResetCurrentDrawTarget(playerId);
|
|
}
|
|
else
|
|
{
|
|
float rvTime = value.Timer;
|
|
|
|
if (!rvTarget.IsAlive())
|
|
RevolutionistTimer.Remove(playerId);
|
|
else if (rvTime >= RevolutionistDrawTime.GetFloat())
|
|
{
|
|
player.SetKillCooldown();
|
|
RevolutionistTimer.Remove(playerId);
|
|
IsDraw[(playerId, rvTarget.PlayerId)] = true;
|
|
player.RpcSetDrawPlayer(rvTarget, true);
|
|
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: rvTarget, ForceLoop: true);
|
|
RPC.ResetCurrentDrawTarget(playerId);
|
|
|
|
if (IRandom.Instance.Next(1, 100) <= RevolutionistKillProbability.GetInt())
|
|
{
|
|
rvTarget.SetRealKiller(player);
|
|
Main.PlayerStates[rvTarget.PlayerId].deathReason = PlayerState.DeathReason.Sacrifice;
|
|
player.Kill(rvTarget);
|
|
Main.PlayerStates[rvTarget.PlayerId].SetDead();
|
|
Logger.Info($"Revolutionist: {player.GetNameWithRole().RemoveHtmlTags()} killed {rvTarget.GetNameWithRole().RemoveHtmlTags()}", "Revolutionist");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
float range = GameManager.Instance.LogicOptions.GetKillDistance();
|
|
|
|
if (FastVector2.DistanceWithinRange(player.Pos(), rvTarget.Pos(), range))
|
|
RevolutionistTimer[playerId] = (rvTarget, rvTime + Time.fixedDeltaTime);
|
|
else
|
|
{
|
|
RevolutionistTimer.Remove(playerId);
|
|
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: rvTarget);
|
|
RPC.ResetCurrentDrawTarget(playerId);
|
|
|
|
Logger.Info($"Canceled: {player.GetNameWithRole().RemoveHtmlTags()}", "Revolutionist");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (player.IsDrawDone() && player.IsAlive())
|
|
{
|
|
if (RevolutionistStart.TryGetValue(playerId, out var start))
|
|
{
|
|
if (RevolutionistLastTime.ContainsKey(playerId))
|
|
{
|
|
long nowtime = Utils.TimeStamp;
|
|
RevolutionistLastTime[playerId] = nowtime;
|
|
var time = (int)(RevolutionistLastTime[playerId] - start);
|
|
int countdown = RevolutionistVentCountDown.GetInt() - time;
|
|
RevolutionistCountdown.Clear();
|
|
|
|
if (countdown <= 0)
|
|
{
|
|
Utils.GetDrawPlayerCount(playerId, out List<PlayerControl> y);
|
|
|
|
if (y != null)
|
|
{
|
|
foreach (PlayerControl pc in y)
|
|
{
|
|
if (pc != null && pc.IsAlive())
|
|
{
|
|
pc.Suicide(PlayerState.DeathReason.Sacrifice);
|
|
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
|
}
|
|
}
|
|
}
|
|
|
|
player.Suicide(PlayerState.DeathReason.Sacrifice);
|
|
|
|
if (player.AmOwner)
|
|
Achievements.Type.OutOfTime.Complete();
|
|
}
|
|
else RevolutionistCountdown[playerId] = countdown;
|
|
}
|
|
else RevolutionistLastTime.TryAdd(playerId, start);
|
|
}
|
|
else RevolutionistStart.TryAdd(playerId, Utils.TimeStamp);
|
|
}
|
|
}
|
|
|
|
public override void OnEnterVent(PlayerControl pc, Vent vent)
|
|
{
|
|
if (AmongUsClient.Instance.IsGameStarted && pc.IsDrawDone())
|
|
{
|
|
CustomWinnerHolder.SetWinnerOrAdditonalWinner(CustomWinner.Revolutionist);
|
|
Utils.GetDrawPlayerCount(pc.PlayerId, out List<PlayerControl> x);
|
|
CustomWinnerHolder.WinnerIds.Add(pc.PlayerId);
|
|
if (x != null) foreach (PlayerControl apc in x) CustomWinnerHolder.WinnerIds.Add(apc.PlayerId);
|
|
}
|
|
}
|
|
|
|
public override void OnRevived(PlayerControl pc)
|
|
{
|
|
RevolutionistTimer.Remove(pc.PlayerId);
|
|
RevolutionistStart.Remove(pc.PlayerId);
|
|
RevolutionistLastTime.Remove(pc.PlayerId);
|
|
RevolutionistCountdown.Remove(pc.PlayerId);
|
|
}
|
|
}
|