mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-19 15:51:58 +00:00
Add Assumer, add Deadlined (add-on)
This commit is contained in:
1 parent
b0a8d9d42d
commit
e4d5a77c2a
19 files changed
+312
-27
No files matched your search
@@ -21,6 +21,7 @@ public enum CustomRoles
|
||||
Hacker, // Anonymous
|
||||
AntiAdminer,
|
||||
Sans, // Arrogance
|
||||
Assumer,
|
||||
Augmenter,
|
||||
Bard,
|
||||
Blackmailer,
|
||||
|
||||
@@ -21,6 +21,7 @@ public enum CustomRoles
|
||||
Hacker, // Anonymous
|
||||
AntiAdminer,
|
||||
Sans, // Arrogance
|
||||
Assumer,
|
||||
Augmenter,
|
||||
Bard,
|
||||
Blackmailer,
|
||||
@@ -395,6 +396,7 @@ public enum CustomRoles
|
||||
Clumsy,
|
||||
Contagious,
|
||||
Damocles,
|
||||
Deadlined,
|
||||
DeadlyQuota,
|
||||
Disco,
|
||||
Diseased,
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TMP/@EntryIndexedValue">TMP</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=EHR/@EntryIndexedValue">EHR</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TP/@EntryIndexedValue">TP</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TS/@EntryIndexedValue">TS</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UI/@EntryIndexedValue">UI</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=VN/@EntryIndexedValue">VN</s:String>
|
||||
<s:Boolean
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
using HarmonyLib;
|
||||
|
||||
namespace EHR.Modules
|
||||
{
|
||||
// Credit: https://github.com/astra1dev/AUnlocker
|
||||
public static class AUnlocker
|
||||
{
|
||||
// Some of the below patches are from https://github.com/scp222thj/MalumMenu/blob/main/src/Passive/UnlockFeaturesPatch.cs
|
||||
|
||||
// Remove minor status
|
||||
[HarmonyPatch(typeof(EOSManager), nameof(EOSManager.IsMinorOrWaiting))]
|
||||
public static class RemoveMinorStatus
|
||||
{
|
||||
public static void Postfix(ref bool __result)
|
||||
{
|
||||
__result = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Unlock custom name
|
||||
[HarmonyPatch(typeof(FullAccount), nameof(FullAccount.CanSetCustomName))]
|
||||
public static class CustomNameEnabled
|
||||
{
|
||||
public static void Prefix(ref bool canSetName)
|
||||
{
|
||||
canSetName = true;
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(HatManager), nameof(HatManager.Initialize))]
|
||||
public static class UnlockCosmetics
|
||||
{
|
||||
// loop through all cosmetics and set them free
|
||||
// Source: https://github.com/scp222thj/MalumMenu/blob/main/src/Passive/FreeCosmeticsPatch.cs
|
||||
public static void Postfix(HatManager __instance)
|
||||
{
|
||||
foreach (var bundle in __instance.allBundles) bundle.Free = true;
|
||||
foreach (var featuredBundle in __instance.allFeaturedBundles) featuredBundle.Free = true;
|
||||
foreach (var featuredCube in __instance.allFeaturedCubes) featuredCube.Free = true;
|
||||
foreach (var featuredItem in __instance.allFeaturedItems) featuredItem.Free = true;
|
||||
foreach (var hat in __instance.allHats) hat.Free = true;
|
||||
foreach (var nameplate in __instance.allNamePlates) nameplate.Free = true;
|
||||
foreach (var pet in __instance.allPets) pet.Free = true;
|
||||
foreach (var skin in __instance.allSkins) skin.Free = true;
|
||||
foreach (var starBundle in __instance.allStarBundles) starBundle.price = 0;
|
||||
foreach (var visor in __instance.allVisors) visor.Free = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -127,6 +127,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Dictator => CustomRoles.Crewmate,
|
||||
CustomRoles.Inhibitor => CustomRoles.Impostor,
|
||||
CustomRoles.Kidnapper => CustomRoles.Shapeshifter,
|
||||
CustomRoles.Assumer => CustomRoles.Impostor,
|
||||
CustomRoles.Augmenter => CustomRoles.Shapeshifter,
|
||||
CustomRoles.Ventriloquist => CustomRoles.Impostor,
|
||||
CustomRoles.Echo => CustomRoles.Shapeshifter,
|
||||
@@ -573,6 +574,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Augmenter or
|
||||
CustomRoles.Inhibitor or
|
||||
CustomRoles.Kidnapper or
|
||||
CustomRoles.Assumer or
|
||||
CustomRoles.Generator or
|
||||
CustomRoles.Blackmailer or
|
||||
CustomRoles.Commander or
|
||||
@@ -1172,6 +1174,7 @@ internal static class CustomRolesHelper
|
||||
{
|
||||
CustomRoles.Sans => RoleOptionType.Impostor_Killing,
|
||||
CustomRoles.Assassin => RoleOptionType.Impostor_Killing,
|
||||
CustomRoles.Assumer => RoleOptionType.Impostor_Killing,
|
||||
CustomRoles.Augmenter => RoleOptionType.Impostor_Killing,
|
||||
CustomRoles.Bomber => RoleOptionType.Impostor_Killing,
|
||||
CustomRoles.BountyHunter => RoleOptionType.Impostor_Killing,
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AmongUs.GameOptions;
|
||||
using EHR.AddOns.Common;
|
||||
using EHR.AddOns.Crewmate;
|
||||
using EHR.AddOns.GhostRoles;
|
||||
using EHR.Crewmate;
|
||||
@@ -54,6 +55,7 @@ public class PlayerState(byte playerId)
|
||||
Consumed,
|
||||
BadLuck,
|
||||
Asthma,
|
||||
Assumed,
|
||||
|
||||
etc = -1
|
||||
}
|
||||
@@ -334,15 +336,6 @@ public class TaskState
|
||||
SpeedrunManager.ResetTimer(player);
|
||||
}
|
||||
|
||||
if (player.Is(CustomRoles.Unlucky) && alive)
|
||||
{
|
||||
var Ue = IRandom.Instance;
|
||||
if (Ue.Next(0, 100) < Options.UnluckyTaskSuicideChance.GetInt())
|
||||
{
|
||||
player.Suicide();
|
||||
}
|
||||
}
|
||||
|
||||
if (alive && Mastermind.ManipulatedPlayers.ContainsKey(player.PlayerId))
|
||||
{
|
||||
Mastermind.OnManipulatedPlayerTaskComplete(player);
|
||||
@@ -380,7 +373,9 @@ public class TaskState
|
||||
|
||||
var addons = Main.PlayerStates[player.PlayerId].SubRoles;
|
||||
|
||||
if (addons.Contains(CustomRoles.Deadlined)) Deadlined.SetDone(player);
|
||||
if (addons.Contains(CustomRoles.Stressed)) Stressed.OnTaskComplete(player);
|
||||
if (addons.Contains(CustomRoles.Unlucky) && alive && IRandom.Instance.Next(0, 100) < Options.UnluckyTaskSuicideChance.GetInt()) player.Suicide();
|
||||
if (GhostRolesManager.AssignedGhostRoles.TryGetValue(player.PlayerId, out var ghostRole))
|
||||
{
|
||||
if (ghostRole is { Role: CustomRoles.Specter, Instance: Specter specter } && (CompletedTasksCount + 1 >= AllTasksCount)) specter.OnFinishedTasks(player);
|
||||
|
||||
@@ -1888,6 +1888,7 @@ public static class Utils
|
||||
|
||||
if (seer.Is(CustomRoles.Asthmatic)) SelfSuffix.Append(Asthmatic.GetSuffixText(seer.PlayerId));
|
||||
if (seer.Is(CustomRoles.Sonar)) SelfSuffix.Append(Sonar.GetSuffix(seer, isForMeeting));
|
||||
if (seer.Is(CustomRoles.Deadlined)) SelfSuffix.Append(Deadlined.GetSuffix(seer));
|
||||
|
||||
SelfSuffix.Append(Bloodmoon.GetSuffix(seer));
|
||||
SelfSuffix.Append(Haunter.GetSuffix(seer));
|
||||
@@ -2582,6 +2583,7 @@ public static class Utils
|
||||
Damocles.AfterMeetingTasks();
|
||||
Stressed.AfterMeetingTasks();
|
||||
Circumvent.AfterMeetingTasks();
|
||||
Deadlined.AfterMeetingTasks();
|
||||
|
||||
if (Options.AirshipVariableElectrical.GetBool())
|
||||
AirshipElectricalDoors.Initialize();
|
||||
|
||||
@@ -156,6 +156,7 @@ internal static class ChatCommands
|
||||
new(["decree", "постановление"], "{number}", GetString("CommandDescription.Decree"), Command.UsageLevels.Everyone, Command.UsageTimes.InMeeting, DecreeCommand, true, [GetString("CommandArgs.Decree.Number")]),
|
||||
new(["addvip", "добавитьвип"], "{id}", GetString("CommandDescription.AddVIP"), Command.UsageLevels.Host, Command.UsageTimes.Always, AddVIPCommand, true, [GetString("CommandArgs.AddVIP.Id")]),
|
||||
new(["deletevip", "удалитьвип"], "{id}", GetString("CommandDescription.DeleteVIP"), Command.UsageLevels.Host, Command.UsageTimes.Always, DeleteVIPCommand, true, [GetString("CommandArgs.DeleteVIP.Id")]),
|
||||
new(["assume", "предположить"], "{id} {number}", GetString("CommandDescription.Assume"), Command.UsageLevels.Everyone, Command.UsageTimes.InMeeting, AssumeCommand, true, [GetString("CommandArgs.Assume.Id"), GetString("CommandArgs.Assume.Number")]),
|
||||
|
||||
// Commands with action handled elsewhere
|
||||
new(["shoot", "guess", "bet", "bt", "st", "угадать", "бт"], "{id} {role}", GetString("CommandDescription.Guess"), Command.UsageLevels.Everyone, Command.UsageTimes.InMeeting, (_, _, _, _) => { }, true, [GetString("CommandArgs.Guess.Id"), GetString("CommandArgs.Guess.Role")]),
|
||||
@@ -282,6 +283,12 @@ internal static class ChatCommands
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
private static void AssumeCommand(ChatController __instance, PlayerControl player, string text, string[] args)
|
||||
{
|
||||
if (args.Length < 3 || !byte.TryParse(args[1], out var id) || !int.TryParse(args[2], out var num) || !player.Is(CustomRoles.Assumer)) return;
|
||||
Assumer.Assume(player.PlayerId, id, num);
|
||||
}
|
||||
|
||||
private static void DeleteVIPCommand(ChatController __instance, PlayerControl player, string text, string[] args)
|
||||
{
|
||||
if (args.Length < 2 || !byte.TryParse(args[1], out var VIPId)) return;
|
||||
|
||||
@@ -163,7 +163,7 @@ public static class ChatManager
|
||||
int operate = message switch
|
||||
{
|
||||
{ } str when CheckCommand(ref str, "id|guesslist|gl编号|玩家编号|玩家id|id列表|玩家列表|列表|所有id|全部id|shoot|guess|bet|st|gs|bt|猜|赌|sp|jj|tl|trial|审判|判|审|xp|效颦|效|颦|sw|换票|换|swap", false) || CheckName(ref playername, "系统消息", false) => 1,
|
||||
{ } str when CheckCommand(ref str, "up|ask|target|vote|chat|check|decree", false) => 2,
|
||||
{ } str when CheckCommand(ref str, "up|ask|target|vote|chat|check|decree|assume", false) => 2,
|
||||
{ } str when CheckCommand(ref str, "r|role|m|myrole|n|now") => 4,
|
||||
_ => 3
|
||||
};
|
||||
|
||||
@@ -240,6 +240,7 @@ class HudManagerPatch
|
||||
{
|
||||
CustomRoles.Asthmatic => Asthmatic.GetSuffixText(player.PlayerId),
|
||||
CustomRoles.Spurt => Spurt.GetSuffix(player, true),
|
||||
CustomRoles.Deadlined => Deadlined.GetSuffix(player, true),
|
||||
_ => string.Empty
|
||||
});
|
||||
return string.Join(string.Empty, suffixes);
|
||||
|
||||
@@ -199,6 +199,7 @@ class CheckForEndVotingPatch
|
||||
states = [.. statesList];
|
||||
|
||||
var VotingData = __instance.CustomCalculateVotes();
|
||||
Assumer.OnVotingEnd(VotingData);
|
||||
byte exileId = byte.MaxValue;
|
||||
int max = 0;
|
||||
voteLog.Info("===Decision to expel player processing begins===");
|
||||
|
||||
@@ -646,6 +646,8 @@ class MurderPlayerPatch
|
||||
if (killer.Is(CustomRoles.Pickpocket) && killer.PlayerId != target.PlayerId)
|
||||
killer.Notify(string.Format(GetString("PickpocketGetVote"), ((Main.AllPlayerControls.Count(x => x.GetRealKiller()?.PlayerId == killer.PlayerId) + 1) * Pickpocket.VotesPerKill.GetFloat()).ToString("0.0#####")));
|
||||
|
||||
if (killer.Is(CustomRoles.Deadlined)) Deadlined.SetDone(killer);
|
||||
|
||||
if (target.Is(CustomRoles.Avanger))
|
||||
{
|
||||
var pcList = Main.AllAlivePlayerControls.Where(x => x.PlayerId != target.PlayerId).ToArray();
|
||||
@@ -1054,6 +1056,7 @@ class ReportDeadBodyPatch
|
||||
Spiritualist.OnReportDeadBody(target);
|
||||
|
||||
Bloodmoon.OnMeetingStart();
|
||||
Deadlined.OnMeetingStart();
|
||||
|
||||
Main.LastVotedPlayerInfo = null;
|
||||
Witness.AllKillers.Clear();
|
||||
@@ -1667,6 +1670,7 @@ static class FixedUpdatePatch
|
||||
Suffix.Append(Haunter.GetSuffix(seer));
|
||||
if (seer.Is(CustomRoles.Asthmatic)) Suffix.Append(Asthmatic.GetSuffixText(seer.PlayerId));
|
||||
if (seer.Is(CustomRoles.Sonar)) Suffix.Append(Sonar.GetSuffix(seer, GameStates.IsMeeting));
|
||||
if (seer.Is(CustomRoles.Deadlined)) Suffix.Append(Deadlined.GetSuffix(seer));
|
||||
}
|
||||
|
||||
switch (Options.CurrentGameMode)
|
||||
|
||||
@@ -11,6 +11,15 @@
|
||||
>
|
||||
> This mod is not affiliated with Among Us or Innersloth LLC, and the content contained therein is not endorsed or
|
||||
> otherwise sponsored by Innersloth LLC. Portions of the materials contained herein are the property of Innersloth LLC.
|
||||
> <br>
|
||||
> <br>
|
||||
> This mod does not unlock all cosmetics permanently, so it does not add them to your account. This is because your
|
||||
> progress is stored on the Innersloth servers and we cannot just modify it. However, this mod uses BepInEx and the
|
||||
> Reactor Framework to Postfix Among Us game methods and unlock all cosmetics temporarily. If you uninstall this mod,
|
||||
> the
|
||||
> cosmetics will be locked again. The cosmetics you have already unlocked legitimately, e.g., through buying a cosmicube
|
||||
> are untouched by this mod. This mod is not a cheat, it is a mod that adds new roles and features to the game. If you
|
||||
> have any questions, feel free to ask in our Discord server.
|
||||
<br>
|
||||
|
||||
</p>
|
||||
|
||||
@@ -1787,6 +1787,7 @@
|
||||
"DeathReason.Consumed": "Consumed",
|
||||
"DeathReason.BadLuck": "Bad Luck",
|
||||
"DeathReason.Asthma": "Asthma",
|
||||
"DeathReason.Assumed": "Assumed",
|
||||
"Alive": "Alive",
|
||||
"Win": " Wins!",
|
||||
"Last-": "Last ",
|
||||
@@ -2209,6 +2210,7 @@
|
||||
"CommandDescription.Decree": "Use a decree as the President",
|
||||
"CommandDescription.AddVIP": "Add a player to the VIP list",
|
||||
"CommandDescription.DeleteVIP": "Remove a player from the VIP list",
|
||||
"CommandDescription.Assume": "Assume how many votes a player will receive as the Assumer",
|
||||
"CommandArgs.ChangeSetting.Name": "The setting's name to change (leave blank to view all settings)",
|
||||
"CommandArgs.ChangeSetting.UnknownValue": "(leave blank to view what to put here)",
|
||||
"CommandArgs.Rename.Name": "Your new name",
|
||||
@@ -2264,6 +2266,8 @@
|
||||
"CommandArgs.Decree.Number": "0/1/2/3/4/5 (leave blank to view all decrees)",
|
||||
"CommandArgs.AddVIP.Id": "The player's ID to add to the VIP list",
|
||||
"CommandArgs.DeleteVIP.Id": "The player's ID to remove from the VIP list",
|
||||
"CommandArgs.Assume.Id": "The player's ID to assume votes for",
|
||||
"CommandArgs.Assume.Number": "The number of votes to assume",
|
||||
"Commands.ChangeSettingHelp": "<b><u>Arguments:</u></b><size=70%>\\n- map (theskeld/mirahq/polus/dlekseht/airship/thefungle/custom)\\n- impostors (number)\\n- players (number)\\n- recommended (on/off)\\n- confirmejects (on/off)\\n- emergencymeetings (number)\\n- anonymousvotes (on/off)\\n- emergencycooldown (number)\\n- discussiontime (number)\\n- votingtime (number)\\n- playerspeed (float)\\n- crewmatevision (float)\\n- impostorvision (float)\\n- killcooldown (float)\\n- killdistance (short/medium/long/custom)\\n- taskbarupdates (always/meetings/never)\\n- visualtasks (on/off)\\n- commontasks (number)\\n- longtasks (number)\\n- shorttasks (number)\\n- scientistcount (number)\\n- scientistchance (number)\\n- vitalsdisplaycooldown (float)\\n- batteryduration (float)\\n- engineercount (number)\\n- engineerchance (number)\\n- ventusecooldown (float)\\n- maxtimeinvents (float)\\n- guardianangelcount (number)\\n- guardianangelchance (number)\\n- protectcooldown (float)\\n- protectduration (float)\\n- protectvisibletoimpostors (on/off)\\n- shapeshiftercount (number)\\n- shapeshifterchance (number)\\n- shapeshiftduration (float)\\n- shapeshiftcooldown (float)\\n- leaveshapeshiftevidence (on/off)\\n- phantomcount (number)\\n- phantomchance (number)\\n- inviscooldown (float)\\n- invisduration (float)\\n- noisemakercount (number)\\n- noisemakerchance (number)\\n- noisemakerimpostoralert (on/off)\\n- noisemakeralertduration (number)\\n- trackercount (number)\\n- trackerchance (number)\\n- trackduration (float)\\n- trackcooldown (float)\\n- trackdelay (float)\\n- ghostdotasks (on/off)\\n\\n<u><b>Notes:</b></u>\\n1. Upper and lowercase matters\\n2. Where it says custom, you obviously put a number argument after it\\n3. A float is a single precision floating number, like 1.7\\n4. \"ghostdotasks\" causes issues if you set it\\n5. Example uses:\\n - \"/cs map polus\"\\n - \"/cs killdistance custom 4\"\\n - \"/cs trackdelay 1,7\"\\n - \"/cs confirmejects on\"",
|
||||
"PollResultTitle": "Poll Results",
|
||||
"Poll.Title": "<#ff0000>➡ POLL ⬅</color>",
|
||||
@@ -3332,6 +3336,17 @@
|
||||
"TornadoDuration": "Tornado Duration",
|
||||
"TornadoRange": "Tornado Range",
|
||||
"TeleportedByTornado": "\\nOh no! You just got caught up in a tornado,\\nand you flew to over here!",
|
||||
"Deadlined": "Deadlined",
|
||||
"DeadlinedInfo": "Must do a task or kill each round",
|
||||
"DeadlinedInfoLong": "(Add-ons):\\nAs the Deadlined, you must complete a task or kill someone each round. If you fail to do so, you will die. If a meeting gets called too soon after the previous one ends (time set by the host), you won't die.",
|
||||
"Prefix.Deadlined": "Deadlined",
|
||||
"Deadlined.InactiveTime": "Safe Time After Meetings",
|
||||
"Assumer": "Assumer",
|
||||
"AssumerInfo": "Assume Vote Counts",
|
||||
"AssumerInfoLong": "(Impostors):\\nAs the Assumer, you can type <b>/assume {id} {number}</b> to assume that the selected player (whose ID you typed as the first argument, replacing '{id}') will get exactly {number} votes (the number you typed in the second argument, replacing '{number}').\\nExample: <b>/assume 0 3</b> (assume that the host gets 3 votes).\\n\\nIf you are correct, <u>every player</u> that voted for your target dies.",
|
||||
"Assumer.AssumedMessage": "You're assuming that {0} will receive <b>{1}</b> votes",
|
||||
"Assumer.VoteReceiverDies": "Vote Receiver Dies on Correct Assumption",
|
||||
"Assumer.MinPlayersToAssume": "Minimum Alive Players to Make Assumptions",
|
||||
"Sentinel": "Sentinel",
|
||||
"SentinelInfo": "Scare Killers Away",
|
||||
"SentinelInfoLong": "(Crewmates):\\nAs the Sentinel, you may vent to start patrolling your surrounding area. When you do, all killers within this area are notified to dip. If any killer attempts to kill someone within this area while you're patrolling, you'll kill them instead. When patrolling is over, all killers in the patrolling area suicide. While patrolling, you have lower vision.",
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace EHR.AddOns.Common
|
||||
{
|
||||
public class Deadlined : IAddon
|
||||
{
|
||||
private static HashSet<byte> DidTask = [];
|
||||
private static long MeetingEndTS;
|
||||
private static OptionItem InactiveTime;
|
||||
public AddonTypes Type => AddonTypes.Harmful;
|
||||
|
||||
public void SetupCustomOption()
|
||||
{
|
||||
Options.SetupAdtRoleOptions(649293, CustomRoles.Deadlined, canSetNum: true, teamSpawnOptions: true);
|
||||
InactiveTime = new IntegerOptionItem(649299, "Deadlined.InactiveTime", new(0, 60, 1), 15, TabGroup.Addons)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Deadlined])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
}
|
||||
|
||||
public static void SetDone(PlayerControl pc)
|
||||
{
|
||||
DidTask.Add(pc.PlayerId);
|
||||
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
||||
}
|
||||
|
||||
public static void AfterMeetingTasks()
|
||||
{
|
||||
DidTask = [];
|
||||
MeetingEndTS = Utils.TimeStamp;
|
||||
|
||||
foreach (var pc in Main.AllPlayerControls)
|
||||
{
|
||||
TaskState ts = pc.GetTaskState();
|
||||
if (pc.Is(CustomRoles.Deadlined) && (!pc.IsAlive() || ts.IsTaskFinished || !ts.hasTasks))
|
||||
Main.PlayerStates[pc.PlayerId].RemoveSubRole(CustomRoles.Deadlined);
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnMeetingStart()
|
||||
{
|
||||
if (MeetingEndTS + InactiveTime.GetInt() > Utils.TimeStamp) return;
|
||||
foreach (var pc in Main.AllAlivePlayerControls)
|
||||
{
|
||||
if (!DidTask.Contains(pc.PlayerId))
|
||||
pc.Suicide();
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetSuffix(PlayerControl seer, bool hud = false)
|
||||
{
|
||||
if (!seer.Is(CustomRoles.Deadlined) || (seer.IsModClient() && !hud)) return string.Empty;
|
||||
if (DidTask.Contains(seer.PlayerId)) return "<#00ff00>\u2713</color>";
|
||||
long now = Utils.TimeStamp;
|
||||
return MeetingEndTS + InactiveTime.GetInt() <= now
|
||||
? Translator.GetString("Deadlined.MustDoTask")
|
||||
: string.Format(Translator.GetString("Deadlined.SafeTime"), InactiveTime.GetInt() - (now - MeetingEndTS));
|
||||
}
|
||||
}
|
||||
}
|
||||
+17
-17
@@ -29,23 +29,23 @@ namespace EHR.Crewmate
|
||||
|
||||
public override void SetupCustomOption()
|
||||
{
|
||||
// int id = 649550;
|
||||
// Options.SetupRoleOptions(id++, TabGroup.CrewmateRoles, CustomRoles.Whisperer);
|
||||
// Cooldown = new IntegerOptionItem(++id, "WhispererCooldown", new(0, 60, 1), 5, TabGroup.CrewmateRoles)
|
||||
// .SetParent(Options.CustomRoleSpawnChances[CustomRoles.Whisperer])
|
||||
// .SetValueFormat(OptionFormat.Seconds);
|
||||
// Duration = new IntegerOptionItem(++id, "WhispererDuration", new(0, 60, 1), 7, TabGroup.CrewmateRoles)
|
||||
// .SetParent(Options.CustomRoleSpawnChances[CustomRoles.Whisperer])
|
||||
// .SetValueFormat(OptionFormat.Seconds);
|
||||
// AbilityUseLimit = new IntegerOptionItem(++id, "AbilityUseLimit", new(0, 20, 1), 1, TabGroup.CrewmateRoles)
|
||||
// .SetParent(Options.CustomRoleSpawnChances[CustomRoles.Whisperer])
|
||||
// .SetValueFormat(OptionFormat.Times);
|
||||
// WhispererAbilityUseGainWithEachTaskCompleted = new FloatOptionItem(++id, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.05f), 1f, TabGroup.CrewmateRoles)
|
||||
// .SetParent(Options.CustomRoleSpawnChances[CustomRoles.Whisperer])
|
||||
// .SetValueFormat(OptionFormat.Times);
|
||||
// AbilityChargesWhenFinishedTasks = new FloatOptionItem(++id, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.05f), 0.2f, TabGroup.CrewmateRoles)
|
||||
// .SetParent(Options.CustomRoleSpawnChances[CustomRoles.Whisperer])
|
||||
// .SetValueFormat(OptionFormat.Times);
|
||||
int id = 649550;
|
||||
Options.SetupRoleOptions(id++, TabGroup.CrewmateRoles, CustomRoles.Whisperer);
|
||||
Cooldown = new IntegerOptionItem(++id, "WhispererCooldown", new(0, 60, 1), 5, TabGroup.CrewmateRoles)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Whisperer])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
Duration = new IntegerOptionItem(++id, "WhispererDuration", new(0, 60, 1), 7, TabGroup.CrewmateRoles)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Whisperer])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
AbilityUseLimit = new IntegerOptionItem(++id, "AbilityUseLimit", new(0, 20, 1), 1, TabGroup.CrewmateRoles)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Whisperer])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
WhispererAbilityUseGainWithEachTaskCompleted = new FloatOptionItem(++id, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.05f), 1f, TabGroup.CrewmateRoles)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Whisperer])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
AbilityChargesWhenFinishedTasks = new FloatOptionItem(++id, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.05f), 0.2f, TabGroup.CrewmateRoles)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Whisperer])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
}
|
||||
|
||||
public override void Init()
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
using System.Collections.Generic;
|
||||
using EHR.Patches;
|
||||
|
||||
namespace EHR.Impostor
|
||||
{
|
||||
public class Assumer : RoleBase
|
||||
{
|
||||
public static bool On;
|
||||
private static List<Assumer> Instances = [];
|
||||
|
||||
private static OptionItem VoteReceiverDies;
|
||||
private static OptionItem MinPlayersToAssume;
|
||||
private static OptionItem CanKill;
|
||||
private static OptionItem KillCooldown;
|
||||
private static OptionItem CanVent;
|
||||
private byte AssumerId;
|
||||
|
||||
private (byte Id, int VoteNum) Assumption;
|
||||
private bool HasAssumed => Assumption.Id != byte.MaxValue;
|
||||
public override bool IsEnable => On;
|
||||
|
||||
public override void SetupCustomOption()
|
||||
{
|
||||
StartSetup(649250, TabGroup.ImpostorRoles, CustomRoles.Assumer)
|
||||
.AutoSetupOption(ref VoteReceiverDies, false)
|
||||
.AutoSetupOption(ref MinPlayersToAssume, 6, new IntegerValueRule(1, 15, 1), OptionFormat.Players)
|
||||
.AutoSetupOption(ref CanKill, true, overrideName: "CanKill")
|
||||
.AutoSetupOption(ref KillCooldown, 30f, new FloatValueRule(0f, 120f, 0.5f), OptionFormat.Seconds, overrideName: "KillCooldown", overrideParent: CanKill)
|
||||
.AutoSetupOption(ref CanVent, false, overrideName: "CanVent");
|
||||
}
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
On = false;
|
||||
Instances = [];
|
||||
}
|
||||
|
||||
public override void Add(byte playerId)
|
||||
{
|
||||
On = true;
|
||||
Instances.Add(this);
|
||||
AssumerId = playerId;
|
||||
Assumption = (byte.MaxValue, 0);
|
||||
}
|
||||
|
||||
public override bool CanUseKillButton(PlayerControl pc) => CanKill.GetBool();
|
||||
public override void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
|
||||
public override bool CanUseImpostorVentButton(PlayerControl pc) => CanVent.GetBool();
|
||||
|
||||
public static void OnVotingEnd(Dictionary<byte, int> voteNum)
|
||||
{
|
||||
foreach (Assumer instance in Instances)
|
||||
{
|
||||
if (instance.HasAssumed && voteNum.TryGetValue(instance.Assumption.Id, out var num) && num == instance.Assumption.VoteNum)
|
||||
{
|
||||
foreach (PlayerVoteArea pva in MeetingHud.Instance.playerStates)
|
||||
{
|
||||
if (pva.VotedFor == instance.Assumption.Id || (VoteReceiverDies.GetBool() && pva.TargetPlayerId == instance.Assumption.Id))
|
||||
CheckForEndVotingPatch.TryAddAfterMeetingDeathPlayers(PlayerState.DeathReason.Assumed, pva.TargetPlayerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Assume(byte assumerId, byte id, int num)
|
||||
{
|
||||
if (Main.AllAlivePlayerControls.Length < MinPlayersToAssume.GetInt()) return;
|
||||
var assumer = Instances.Find(x => x.AssumerId == assumerId);
|
||||
if (assumer == null || assumer.HasAssumed) return;
|
||||
assumer.Assumption = (id, num);
|
||||
Utils.SendMessage("\n", assumerId, string.Format(Translator.GetString("Assumer.AssumedMessage"), id.ColoredPlayerName(), num));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
global using Object = UnityEngine.Object;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using AmongUs.GameOptions;
|
||||
using EHR.AddOns.Crewmate;
|
||||
@@ -188,5 +190,63 @@ namespace EHR
|
||||
var seerRole = seer.GetCustomRole();
|
||||
return seerRole.IsNK() && seerRole == target.GetCustomRole() && seer.GetTeam() == target.GetTeam();
|
||||
}
|
||||
|
||||
// Option setup simplifier
|
||||
protected static OptionSetupHandler StartSetup(int id, TabGroup tab, CustomRoles role)
|
||||
{
|
||||
Options.SetupRoleOptions(id++, tab, role);
|
||||
return new(++id, tab, role);
|
||||
}
|
||||
}
|
||||
|
||||
public class OptionSetupHandler(int id, TabGroup tab, CustomRoles role)
|
||||
{
|
||||
private readonly OptionItem Parent = Options.CustomRoleSpawnChances[role];
|
||||
|
||||
public OptionSetupHandler AutoSetupOption(ref OptionItem field, object defaultValue, object valueRule = null, OptionFormat format = OptionFormat.None, [CallerArgumentExpression("field")] string fieldName = "", string overrideName = "", OptionItem overrideParent = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var name = overrideName == "" ? $"{role}.{fieldName}" : overrideName;
|
||||
switch (valueRule, defaultValue)
|
||||
{
|
||||
case (null, bool bdv):
|
||||
field = new BooleanOptionItem(++id, name, bdv, tab);
|
||||
field.SetParent(overrideParent ?? Parent);
|
||||
break;
|
||||
case (IntegerValueRule ivr, int idv):
|
||||
field = new IntegerOptionItem(++id, name, ivr, idv, tab);
|
||||
field.SetParent(overrideParent ?? Parent);
|
||||
break;
|
||||
case (FloatValueRule fvr, float fdv):
|
||||
field = new FloatOptionItem(++id, name, fvr, fdv, tab);
|
||||
field.SetParent(overrideParent ?? Parent);
|
||||
break;
|
||||
case (IList<string> selections, int index):
|
||||
field = new StringOptionItem(++id, name, selections, index, tab);
|
||||
field.SetParent(overrideParent ?? Parent);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("The valueRule and defaultValue combination is not supported.");
|
||||
}
|
||||
|
||||
if (format != OptionFormat.None) field?.SetValueFormat(format);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error($"Failed to setup option {fieldName} for {role}", "OptionSetupHandler");
|
||||
Utils.ThrowException(e);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public enum OptionType
|
||||
{
|
||||
Boolean,
|
||||
Int,
|
||||
Float,
|
||||
String
|
||||
}
|
||||
}
|
||||
@@ -547,6 +547,7 @@ public class Main : BasePlugin
|
||||
{ CustomRoles.Messenger, "#28b573" },
|
||||
{ CustomRoles.Dynamo, "#ebe534" },
|
||||
{ CustomRoles.AntiTP, "#fcba03" },
|
||||
{ CustomRoles.Deadlined, "#ffa500" },
|
||||
{ CustomRoles.Rookie, "#bf671f" },
|
||||
{ CustomRoles.Taskcounter, "#ff1919" },
|
||||
{ CustomRoles.Stained, "#e6bf91" },
|
||||
|
||||
Reference in new issue
Block a user