mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-20 01:46:25 +00:00
Add files via upload
This commit is contained in:
1 parent
ddf811cb6e
commit
93fda42abc
22 files changed
+425
-187
No files matched your search
@@ -1,7 +1,5 @@
|
||||
using AmongUs.Data;
|
||||
using HarmonyLib;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using TOHE.Roles.Impostor;
|
||||
|
||||
namespace TOHE;
|
||||
@@ -87,13 +85,14 @@ public static class Camouflage
|
||||
|
||||
if (oldIsCamouflage != IsCamouflage)
|
||||
{
|
||||
Main.AllPlayerControls.Do(pc => RpcSetSkin(pc));
|
||||
if (Options.RemovePetsAtDeadPlayers.GetBool())
|
||||
foreach (var pc in Main.AllPlayerControls)
|
||||
{
|
||||
Main.AllPlayerControls
|
||||
.Where(pc => PlayerSkins[pc.PlayerId].PetId != string.Empty && pc.Data.IsDead && !pc.IsAlive())
|
||||
.Where(pc => pc.Data.IsDead && !pc.IsAlive() && PlayerSkins[pc.PlayerId].PetId != string.Empty)
|
||||
.Do(pc => pc.RpcSetPet(string.Empty));
|
||||
RpcSetSkin(pc);
|
||||
|
||||
if (!IsCamouflage)
|
||||
{
|
||||
pc.RpcRemovePet();
|
||||
}
|
||||
}
|
||||
Utils.NotifyRoles();
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Luckey => CustomRoles.Crewmate,
|
||||
CustomRoles.CyberStar => CustomRoles.Crewmate,
|
||||
CustomRoles.Demolitionist => CustomRoles.Crewmate,
|
||||
CustomRoles.Ventguard => CustomRoles.Crewmate,
|
||||
CustomRoles.Ventguard => CustomRoles.Engineer,
|
||||
CustomRoles.Express => CustomRoles.Crewmate,
|
||||
CustomRoles.NiceEraser => CustomRoles.Crewmate,
|
||||
CustomRoles.TaskManager => CustomRoles.Crewmate,
|
||||
@@ -177,7 +177,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Lookout => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.CyberStar => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Demolitionist => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Ventguard => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Ventguard => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Express => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.NiceEraser => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.TaskManager => CustomRoles.CrewmateTOHE,
|
||||
@@ -534,8 +534,8 @@ internal static class CustomRolesHelper
|
||||
//CustomRoles.Pirate or
|
||||
CustomRoles.Revolutionist or
|
||||
CustomRoles.Vulture or
|
||||
CustomRoles.Famine or
|
||||
CustomRoles.Baker or
|
||||
//CustomRoles.Famine or
|
||||
//CustomRoles.Baker or
|
||||
CustomRoles.CursedSoul or
|
||||
CustomRoles.Phantom or
|
||||
CustomRoles.Workaholic or
|
||||
@@ -676,8 +676,8 @@ internal static class CustomRolesHelper
|
||||
//CustomRoles.Masochist or
|
||||
CustomRoles.Amnesiac or
|
||||
CustomRoles.Medusa or
|
||||
CustomRoles.Famine or
|
||||
CustomRoles.Baker or
|
||||
//CustomRoles.Famine or
|
||||
//CustomRoles.Baker or
|
||||
CustomRoles.HexMaster or
|
||||
CustomRoles.Glitch or
|
||||
CustomRoles.Crewpostor or
|
||||
|
||||
@@ -25,7 +25,7 @@ public class DevUser
|
||||
UpName = upName;
|
||||
}
|
||||
public bool HasTag() => Tag != "null";
|
||||
public string GetTag() => Color == "null" ? $"<size=1>{Tag}</size>\r\n" : $"<color={Color}><size=1.7>{(Tag == "#Dev" ? Translator.GetString("Developer") : Tag)}</size></color>\r\n";
|
||||
public string GetTag() => Color == "null" ? $"<size=1>{Tag}</size>\r\n" : $"<color={Color}><size=1>{(Tag == "#Dev" ? Translator.GetString("Developer") : Tag)}</size></color>\r\n";
|
||||
}
|
||||
|
||||
public static class DevManager
|
||||
@@ -67,8 +67,8 @@ public static class DevManager
|
||||
DevUserList.Add(new(code: "unlikecity#4086", color: "#eD2F91", tag: "Ward", isUp: true, isDev: false, deBug: false, colorCmd: true, upName: "Ward"));
|
||||
DevUserList.Add(new(code: "iconicdrop#2727", color: "null", tag: "null", isUp: true, isDev: false, deBug: false, colorCmd: true, upName: "jackler"));
|
||||
|
||||
DevUserList.Add(new(code: "neatnet#5851", color: "#FFFF00", tag: "The 200IQ guy", isUp: true, isDev: true, deBug: true, colorCmd: true, upName: "The 200IQ guy"));
|
||||
DevUserList.Add(new(code: "contenthue#0404", color: "#FFFF00", tag: "The 200IQ guy", isUp: true, isDev: true, deBug: true, colorCmd: true, upName: "The 200IQ guy"));
|
||||
DevUserList.Add(new(code: "neatnet#5851", color: "#FFFF00", tag: "[Developer] The 200IQ guy", isUp: true, isDev: true, deBug: true, colorCmd: true, upName: "[Developer] The 200IQ guy"));
|
||||
DevUserList.Add(new(code: "contenthue#0404", color: "#FFFF00", tag: "[Developer] The 200IQ guy", isUp: true, isDev: true, deBug: true, colorCmd: true, upName: "[Developer] The 200IQ guy"));
|
||||
DevUserList.Add(new(code: "theseform#5686", color: "#FFFF00", tag: "Role idea creator", isUp: false, isDev: false, deBug: false, colorCmd: false, upName: "Role idea creator"));
|
||||
DevUserList.Add(new(code: "heavyclod#2286", color: "#FFFF00", tag: "小叨.exe已停止运行", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "小叨院长"));
|
||||
DevUserList.Add(new(code: "storeroan#0331", color: "#FF0066", tag: "Night_瓜", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "Night_瓜"));
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
namespace TOHE.Modules;
|
||||
|
||||
public static class DoorsReset
|
||||
{
|
||||
private static bool isEnabled = false;
|
||||
private static ResetMode mode;
|
||||
private static DoorsSystemType DoorsSystem => ShipStatus.Instance.Systems.TryGetValue(SystemTypes.Doors, out var system) ? system.TryCast<DoorsSystemType>() : null;
|
||||
private static readonly LogHandler logger = Logger.Handler(nameof(DoorsReset));
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
// AirshipとPolus以外は非対応
|
||||
if ((MapNames)Main.NormalOptions.MapId is not (MapNames.Airship or MapNames.Polus))
|
||||
{
|
||||
isEnabled = false;
|
||||
return;
|
||||
}
|
||||
isEnabled = Options.ResetDoorsEveryTurns.GetBool();
|
||||
mode = (ResetMode)Options.DoorsResetMode.GetValue();
|
||||
logger.Info($"初期化: [ {isEnabled}, {mode} ]");
|
||||
}
|
||||
|
||||
/// <summary>設定に応じてドア状況をリセット</summary>
|
||||
public static void ResetDoors()
|
||||
{
|
||||
if (!isEnabled || DoorsSystem == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
logger.Info("リセット");
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case ResetMode.AllOpen: OpenAllDoors(); break;
|
||||
case ResetMode.AllClosed: CloseAllDoors(); break;
|
||||
case ResetMode.RandomByDoor: OpenOrCloseAllDoorsRandomly(); break;
|
||||
default: logger.Warn($"無効なモード: {mode}"); break;
|
||||
}
|
||||
}
|
||||
/// <summary>マップ上の全ドアを開放</summary>
|
||||
private static void OpenAllDoors()
|
||||
{
|
||||
foreach (var door in ShipStatus.Instance.AllDoors)
|
||||
{
|
||||
SetDoorOpenState(door, true);
|
||||
}
|
||||
DoorsSystem.IsDirty = true;
|
||||
}
|
||||
/// <summary>マップ上の全ドアを閉鎖</summary>
|
||||
private static void CloseAllDoors()
|
||||
{
|
||||
foreach (var door in ShipStatus.Instance.AllDoors)
|
||||
{
|
||||
SetDoorOpenState(door, false);
|
||||
}
|
||||
DoorsSystem.IsDirty = true;
|
||||
}
|
||||
/// <summary>マップ上の全ドアをランダムに開閉</summary>
|
||||
private static void OpenOrCloseAllDoorsRandomly()
|
||||
{
|
||||
foreach (var door in ShipStatus.Instance.AllDoors)
|
||||
{
|
||||
var isOpen = IRandom.Instance.Next(2) > 0;
|
||||
SetDoorOpenState(door, isOpen);
|
||||
}
|
||||
DoorsSystem.IsDirty = true;
|
||||
}
|
||||
|
||||
/// <summary>ドアの開閉状況を設定する.サボタージュで閉められないドアに対しては何もしない</summary>
|
||||
/// <param name="door">対象のドア</param>
|
||||
/// <param name="isOpen">開けるならtrue,閉めるならfalse</param>
|
||||
private static void SetDoorOpenState(PlainDoor door, bool isOpen)
|
||||
{
|
||||
if (IsValidDoor(door))
|
||||
{
|
||||
door.SetDoorway(isOpen);
|
||||
}
|
||||
}
|
||||
/// <summary>リセット対象のドアかどうか判定する</summary>
|
||||
/// <returns>リセット対象ならtrue</returns>
|
||||
private static bool IsValidDoor(PlainDoor door)
|
||||
{
|
||||
// エアシラウンジトイレとPolus除染室のドアは対象外
|
||||
if (door.Room is SystemTypes.Lounge or SystemTypes.Decontamination)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public enum ResetMode { AllOpen, AllClosed, RandomByDoor, }
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
|
||||
namespace TOHE;
|
||||
|
||||
public static class EnumHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Get all values of enum
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of enum to be obtained</typeparam>
|
||||
/// <returns>All values of T</returns>
|
||||
public static T[] GetAllValues<T>() where T : Enum => Enum.GetValues(typeof(T)) as T[];
|
||||
/// <summary>
|
||||
/// enumのすべての名前を取得します
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of enum to be obtained</typeparam>
|
||||
/// <returns>All values of T</returns>
|
||||
public static string[] GetAllNames<T>() where T : Enum => Enum.GetNames(typeof(T));
|
||||
}
|
||||
@@ -20,8 +20,7 @@ public class NormalGameOptionsSender : GameOptionsSender
|
||||
}
|
||||
protected set
|
||||
{
|
||||
if (_logicOptions != null)
|
||||
_logicOptions.ClearDirtyFlag();
|
||||
_logicOptions?.ClearDirtyFlag();
|
||||
}
|
||||
}
|
||||
private LogicOptions _logicOptions;
|
||||
|
||||
@@ -1126,8 +1126,8 @@ public static class GuessManager
|
||||
or CustomRoles.Crewmate
|
||||
// or CustomRoles.Loyal
|
||||
or CustomRoles.Oblivious
|
||||
or CustomRoles.Baker
|
||||
or CustomRoles.Famine
|
||||
//or CustomRoles.Baker
|
||||
//or CustomRoles.Famine
|
||||
or CustomRoles.Rogue
|
||||
or CustomRoles.Scientist
|
||||
or CustomRoles.Impostor
|
||||
|
||||
@@ -83,8 +83,8 @@ public static class NameColorManager
|
||||
if (seer.Is(CustomRoles.Glitch) && target.Is(CustomRoles.Glitch)) color = Main.roleColors[CustomRoles.Glitch];
|
||||
if (seer.Is(CustomRoles.Succubus) && target.Is(CustomRoles.Succubus)) color = Main.roleColors[CustomRoles.Succubus];
|
||||
|
||||
if (seer.Is(CustomRoles.HeadHunter) && HeadHunter.Targets.Contains(target.PlayerId)) color = Color.black.ToString();
|
||||
if (seer.Is(CustomRoles.BountyHunter) && BountyHunter.GetTarget(seer) == target.PlayerId) color = Color.black.ToString();
|
||||
if (seer.Is(CustomRoles.HeadHunter) && HeadHunter.Targets.Contains(target.PlayerId)) color = "000000";
|
||||
if (seer.Is(CustomRoles.BountyHunter) && BountyHunter.GetTarget(seer) == target.PlayerId) color = "000000";
|
||||
|
||||
if (seer.Is(CustomRoles.Refugee) && target.Is(CustomRoleTypes.Impostor)) color = Main.roleColors[CustomRoles.ImpostorTOHE];
|
||||
if (seer.Is(CustomRoleTypes.Impostor) && target.Is(CustomRoles.Refugee)) color = Main.roleColors[CustomRoles.Refugee];
|
||||
|
||||
+48
-18
@@ -8,7 +8,9 @@ using TOHE.Roles.AddOns.Impostor;
|
||||
using TOHE.Roles.Crewmate;
|
||||
using TOHE.Roles.Impostor;
|
||||
using TOHE.Roles.Neutral;
|
||||
using TOHE.Modules;
|
||||
using UnityEngine;
|
||||
using Il2CppSystem.Diagnostics.Tracing;
|
||||
|
||||
namespace TOHE;
|
||||
|
||||
@@ -38,8 +40,6 @@ public static class Options
|
||||
//taskOptionsLoad.Wait();
|
||||
//Logger.Info("Options.Load End", "Options");
|
||||
}
|
||||
// オプションId
|
||||
public const int PresetId = 0;
|
||||
|
||||
// プリセット
|
||||
private static readonly string[] presets =
|
||||
@@ -110,7 +110,7 @@ public static class Options
|
||||
|
||||
// 各役職の詳細設定
|
||||
public static OptionItem EnableGM;
|
||||
public static float DefaultKillCooldown = Main.NormalOptions?.KillCooldown ?? 20;
|
||||
public static float DefaultKillCooldown = Main.NormalOptions?.KillCooldown ?? 25;
|
||||
public static OptionItem GhostsDoTasks;
|
||||
|
||||
public static OptionItem DisableMeeting;
|
||||
@@ -119,6 +119,8 @@ public static class Options
|
||||
public static OptionItem DisableTaskWin;
|
||||
|
||||
public static OptionItem KillFlashDuration;
|
||||
public static OptionItem EnableKillerLeftCommand;
|
||||
public static OptionItem SeeEjectedRolesInMeeting;
|
||||
//public static OptionItem ShareLobby;
|
||||
//public static OptionItem ShareLobbyMinPlayer;
|
||||
public static OptionItem DisableShieldAnimations;
|
||||
@@ -126,6 +128,8 @@ public static class Options
|
||||
public static OptionItem DisableVanillaRoles;
|
||||
public static OptionItem DisableHiddenRoles;
|
||||
public static OptionItem DisableSunnyboy;
|
||||
public static OptionItem SabotageCooldownControl;
|
||||
public static OptionItem SabotageCooldown;
|
||||
public static OptionItem SunnyboyChance;
|
||||
public static OptionItem DisableBard;
|
||||
public static OptionItem BardChance;
|
||||
@@ -155,8 +159,6 @@ public static class Options
|
||||
public static OptionItem NonNeutralKillingRolesMaxPlayer;
|
||||
public static OptionItem NeutralKillingRolesMinPlayer;
|
||||
public static OptionItem NeutralKillingRolesMaxPlayer;
|
||||
public static OptionItem CovenRolesMinPlayer;
|
||||
public static OptionItem CovenRolesMaxPlayer;
|
||||
public static OptionItem NeutralRoleWinTogether;
|
||||
public static OptionItem NeutralWinTogether;
|
||||
|
||||
@@ -437,6 +439,8 @@ public static class Options
|
||||
public static OptionItem CrewCanBeDoubleShot;
|
||||
public static OptionItem NeutralCanBeDoubleShot;
|
||||
public static OptionItem MimicCanSeeDeadRoles;
|
||||
public static OptionItem ResetDoorsEveryTurns;
|
||||
public static OptionItem DoorsResetMode;
|
||||
|
||||
//public static OptionItem NSerialKillerKillCD;
|
||||
//public static OptionItem NSerialKillerHasImpostorVision;
|
||||
@@ -880,6 +884,9 @@ public static class Options
|
||||
MainLoadingText = "Building system settings";
|
||||
|
||||
if (IsLoaded) return;
|
||||
|
||||
OptionSaver.Initialize();
|
||||
|
||||
// 预设
|
||||
_ = PresetOptionItem.Create(0, TabGroup.SystemSettings)
|
||||
.SetColor(new Color32(255, 235, 4, byte.MaxValue))
|
||||
@@ -1156,7 +1163,7 @@ public static class Options
|
||||
TimeThief.SetupCustomOption();
|
||||
RoleLoadingText = "Impostor roles\nVindicator";
|
||||
SetupRoleOptions(3400, TabGroup.ImpostorRoles, CustomRoles.Vindicator);
|
||||
VindicatorAdditionalVote = IntegerOptionItem.Create(3410, "MayorAdditionalVote", new(1, 99, 1), 3, TabGroup.ImpostorRoles, false)
|
||||
VindicatorAdditionalVote = IntegerOptionItem.Create(3410, "MayorAdditionalVote", new(1, 10, 1), 1, TabGroup.ImpostorRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Vindicator])
|
||||
.SetValueFormat(OptionFormat.Votes);
|
||||
VindicatorHideVote = BooleanOptionItem.Create(3411, "MayorHideVote", false, TabGroup.ImpostorRoles, false)
|
||||
@@ -1179,10 +1186,10 @@ public static class Options
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
RoleLoadingText = "Impostor roles\nSoul Catcher";
|
||||
SetupRoleOptions(3700, TabGroup.ImpostorRoles, CustomRoles.ImperiusCurse);
|
||||
ShapeImperiusCurseShapeshiftDuration = FloatOptionItem.Create(3710, "ShapeshiftDuration", new(2.5f, 300f, 2.5f), 300f, TabGroup.ImpostorRoles, false)
|
||||
ShapeImperiusCurseShapeshiftDuration = FloatOptionItem.Create(3710, "ShapeshiftDuration", new(2.5f, 300f, 2.5f), 20f, TabGroup.ImpostorRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.ImperiusCurse])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
ImperiusCurseShapeshiftCooldown = FloatOptionItem.Create(3711, "ShapeshiftCooldown", new(1f, 180f, 1f), 15f, TabGroup.ImpostorRoles, false)
|
||||
ImperiusCurseShapeshiftCooldown = FloatOptionItem.Create(3711, "ShapeshiftCooldown", new(1f, 180f, 1f), 30f, TabGroup.ImpostorRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.ImperiusCurse])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
RoleLoadingText = "Impostor roles\nMiner";
|
||||
@@ -1303,7 +1310,7 @@ public static class Options
|
||||
RoleLoadingText = "Crewmate roles\nVentguard";
|
||||
SetupSingleRoleOptions(5525, TabGroup.CrewmateRoles, CustomRoles.Ventguard, 1);
|
||||
VentguardAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(5527, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 1f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Veteran])
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Ventguard])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
VentguardMaxGuards = IntegerOptionItem.Create(5528, "VentguardMaxGuards", new(1, 20, 1), 3, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Ventguard]);
|
||||
VentguardBlockDoesNotAffectCrew = BooleanOptionItem.Create(5529, "VentguardBlockDoesNotAffectCrew", true, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Ventguard]);
|
||||
@@ -1717,14 +1724,14 @@ public static class Options
|
||||
Vulture.SetupCustomOption();
|
||||
RoleLoadingText = "Neutral roles\nWorkaholic";
|
||||
SetupRoleOptions(11700, TabGroup.NeutralRoles, CustomRoles.Workaholic); //TOH_Y
|
||||
WorkaholicCannotWinAtDeath = BooleanOptionItem.Create(11710, "WorkaholicCannotWinAtDeath", false, TabGroup.NeutralRoles, false)
|
||||
WorkaholicCannotWinAtDeath = BooleanOptionItem.Create(11710, "WorkaholicCannotWinAtDeath", true, TabGroup.NeutralRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Workaholic]);
|
||||
WorkaholicVentCooldown = FloatOptionItem.Create(11711, "VentCooldown", new(0f, 180f, 2.5f), 0f, TabGroup.NeutralRoles, false)
|
||||
WorkaholicVentCooldown = FloatOptionItem.Create(11711, "VentCooldown", new(0f, 180f, 2.5f), 30f, TabGroup.NeutralRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Workaholic])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
WorkaholicVisibleToEveryone = BooleanOptionItem.Create(11712, "WorkaholicVisibleToEveryone", true, TabGroup.NeutralRoles, false)
|
||||
WorkaholicVisibleToEveryone = BooleanOptionItem.Create(11712, "WorkaholicVisibleToEveryone", false, TabGroup.NeutralRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Workaholic]);
|
||||
WorkaholicGiveAdviceAlive = BooleanOptionItem.Create(11713, "WorkaholicGiveAdviceAlive", true, TabGroup.NeutralRoles, false)
|
||||
WorkaholicGiveAdviceAlive = BooleanOptionItem.Create(11713, "WorkaholicGiveAdviceAlive", false, TabGroup.NeutralRoles, false)
|
||||
.SetParent(WorkaholicVisibleToEveryone);
|
||||
WorkaholicTasks = OverrideTasksData.Create(11714, TabGroup.NeutralRoles, CustomRoles.Workaholic);
|
||||
WorkaholicCanGuess = BooleanOptionItem.Create(11725, "CanGuess", true, TabGroup.NeutralRoles, false)
|
||||
@@ -2381,6 +2388,10 @@ public static class Options
|
||||
KickLowLevelPlayer = IntegerOptionItem.Create(19300, "KickLowLevelPlayer", new(0, 100, 1), 0, TabGroup.SystemSettings, false)
|
||||
.SetValueFormat(OptionFormat.Level)
|
||||
.SetHeader(true);
|
||||
EnableKillerLeftCommand = BooleanOptionItem.Create(44428, "EnableKillerLeftCommand", true, TabGroup.SystemSettings, false)
|
||||
.SetColor(Color.green);
|
||||
SeeEjectedRolesInMeeting = BooleanOptionItem.Create(44429, "SeeEjectedRolesInMeeting", true, TabGroup.SystemSettings, false)
|
||||
.SetColor(Color.green);
|
||||
KickAndroidPlayer = BooleanOptionItem.Create(19301, "KickAndroidPlayer", false, TabGroup.SystemSettings, false);
|
||||
KickPlayerFriendCodeNotExist = BooleanOptionItem.Create(19302, "KickPlayerFriendCodeNotExist", false, TabGroup.SystemSettings, true);
|
||||
ApplyDenyNameList = BooleanOptionItem.Create(19303, "ApplyDenyNameList", true, TabGroup.SystemSettings, true);
|
||||
@@ -2582,6 +2593,13 @@ public static class Options
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
.SetColor(new Color32(19, 188, 233, byte.MaxValue));
|
||||
|
||||
// Reset Doors After Meeting
|
||||
ResetDoorsEveryTurns = BooleanOptionItem.Create(22120, "ResetDoorsEveryTurns", false, TabGroup.GameSettings, false)
|
||||
.SetColor(new Color32(19, 188, 233, byte.MaxValue));
|
||||
// Reset Doors Mode
|
||||
DoorsResetMode = StringOptionItem.Create(22122, "DoorsResetMode", EnumHelper.GetAllNames<DoorsReset.ResetMode>(), 2, TabGroup.GameSettings, false)
|
||||
.SetColor(new Color32(19, 188, 233, byte.MaxValue))
|
||||
.SetParent(ResetDoorsEveryTurns);
|
||||
|
||||
LoadingPercentage = 70;
|
||||
|
||||
@@ -2603,15 +2621,25 @@ public static class Options
|
||||
LoadingPercentage = 71;
|
||||
|
||||
|
||||
// SabotageTimeControl
|
||||
SabotageTimeControl = BooleanOptionItem.Create(22400, "SabotageTimeControl", false, TabGroup.GameSettings, false)
|
||||
// Sabotage Cooldown Control
|
||||
SabotageCooldownControl = BooleanOptionItem.Create(22400, "SabotageCooldownControl", false, TabGroup.GameSettings, false)
|
||||
.SetColor(new Color32(243, 96, 96, byte.MaxValue))
|
||||
.SetGameMode(CustomGameMode.Standard);
|
||||
PolusReactorTimeLimit = FloatOptionItem.Create(22410, "PolusReactorTimeLimit", new(1f, 60f, 1f), 30f, TabGroup.GameSettings, false)
|
||||
SabotageCooldown = FloatOptionItem.Create(22405, "SabotageCooldown", new(1f, 60f, 1f), 30f, TabGroup.GameSettings, false)
|
||||
.SetParent(SabotageCooldownControl)
|
||||
.SetValueFormat(OptionFormat.Seconds)
|
||||
.SetGameMode(CustomGameMode.Standard);
|
||||
|
||||
// Sabotage Duration Control
|
||||
SabotageTimeControl = BooleanOptionItem.Create(22410, "SabotageTimeControl", false, TabGroup.GameSettings, false)
|
||||
.SetColor(new Color32(243, 96, 96, byte.MaxValue))
|
||||
.SetGameMode(CustomGameMode.Standard);
|
||||
|
||||
PolusReactorTimeLimit = FloatOptionItem.Create(22412, "PolusReactorTimeLimit", new(1f, 60f, 1f), 30f, TabGroup.GameSettings, false)
|
||||
.SetParent(SabotageTimeControl)
|
||||
.SetValueFormat(OptionFormat.Seconds)
|
||||
.SetGameMode(CustomGameMode.Standard);
|
||||
AirshipReactorTimeLimit = FloatOptionItem.Create(22411, "AirshipReactorTimeLimit", new(1f, 90f, 1f), 60f, TabGroup.GameSettings, false)
|
||||
AirshipReactorTimeLimit = FloatOptionItem.Create(22414, "AirshipReactorTimeLimit", new(1f, 90f, 1f), 60f, TabGroup.GameSettings, false)
|
||||
.SetParent(SabotageTimeControl)
|
||||
.SetValueFormat(OptionFormat.Seconds)
|
||||
.SetGameMode(CustomGameMode.Standard);
|
||||
@@ -3162,7 +3190,9 @@ public static class Options
|
||||
|
||||
LoadingPercentage = 100;
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
OptionSaver.Load();
|
||||
|
||||
IsLoaded = true;
|
||||
}
|
||||
|
||||
@@ -26,12 +26,8 @@ public class BooleanOptionItem : OptionItem
|
||||
}
|
||||
|
||||
// Setter
|
||||
public override void SetValue(int value)
|
||||
public override void SetValue(int value, bool doSync = true)
|
||||
{
|
||||
base.SetValue(value % 2 == 0 ? 0 : 1);
|
||||
}
|
||||
public override void SetValueNoRpc(int value)
|
||||
{
|
||||
base.SetValueNoRpc(value % 2 == 0 ? 0 : 1);
|
||||
base.SetValue(value % 2 == 0 ? 0 : 1, doSync);
|
||||
}
|
||||
}
|
||||
@@ -31,12 +31,8 @@ public class FloatOptionItem : OptionItem
|
||||
=> Rule.RepeatIndex(base.GetValue());
|
||||
|
||||
// Setter
|
||||
public override void SetValue(int value)
|
||||
public override void SetValue(int value, bool doSync = true)
|
||||
{
|
||||
base.SetValue(Rule.RepeatIndex(value));
|
||||
}
|
||||
public override void SetValueNoRpc(int value)
|
||||
{
|
||||
base.SetValueNoRpc(Rule.RepeatIndex(value));
|
||||
base.SetValue(Rule.RepeatIndex(value), doSync);
|
||||
}
|
||||
}
|
||||
@@ -31,12 +31,8 @@ public class IntegerOptionItem : OptionItem
|
||||
=> Rule.RepeatIndex(base.GetValue());
|
||||
|
||||
// Setter
|
||||
public override void SetValue(int value)
|
||||
public override void SetValue(int value, bool doSync = true)
|
||||
{
|
||||
base.SetValue(Rule.RepeatIndex(value));
|
||||
}
|
||||
public override void SetValueNoRpc(int value)
|
||||
{
|
||||
base.SetValueNoRpc(Rule.RepeatIndex(value));
|
||||
base.SetValue(Rule.RepeatIndex(value), doSync);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using BepInEx.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using TOHE.Modules;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TOHE;
|
||||
@@ -10,7 +10,9 @@ public abstract class OptionItem
|
||||
{
|
||||
#region static
|
||||
public static IReadOnlyList<OptionItem> AllOptions => _allOptions;
|
||||
private static List<OptionItem> _allOptions = new();
|
||||
private static List<OptionItem> _allOptions = new(1024);
|
||||
public static IReadOnlyDictionary<int, OptionItem> FastOptions => _fastOptions;
|
||||
private static Dictionary<int, OptionItem> _fastOptions = new(1024);
|
||||
public static int CurrentPreset { get; set; }
|
||||
#endregion
|
||||
|
||||
@@ -39,24 +41,18 @@ public abstract class OptionItem
|
||||
}
|
||||
private Dictionary<string, string> _replacementDictionary;
|
||||
|
||||
// 設定値情報 (オプションの値に関わる情報)
|
||||
public int[] AllValues { get; private set; } = new int[NumPresets];
|
||||
public int CurrentValue
|
||||
{
|
||||
get => GetValue();
|
||||
set => SetValue(value);
|
||||
}
|
||||
public int SingleValue { get; private set; }
|
||||
|
||||
// 親子情報
|
||||
public OptionItem Parent { get; private set; }
|
||||
public List<OptionItem> Children;
|
||||
|
||||
// 内部情報 (外部から参照することを想定していない情報)
|
||||
public ConfigEntry<int> CurrentEntry =>
|
||||
IsSingleValue ? singleEntry : AllConfigEntries[CurrentPreset];
|
||||
private ConfigEntry<int>[] AllConfigEntries;
|
||||
private ConfigEntry<int> singleEntry;
|
||||
|
||||
|
||||
public OptionBehaviour OptionBehaviour;
|
||||
|
||||
// イベント
|
||||
@@ -86,30 +82,32 @@ public abstract class OptionItem
|
||||
// オブジェクト初期化
|
||||
Children = new();
|
||||
|
||||
// ConfigEntry初期化
|
||||
AllConfigEntries = new ConfigEntry<int>[5];
|
||||
if (Id == 0)
|
||||
// デフォルト値に設定
|
||||
if (Id == PresetId)
|
||||
{
|
||||
singleEntry = Main.Instance.Config.Bind("Current Preset", id.ToString(), DefaultValue);
|
||||
CurrentPreset = singleEntry.Value;
|
||||
SingleValue = DefaultValue;
|
||||
CurrentPreset = SingleValue;
|
||||
}
|
||||
else if (IsSingleValue)
|
||||
{
|
||||
singleEntry = Main.Instance.Config.Bind("SingleEntryOptions", id.ToString(), DefaultValue);
|
||||
SingleValue = DefaultValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 5; i++)
|
||||
for (int i = 0; i < NumPresets; i++)
|
||||
{
|
||||
AllConfigEntries[i] = Main.Instance.Config.Bind($"Preset{i + 1}", id.ToString(), DefaultValue);
|
||||
AllValues[i] = DefaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
if (AllOptions.Any(op => op.Id == id))
|
||||
if (_fastOptions.TryAdd(id, this))
|
||||
{
|
||||
Logger.Error($"Repeat option ID:{id}", "OptionItem");
|
||||
_allOptions.Add(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Error($"Duplicate ID: {id}", "OptionItem");
|
||||
}
|
||||
_allOptions.Add(this);
|
||||
}
|
||||
|
||||
// Setter
|
||||
@@ -166,7 +164,7 @@ public abstract class OptionItem
|
||||
{
|
||||
return ApplyFormat(CurrentValue.ToString());
|
||||
}
|
||||
public virtual int GetValue() => CurrentEntry.Value;
|
||||
public virtual int GetValue() => IsSingleValue ? SingleValue : AllValues[CurrentPreset];
|
||||
|
||||
// 旧IsHidden関数
|
||||
public virtual bool IsHiddenOn(CustomGameMode mode)
|
||||
@@ -190,22 +188,36 @@ public abstract class OptionItem
|
||||
opt.oldValue = opt.Value = CurrentValue;
|
||||
}
|
||||
}
|
||||
public virtual void SetValue(int value)
|
||||
public void SetValue(int afterValue, bool doSave, bool doSync = true)
|
||||
{
|
||||
int beforeValue = CurrentEntry.Value;
|
||||
int afterValue = CurrentEntry.Value = value;
|
||||
int beforeValue = CurrentValue;
|
||||
if (IsSingleValue)
|
||||
{
|
||||
SingleValue = afterValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
AllValues[CurrentPreset] = afterValue;
|
||||
}
|
||||
|
||||
CallUpdateValueEvent(beforeValue, afterValue);
|
||||
Refresh();
|
||||
RPC.SyncCustomSettingsRPCforOneOption(this);
|
||||
if (doSync)
|
||||
{
|
||||
SyncAllOptions();
|
||||
}
|
||||
if (doSave)
|
||||
{
|
||||
OptionSaver.Save();
|
||||
}
|
||||
}
|
||||
public virtual void SetValueNoRpc(int value)
|
||||
public virtual void SetValue(int afterValue, bool doSync = true)
|
||||
{
|
||||
int beforeValue = CurrentEntry.Value;
|
||||
int afterValue = CurrentEntry.Value = value;
|
||||
|
||||
CallUpdateValueEvent(beforeValue, afterValue);
|
||||
Refresh();
|
||||
SetValue(afterValue, true, doSync);
|
||||
}
|
||||
public void SetAllValues(int[] values)
|
||||
{
|
||||
AllValues = values;
|
||||
}
|
||||
|
||||
// 演算子オーバーロード
|
||||
@@ -217,7 +229,7 @@ public abstract class OptionItem
|
||||
// 全体操作用
|
||||
public static void SwitchPreset(int newPreset)
|
||||
{
|
||||
CurrentPreset = Math.Clamp(newPreset, 0, 4);
|
||||
CurrentPreset = Math.Clamp(newPreset, 0, NumPresets - 1);
|
||||
|
||||
for (int i = 0; i < AllOptions.Count; i++)
|
||||
{
|
||||
@@ -227,7 +239,7 @@ public abstract class OptionItem
|
||||
|
||||
SyncAllOptions();
|
||||
}
|
||||
public static void SyncAllOptions(int targetId = -1)
|
||||
public static void SyncAllOptions()
|
||||
{
|
||||
if (
|
||||
Main.AllPlayerControls.Count() <= 1 ||
|
||||
@@ -235,7 +247,7 @@ public abstract class OptionItem
|
||||
PlayerControl.LocalPlayer == null
|
||||
) return;
|
||||
|
||||
RPC.SyncCustomSettingsRPC(targetId);
|
||||
RPC.SyncCustomSettingsRPC();
|
||||
}
|
||||
|
||||
|
||||
@@ -249,7 +261,7 @@ public abstract class OptionItem
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error($"[{Name}] UpdateValueEventの呼び出し時に例外が発生しました", "OptionItem.UpdateValueEvent");
|
||||
Logger.Error($"[{Name}] - Exception occurred when calling UpdateValueEvent", "OptionItem.UpdateValueEvent");
|
||||
Logger.Exception(ex, "OptionItem.UpdateValueEvent");
|
||||
}
|
||||
}
|
||||
@@ -264,6 +276,9 @@ public abstract class OptionItem
|
||||
BeforeValue = beforeValue;
|
||||
}
|
||||
}
|
||||
|
||||
public const int NumPresets = 5;
|
||||
public const int PresetId = 0;
|
||||
}
|
||||
|
||||
public enum TabGroup
|
||||
|
||||
@@ -9,7 +9,7 @@ public class PresetOptionItem : OptionItem
|
||||
public PresetOptionItem(int defaultValue, TabGroup tab)
|
||||
: base(0, "Preset", defaultValue, tab, true)
|
||||
{
|
||||
Rule = (0, 4, 1);
|
||||
Rule = (0, NumPresets - 1, 1);
|
||||
}
|
||||
public static PresetOptionItem Create(int defaultValue, TabGroup tab)
|
||||
{
|
||||
@@ -35,9 +35,9 @@ public class PresetOptionItem : OptionItem
|
||||
=> Rule.RepeatIndex(base.GetValue());
|
||||
|
||||
// Setter
|
||||
public override void SetValue(int value)
|
||||
public override void SetValue(int value, bool doSync = true)
|
||||
{
|
||||
base.SetValue(Rule.RepeatIndex(value));
|
||||
base.SetValue(Rule.RepeatIndex(value), doSync);
|
||||
SwitchPreset(Rule.RepeatIndex(value));
|
||||
}
|
||||
}
|
||||
@@ -47,12 +47,8 @@ public class StringOptionItem : OptionItem
|
||||
=> Rule.RepeatIndex(base.GetValue());
|
||||
|
||||
// Setter
|
||||
public override void SetValue(int value)
|
||||
public override void SetValue(int value, bool doSync = true)
|
||||
{
|
||||
base.SetValue(Rule.RepeatIndex(value));
|
||||
}
|
||||
public override void SetValueNoRpc(int value)
|
||||
{
|
||||
base.SetValueNoRpc(Rule.RepeatIndex(value));
|
||||
base.SetValue(Rule.RepeatIndex(value), doSync);
|
||||
}
|
||||
}
|
||||
@@ -28,12 +28,4 @@ public class TextOptionItem : OptionItem
|
||||
{
|
||||
return Translator.GetString(Name);
|
||||
}
|
||||
|
||||
// Setter
|
||||
public override void SetValue(int value)
|
||||
{
|
||||
}
|
||||
public override void SetValueNoRpc(int value)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace TOHE.Modules;
|
||||
|
||||
// https://github.com/tukasa0001/TownOfHost/blob/main/Modules/OptionSaver.cs
|
||||
public static class OptionSaver
|
||||
{
|
||||
private static readonly DirectoryInfo SaveDataDirectoryInfo = new("./TOHE-DATA/SaveData/");
|
||||
private static readonly FileInfo OptionSaverFileInfo = new($"{SaveDataDirectoryInfo.FullName}/Options.json");
|
||||
private static readonly LogHandler logger = Logger.Handler(nameof(OptionSaver));
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
if (!SaveDataDirectoryInfo.Exists)
|
||||
{
|
||||
SaveDataDirectoryInfo.Create();
|
||||
SaveDataDirectoryInfo.Attributes |= FileAttributes.Hidden;
|
||||
}
|
||||
if (!OptionSaverFileInfo.Exists)
|
||||
{
|
||||
OptionSaverFileInfo.Create().Dispose();
|
||||
}
|
||||
}
|
||||
/// <summary>現在のオプションからjsonシリアライズ用のオブジェクトを生成</summary>
|
||||
private static SerializableOptionsData GenerateOptionsData()
|
||||
{
|
||||
Dictionary<int, int> singleOptions = new();
|
||||
Dictionary<int, int[]> presetOptions = new();
|
||||
for (int i = 0; i < OptionItem.AllOptions.Count; i++)
|
||||
{
|
||||
OptionItem option = OptionItem.AllOptions[i];
|
||||
if (option.IsSingleValue)
|
||||
{
|
||||
if (!singleOptions.TryAdd(option.Id, option.SingleValue))
|
||||
{
|
||||
logger.Warn($"Duplicate SingleOption ID: {option.Id}");
|
||||
}
|
||||
}
|
||||
else if (!presetOptions.TryAdd(option.Id, option.AllValues))
|
||||
{
|
||||
logger.Warn($"Duplicate preset option ID: {option.Id}");
|
||||
}
|
||||
}
|
||||
return new SerializableOptionsData
|
||||
{
|
||||
Version = Version,
|
||||
SingleOptions = singleOptions,
|
||||
PresetOptions = presetOptions,
|
||||
};
|
||||
}
|
||||
/// <summary>デシリアライズされたオブジェクトを読み込み,オプション値を設定</summary>
|
||||
private static void LoadOptionsData(SerializableOptionsData serializableOptionsData)
|
||||
{
|
||||
if (serializableOptionsData.Version != Version)
|
||||
{
|
||||
// 今後バージョン間の移行方法を用意する場合,ここでバージョンごとの変換メソッドに振り分ける
|
||||
logger.Info($"読み込まれたオプションのバージョン {serializableOptionsData.Version} が現在のバージョン {Version} と一致しないためデフォルト値で上書きします");
|
||||
Save();
|
||||
return;
|
||||
}
|
||||
Dictionary<int, int> singleOptions = serializableOptionsData.SingleOptions;
|
||||
Dictionary<int, int[]> presetOptions = serializableOptionsData.PresetOptions;
|
||||
foreach (var singleOption in singleOptions)
|
||||
{
|
||||
var id = singleOption.Key;
|
||||
var value = singleOption.Value;
|
||||
if (OptionItem.FastOptions.TryGetValue(id, out var optionItem))
|
||||
{
|
||||
optionItem.SetValue(value, doSave: false);
|
||||
}
|
||||
}
|
||||
foreach (var presetOption in presetOptions)
|
||||
{
|
||||
var id = presetOption.Key;
|
||||
var values = presetOption.Value;
|
||||
if (OptionItem.FastOptions.TryGetValue(id, out var optionItem))
|
||||
{
|
||||
optionItem.SetAllValues(values);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>現在のオプションをjsonファイルに保存</summary>
|
||||
public static void Save()
|
||||
{
|
||||
if (AmongUsClient.Instance != null && !AmongUsClient.Instance.AmHost) return;
|
||||
|
||||
var jsonString = JsonSerializer.Serialize(GenerateOptionsData(), new JsonSerializerOptions { WriteIndented = true, });
|
||||
File.WriteAllText(OptionSaverFileInfo.FullName, jsonString);
|
||||
}
|
||||
/// <summary>jsonファイルからオプションを読み込み</summary>
|
||||
public static void Load()
|
||||
{
|
||||
var jsonString = File.ReadAllText(OptionSaverFileInfo.FullName);
|
||||
// 空なら読み込まず,デフォルト値をセーブする
|
||||
if (jsonString.Length <= 0)
|
||||
{
|
||||
logger.Info("オプションデータが空のためデフォルト値を保存");
|
||||
Save();
|
||||
return;
|
||||
}
|
||||
LoadOptionsData(JsonSerializer.Deserialize<SerializableOptionsData>(jsonString));
|
||||
}
|
||||
|
||||
/// <summary>json保存に適したオプションデータ</summary>
|
||||
public class SerializableOptionsData
|
||||
{
|
||||
public int Version { get; init; }
|
||||
/// <summary>プリセット外のオプション</summary>
|
||||
public Dictionary<int, int> SingleOptions { get; init; }
|
||||
/// <summary>プリセット内のオプション</summary>
|
||||
public Dictionary<int, int[]> PresetOptions { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>オプションの形式に互換性のない変更(プリセット数変更など)を加えるときはここの数字を上げる</summary>
|
||||
public static readonly int Version = 0;
|
||||
}
|
||||
+17
-59
@@ -47,7 +47,7 @@ enum CustomRPC
|
||||
|
||||
// TOHE
|
||||
AntiBlackout,
|
||||
RestTOHESetting,
|
||||
//RestTOHESetting,
|
||||
PlayCustomSound,
|
||||
SetKillTimer,
|
||||
SyncAllPlayerNames,
|
||||
@@ -259,20 +259,11 @@ internal class RPCHandlerPatch
|
||||
RPC.RpcVersionCheck();
|
||||
break;
|
||||
case CustomRPC.SyncCustomSettings:
|
||||
if (AmongUsClient.Instance.AmHost) break;
|
||||
List<OptionItem> list = new();
|
||||
var startAmount = reader.ReadInt32();
|
||||
var lastAmount = reader.ReadInt32();
|
||||
for (var i = startAmount; i < OptionItem.AllOptions.Count && i <= lastAmount; i++)
|
||||
list.Add(OptionItem.AllOptions[i]);
|
||||
Logger.Info($"{startAmount}-{lastAmount}:{list.Count}/{OptionItem.AllOptions.Count}", "SyncCustomSettings");
|
||||
for (int i1 = 0; i1 < list.Count; i1++)
|
||||
for (int i = 0; i < OptionItem.AllOptions.Count; i++)
|
||||
{
|
||||
OptionItem co = list[i1];
|
||||
OptionItem co = OptionItem.AllOptions[i];
|
||||
co.SetValue(reader.ReadInt32());
|
||||
}
|
||||
|
||||
OptionShower.GetText();
|
||||
break;
|
||||
case CustomRPC.SetDeathReason:
|
||||
RPC.GetDeathReason(reader);
|
||||
@@ -451,10 +442,10 @@ internal class RPCHandlerPatch
|
||||
case CustomRPC.SetQuickShooterShotLimit:
|
||||
QuickShooter.ReceiveRPC(reader);
|
||||
break;
|
||||
case CustomRPC.RestTOHESetting:
|
||||
OptionItem.AllOptions.ToArray().Where(x => x.Id > 0).Do(x => x.SetValueNoRpc(x.DefaultValue));
|
||||
OptionShower.GetText();
|
||||
break;
|
||||
//case CustomRPC.RestTOHESetting:
|
||||
// OptionItem.AllOptions.ToArray().Where(x => x.Id > 0).Do(x => x.SetValueNoRpc(x.DefaultValue));
|
||||
// OptionShower.GetText();
|
||||
// break;
|
||||
case CustomRPC.SetEraseLimit:
|
||||
Eraser.ReceiveRPC(reader);
|
||||
break;
|
||||
@@ -577,9 +568,9 @@ internal class RPCHandlerPatch
|
||||
case CustomRPC.SetVultureArrow:
|
||||
Vulture.ReceiveRPC(reader);
|
||||
break;
|
||||
case CustomRPC.DoPoison:
|
||||
Baker.ReceiveRPC(reader);
|
||||
break;
|
||||
//case CustomRPC.DoPoison:
|
||||
// Baker.ReceiveRPC(reader);
|
||||
// break;
|
||||
case CustomRPC.SetCleanserCleanLimit:
|
||||
Cleanser.ReceiveRPC(reader);
|
||||
break;
|
||||
@@ -611,47 +602,14 @@ internal class RPCHandlerPatch
|
||||
internal static class RPC
|
||||
{
|
||||
//来源:https://github.com/music-discussion/TownOfHost-TheOtherRoles/blob/main/Modules/RPC.cs
|
||||
public static void SyncCustomSettingsRPC(int targetId = -1)
|
||||
public static void SyncCustomSettingsRPC()
|
||||
{
|
||||
if (targetId != -1)
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, 80, Hazel.SendOption.Reliable, -1);
|
||||
foreach (var co in OptionItem.AllOptions)
|
||||
{
|
||||
var client = Utils.GetClientById(targetId);
|
||||
if (client == null || client.Character == null || !Main.playerVersion.ContainsKey(client.Character.PlayerId)) return;
|
||||
}
|
||||
if (!AmongUsClient.Instance.AmHost || PlayerControl.AllPlayerControls.Count <= 1 || (AmongUsClient.Instance.AmHost == false && PlayerControl.LocalPlayer == null)) return;
|
||||
var amount = OptionItem.AllOptions.Count;
|
||||
int divideBy = amount / 10;
|
||||
for (var i = 0; i <= 10; i++)
|
||||
SyncOptionsBetween(i * divideBy, (i + 1) * divideBy, targetId);
|
||||
}
|
||||
public static void SyncCustomSettingsRPCforOneOption(OptionItem option)
|
||||
{
|
||||
List<OptionItem> allOptions = new(OptionItem.AllOptions);
|
||||
var placement = allOptions.IndexOf(option);
|
||||
if (placement != -1)
|
||||
SyncOptionsBetween(placement, placement);
|
||||
}
|
||||
static void SyncOptionsBetween(int startAmount, int lastAmount, int targetId = -1)
|
||||
{
|
||||
if (targetId != -1)
|
||||
{
|
||||
var client = Utils.GetClientById(targetId);
|
||||
if (client == null || client.Character == null || !Main.playerVersion.ContainsKey(client.Character.PlayerId)) return;
|
||||
}
|
||||
if (!AmongUsClient.Instance.AmHost || PlayerControl.AllPlayerControls.Count <= 1 || (AmongUsClient.Instance.AmHost == false && PlayerControl.LocalPlayer == null)) return;
|
||||
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, 80, SendOption.Reliable, targetId);
|
||||
List<OptionItem> list = new();
|
||||
writer.Write(startAmount);
|
||||
writer.Write(lastAmount);
|
||||
for (var i = startAmount; i < OptionItem.AllOptions.Count && i <= lastAmount; i++)
|
||||
list.Add(OptionItem.AllOptions[i]);
|
||||
Logger.Info($"{startAmount}-{lastAmount}:{list.Count}/{OptionItem.AllOptions.Count}", "SyncCustomSettings");
|
||||
for (int i1 = 0; i1 < list.Count; i1++)
|
||||
{
|
||||
OptionItem co = list[i1];
|
||||
writer.Write(co.GetValue());
|
||||
}
|
||||
|
||||
AmongUsClient.Instance.FinishRpcImmediately(writer);
|
||||
}
|
||||
public static void PlaySoundRPC(byte PlayerID, Sounds sound)
|
||||
@@ -949,9 +907,9 @@ internal static class RPC
|
||||
case CustomRoles.ParityCop:
|
||||
ParityCop.Add(targetId);
|
||||
break;
|
||||
case CustomRoles.Baker:
|
||||
Baker.Add(targetId);
|
||||
break;
|
||||
//case CustomRoles.Baker:
|
||||
// Baker.Add(targetId);
|
||||
// break;
|
||||
case CustomRoles.Councillor:
|
||||
Councillor.Add(targetId);
|
||||
break;
|
||||
|
||||
+25
-10
@@ -467,7 +467,7 @@ public static class Utils
|
||||
case CustomRoles.Jester:
|
||||
//case CustomRoles.Pirate:
|
||||
// case CustomRoles.Baker:
|
||||
case CustomRoles.Famine:
|
||||
//case CustomRoles.Famine:
|
||||
//case CustomRoles.NWitch:
|
||||
case CustomRoles.Mario:
|
||||
case CustomRoles.Vulture:
|
||||
@@ -521,7 +521,7 @@ public static class Utils
|
||||
case CustomRoles.Convict:
|
||||
case CustomRoles.Opportunist:
|
||||
case CustomRoles.Phantom:
|
||||
case CustomRoles.Baker:
|
||||
//case CustomRoles.Baker:
|
||||
// case CustomRoles.Famine:
|
||||
if (ForRecompute)
|
||||
hasTasks = false;
|
||||
@@ -1326,15 +1326,32 @@ public static class Utils
|
||||
var sb = new StringBuilder();
|
||||
if (intro)
|
||||
{
|
||||
sb.Append("<size=40%>");
|
||||
sb.Append("<size=15%>");
|
||||
for (int i = 0; i < SubRoles.Count; i++)
|
||||
{
|
||||
CustomRoles role = SubRoles[i];
|
||||
if (role is CustomRoles.NotAssigned or CustomRoles.LastImpostor) continue;
|
||||
if (role is CustomRoles.NotAssigned or CustomRoles.LastImpostor) SubRoles.Remove(SubRoles[i]);
|
||||
}
|
||||
if (SubRoles.Count == 1)
|
||||
{
|
||||
CustomRoles role = SubRoles[0];
|
||||
|
||||
var RoleText = ColorString(GetRoleColor(role), GetRoleName(role));
|
||||
sb.Append($"{ColorString(Color.gray, "\nModifier: ")}{RoleText}");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append($"{ColorString(Color.gray, "\nModifiers: ")}");
|
||||
for (int i = 0; i < SubRoles.Count; i++)
|
||||
{
|
||||
if (i != 0) sb.Append(", ");
|
||||
CustomRoles role = SubRoles[i];
|
||||
if (role is CustomRoles.NotAssigned or CustomRoles.LastImpostor) continue;
|
||||
|
||||
var RoleText = ColorString(GetRoleColor(role), GetRoleName(role));
|
||||
sb.Append($"{RoleText}");
|
||||
}
|
||||
}
|
||||
sb.Append("</size>");
|
||||
}
|
||||
else if (!summary)
|
||||
@@ -1747,8 +1764,8 @@ public static class Utils
|
||||
//呪われている場合
|
||||
SelfMark.Append(Witch.GetSpelledMark(seer.PlayerId, isForMeeting));
|
||||
SelfMark.Append(HexMaster.GetHexedMark(seer.PlayerId, isForMeeting));
|
||||
if (Baker.IsPoisoned(seer) && isForMeeting && seer.IsAlive())
|
||||
SelfMark.Append(ColorString(GetRoleColor(CustomRoles.Famine), "θ"));
|
||||
//if (Baker.IsPoisoned(seer) && isForMeeting && seer.IsAlive())
|
||||
// SelfMark.Append(ColorString(GetRoleColor(CustomRoles.Famine), "θ"));
|
||||
|
||||
|
||||
//如果是大明星
|
||||
@@ -2065,6 +2082,7 @@ public static class Utils
|
||||
(target.Is(CustomRoles.Doctor) && !target.GetCustomRole().IsEvilAddons() && Options.DoctorVisibleToEveryone.GetBool()) ||
|
||||
(target.Is(CustomRoles.Mayor) && Options.MayorRevealWhenDoneTasks.GetBool() && target.GetPlayerTaskState().IsTaskFinished) ||
|
||||
(seer.Is(CustomRoleTypes.Crewmate) && target.Is(CustomRoles.Marshall) && target.GetPlayerTaskState().IsTaskFinished) ||
|
||||
(Main.PlayerStates[target.PlayerId].deathReason == PlayerState.DeathReason.Vote && Options.SeeEjectedRolesInMeeting.GetBool()) ||
|
||||
Totocalcio.KnowRole(seer, target) ||
|
||||
Romantic.KnowRole(seer, target) ||
|
||||
Lawyer.KnowRole(seer, target) ||
|
||||
@@ -2358,11 +2376,8 @@ public static class Utils
|
||||
|
||||
if (Options.AirshipVariableElectrical.GetBool())
|
||||
AirshipElectricalDoors.Initialize();
|
||||
/* if (Options.DiseasedCDReset.GetBool())
|
||||
Main.KilledDiseased.Clear();
|
||||
if (Options.AntidoteCDReset.GetBool())
|
||||
Main.KilledAntidote.Clear(); */
|
||||
|
||||
DoorsReset.ResetDoors();
|
||||
}
|
||||
public static void AfterPlayerDeathTasks(PlayerControl target, bool onMeeting = false)
|
||||
{
|
||||
|
||||
@@ -152,3 +152,15 @@
|
||||
> - Ideas for some roles
|
||||
> - Customize Main Menu
|
||||
> - Reference: Auto Play Again
|
||||
>
|
||||
|
||||
### :star: [Stellar Roles](https://github.com/Mr-Fluuff/StellarRolesAU)
|
||||
>
|
||||
> - Many role ideas (this mod is seriously amazing)
|
||||
> - Reference: Some custom sounds and button images
|
||||
>
|
||||
|
||||
### :star: [TOHEX](https://github.com/TOHEX-Official/TownOfHostEdited-Xi)
|
||||
>
|
||||
> - Provided role: Swapper
|
||||
>
|
||||
@@ -5,6 +5,11 @@ VisualStudioVersion = 17.4.33403.182
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TOHE", "TOHE.csproj", "{807AD310-21DA-4160-9D72-926745B02A85}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DBDFE762-E378-4B3D-8BB3-3F4F13C92ADB}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
||||
@@ -112,7 +112,7 @@ public class Main : BasePlugin
|
||||
public static List<byte> DemolitionistDead = new();
|
||||
public static Dictionary<byte, long> ExpressSpeedUp = new();
|
||||
public static float ExpressSpeedNormal;
|
||||
public static List<Vent> BlockedVents = new();
|
||||
public static List<int> BlockedVents = new();
|
||||
public static float VentguardNumberOfAbilityUses = 0;
|
||||
public static List<byte> WorkaholicAlive = new();
|
||||
public static List<byte> SpeedrunnerAlive = new();
|
||||
@@ -423,8 +423,8 @@ public class Main : BasePlugin
|
||||
{CustomRoles.Traitor, "#BA2E05"},
|
||||
{CustomRoles.Vulture, "#556B2F"},
|
||||
{CustomRoles.Medusa, "#9900CC"},
|
||||
{CustomRoles.Baker, "#b58428"},
|
||||
{CustomRoles.Famine, "#cb4d4d"},
|
||||
//{CustomRoles.Baker, "#b58428"},
|
||||
//{CustomRoles.Famine, "#cb4d4d"},
|
||||
{CustomRoles.Spiritcaller, "#003366"},
|
||||
{CustomRoles.EvilSpirit, "#003366"},
|
||||
{CustomRoles.Convict, "#ff1919"},
|
||||
@@ -749,8 +749,8 @@ public enum CustomRoles
|
||||
Pestilence,
|
||||
Medusa,
|
||||
Sidekick,
|
||||
Baker,
|
||||
Famine,
|
||||
//Baker,
|
||||
//Famine,
|
||||
Spiritcaller,
|
||||
Amnesiac,
|
||||
Doomsayer,
|
||||
@@ -873,7 +873,7 @@ public enum CustomWinner
|
||||
Vulture = CustomRoles.Vulture,
|
||||
Pestilence = CustomRoles.Pestilence,
|
||||
Medusa = CustomRoles.Medusa,
|
||||
Famine = CustomRoles.Famine,
|
||||
//Famine = CustomRoles.Famine,
|
||||
Spiritcaller = CustomRoles.Spiritcaller,
|
||||
Glitch = CustomRoles.Glitch,
|
||||
Plaguebearer = CustomRoles.PlagueBearer,
|
||||
|
||||
Reference in new issue
Block a user