mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-21 21:43:34 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
087fe9288d | ||
|
|
817c786c2f | ||
|
|
ab3b2e517d | ||
|
|
16170126da | ||
|
|
cb8b161cac | ||
|
|
b1ef23682e | ||
|
|
23c381e603 | ||
|
|
474513189c | ||
|
|
cffeff8e64 |
No files matched your search
@@ -1,5 +1,4 @@
|
||||
using AmongUs.GameOptions;
|
||||
using HarmonyLib;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -82,6 +81,8 @@ internal class CustomRoleSelector
|
||||
|
||||
foreach (var id in Main.SetRoles.Keys.Where(id => Utils.GetPlayerById(id) == null).ToArray()) Main.SetRoles.Remove(id);
|
||||
|
||||
Dictionary<CustomRoles, (int ASSIGNED, int COUNT)> RoleCounts = [];
|
||||
|
||||
System.Collections.IList list = Enum.GetValues(typeof(CustomRoles));
|
||||
for (int i1 = 0; i1 < list.Count; i1++)
|
||||
{
|
||||
@@ -100,10 +101,14 @@ internal class CustomRoleSelector
|
||||
case CustomRoles.NotAssigned:
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < role.GetCount(); i++)
|
||||
var roleCount = role.GetCount();
|
||||
RoleCounts[role] = (0, roleCount);
|
||||
for (int i = 0; i < roleCount; i++)
|
||||
roleList.Add(role);
|
||||
}
|
||||
|
||||
Logger.Info(string.Join(", ", RoleCounts.Select(x => $"{x.Key}: {x.Value.COUNT}")), "RoleCounts");
|
||||
|
||||
// Career setting: priority
|
||||
for (int i2 = 0; i2 < roleList.Count; i2++)
|
||||
{
|
||||
@@ -168,9 +173,22 @@ internal class CustomRoleSelector
|
||||
for (int i = 0; i < optImpNum; i++)
|
||||
{
|
||||
ImpOnList.Add(CustomRoles.ImpostorTOHE);
|
||||
Logger.Warn("No Impostor roles are enabled, adding a vanilla impostor to the game", "CustomRoleSelector");
|
||||
}
|
||||
}
|
||||
|
||||
LogRoleChancePool();
|
||||
|
||||
void LogRoleChancePool()
|
||||
{
|
||||
Logger.Info(string.Join(", ", ImpRateList.Select(p => p.ToString())), "ImpChancePool");
|
||||
Logger.Info(string.Join(", ", NeutralKillingRateList.Select(p => p.ToString())), "NKChancePool");
|
||||
Logger.Info(string.Join(", ", NonNeutralKillingRateList.Select(p => p.ToString())), "NNKChancePool");
|
||||
Logger.Info(string.Join(", ", roleRateList.Select(p => p.ToString())), "CrewChancePool");
|
||||
|
||||
Logger.Info(string.Join(", ", RoleCounts.Select(p => $"{p.Key}: {p.Value.ASSIGNED}/{p.Value.COUNT}")), "AssignedCount");
|
||||
}
|
||||
|
||||
// Assign roles set to ALWAYS (impostors)
|
||||
while (ImpOnList.Count > 0)
|
||||
{
|
||||
@@ -188,10 +206,12 @@ internal class CustomRoleSelector
|
||||
while (ImpRateList.Count > 0)
|
||||
{
|
||||
var select = ImpRateList[rd.Next(0, ImpRateList.Count)];
|
||||
while (ImpRateList.Contains(select)) ImpRateList.Remove(select);
|
||||
var (ASSIGNED, COUNT) = RoleCounts[select];
|
||||
rolesToAssign.Add(select);
|
||||
readyRoleNum++;
|
||||
Logger.Info(select.ToString() + " added to the impostor role waiting list", "CustomRoleSelector");
|
||||
RoleCounts[select] = (ASSIGNED + 1, COUNT);
|
||||
if (ASSIGNED + 1 >= COUNT) while (ImpRateList.Contains(select)) ImpRateList.Remove(select);
|
||||
if (readyRoleNum >= playerCount) goto EndOfAssign;
|
||||
if (readyRoleNum >= optImpNum) break;
|
||||
}
|
||||
@@ -216,11 +236,13 @@ internal class CustomRoleSelector
|
||||
while (NonNeutralKillingRateList.Count > 0 && optNonNeutralKillingNum > 0)
|
||||
{
|
||||
var select = NonNeutralKillingRateList[rd.Next(0, NonNeutralKillingRateList.Count)];
|
||||
while (NonNeutralKillingRateList.Contains(select)) NonNeutralKillingRateList.Remove(select);
|
||||
var (ASSIGNED, COUNT) = RoleCounts[select];
|
||||
rolesToAssign.Add(select);
|
||||
readyRoleNum++;
|
||||
readyNonNeutralKillingNum += select.GetCount();
|
||||
Logger.Info(select.ToString() + " added to neutral role waiting list", "CustomRoleSelector");
|
||||
RoleCounts[select] = (ASSIGNED + 1, COUNT);
|
||||
if (ASSIGNED + 1 >= COUNT) while (NonNeutralKillingRateList.Contains(select)) NonNeutralKillingRateList.Remove(select);
|
||||
if (readyRoleNum >= playerCount) goto EndOfAssign;
|
||||
if (readyNonNeutralKillingNum >= optNonNeutralKillingNum) break;
|
||||
}
|
||||
@@ -245,11 +267,13 @@ internal class CustomRoleSelector
|
||||
while (NeutralKillingRateList.Count > 0 && optNeutralKillingNum > 0)
|
||||
{
|
||||
var select = NeutralKillingRateList[rd.Next(0, NeutralKillingRateList.Count)];
|
||||
while (NeutralKillingRateList.Contains(select)) NeutralKillingRateList.Remove(select);
|
||||
var (ASSIGNED, COUNT) = RoleCounts[select];
|
||||
rolesToAssign.Add(select);
|
||||
readyRoleNum++;
|
||||
readyNeutralKillingNum += select.GetCount();
|
||||
Logger.Info(select.ToString() + " added to neutral role waiting list", "CustomRoleSelector");
|
||||
RoleCounts[select] = (ASSIGNED + 1, COUNT);
|
||||
if (ASSIGNED + 1 >= COUNT) while (NeutralKillingRateList.Contains(select)) NeutralKillingRateList.Remove(select);
|
||||
if (readyRoleNum >= playerCount) goto EndOfAssign;
|
||||
if (readyNeutralKillingNum >= optNeutralKillingNum) break;
|
||||
}
|
||||
@@ -271,16 +295,20 @@ internal class CustomRoleSelector
|
||||
while (roleRateList.Count > 0)
|
||||
{
|
||||
var select = roleRateList[rd.Next(0, roleRateList.Count)];
|
||||
while (roleRateList.Contains(select)) roleRateList.Remove(select);
|
||||
var (ASSIGNED, COUNT) = RoleCounts[select];
|
||||
rolesToAssign.Add(select);
|
||||
readyRoleNum++;
|
||||
Logger.Info(select.ToString() + " joined the crew role waiting list", "CustomRoleSelector");
|
||||
RoleCounts[select] = (ASSIGNED + 1, COUNT);
|
||||
if (ASSIGNED + 1 >= COUNT) while (roleRateList.Contains(select)) roleRateList.Remove(select);
|
||||
if (readyRoleNum >= playerCount) goto EndOfAssign;
|
||||
}
|
||||
}
|
||||
|
||||
EndOfAssign:
|
||||
|
||||
LogRoleChancePool();
|
||||
|
||||
if (rd.Next(0, 100) < Options.SunnyboyChance.GetInt() && rolesToAssign.Remove(CustomRoles.Jester)) rolesToAssign.Add(CustomRoles.Sunnyboy);
|
||||
if (rd.Next(0, 100) < Sans.BardChance.GetInt() && rolesToAssign.Remove(CustomRoles.Sans)) rolesToAssign.Add(CustomRoles.Bard);
|
||||
if (rd.Next(0, 100) < Options.NukerChance.GetInt() && rolesToAssign.Remove(CustomRoles.Bomber)) rolesToAssign.Add(CustomRoles.Nuker);
|
||||
|
||||
@@ -93,6 +93,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Express => CustomRoles.Crewmate,
|
||||
CustomRoles.NiceEraser => CustomRoles.Crewmate,
|
||||
CustomRoles.TaskManager => CustomRoles.Crewmate,
|
||||
CustomRoles.Shiftguard => CustomRoles.Crewmate,
|
||||
CustomRoles.Mole => CustomRoles.Engineer,
|
||||
CustomRoles.Sentinel => Options.UsePets.GetBool() ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Electric => CustomRoles.Crewmate,
|
||||
@@ -229,6 +230,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Express => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.NiceEraser => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.TaskManager => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Shiftguard => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Mole => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Sentinel => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Electric => CustomRoles.CrewmateTOHE,
|
||||
@@ -1104,6 +1106,7 @@ internal static class CustomRolesHelper
|
||||
{
|
||||
return role is
|
||||
CustomRoles.Sheriff or
|
||||
CustomRoles.Admirer or
|
||||
CustomRoles.Medic or
|
||||
CustomRoles.CopyCat or
|
||||
//CustomRoles.Reverie or
|
||||
@@ -1129,6 +1132,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Mayor or
|
||||
CustomRoles.Paranoia or
|
||||
CustomRoles.Grenadier or
|
||||
CustomRoles.Veteran or
|
||||
CustomRoles.Lighter or
|
||||
CustomRoles.SecurityGuard or
|
||||
CustomRoles.DovesOfNeace or
|
||||
@@ -1137,6 +1141,11 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Sapper or
|
||||
CustomRoles.CameraMan or
|
||||
CustomRoles.NiceHacker or
|
||||
CustomRoles.Druid or
|
||||
CustomRoles.Tunneler or
|
||||
CustomRoles.Tornado or
|
||||
CustomRoles.Sentinel or
|
||||
CustomRoles.Lookout or
|
||||
CustomRoles.Sniper or
|
||||
CustomRoles.Warlock or
|
||||
CustomRoles.Assassin or
|
||||
@@ -1152,7 +1161,10 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Glitch or
|
||||
CustomRoles.Magician or
|
||||
CustomRoles.WeaponMaster or
|
||||
CustomRoles.Veteran;
|
||||
CustomRoles.Enderman or
|
||||
CustomRoles.Mycologist or
|
||||
CustomRoles.Hookshot or
|
||||
CustomRoles.Sprayer;
|
||||
}
|
||||
public static bool NeedUpdateOnLights(this CustomRoles role)
|
||||
{
|
||||
@@ -1774,7 +1786,7 @@ internal static class CustomRolesHelper
|
||||
_ => role.IsImpostorTeam() ? CountTypes.Impostor : CountTypes.Crew,
|
||||
};
|
||||
|
||||
public static bool HasSubRole(this PlayerControl pc) => Main.PlayerStates[pc.PlayerId].SubRoles.Any();
|
||||
public static bool HasSubRole(this PlayerControl pc) => Main.PlayerStates[pc.PlayerId].SubRoles.Count > 0;
|
||||
}
|
||||
public enum CustomRoleTypes
|
||||
{
|
||||
|
||||
@@ -5,18 +5,18 @@ namespace TOHE;
|
||||
|
||||
public static class CustomWinnerHolder
|
||||
{
|
||||
// 勝者のチームが格納されます。
|
||||
// リザルトの背景色の決定などに使用されます。
|
||||
// 注: この変数を変更する時、WinnerRoles・WinnerIdsを同時に変更しないと予期せぬ勝者が現れる可能性があります。
|
||||
// The winning team will be stored.
|
||||
// Used to determine background color of results, etc.
|
||||
// Note: When changing this variable, if you do not change WinnerRoles and WinnerIds at the same time, unexpected winners may appear.
|
||||
public static CustomWinner WinnerTeam;
|
||||
// 追加勝利するプレイヤーのチームが格納されます。
|
||||
// リザルトの表示に使用されます。
|
||||
// Stores the team of additional winning players.
|
||||
// Used to display results.
|
||||
public static HashSet<AdditionalWinners> AdditionalWinnerTeams;
|
||||
// 勝者の役職が格納され、この変数に格納されている役職のプレイヤーは全員勝利となります。
|
||||
// チームとなるニュートラルの処理に最適です。
|
||||
// The winning role is stored, and all players whose roles are stored in this variable win.
|
||||
// Ideal for handling team neutrals.
|
||||
public static HashSet<CustomRoles> WinnerRoles;
|
||||
// 勝者のPlayerIDが格納され、このIDを持つプレイヤーは全員勝利します。
|
||||
// 単独勝利するニュートラルの処理に最適です。
|
||||
// Stores the winner's PlayerID, all players with this ID win.
|
||||
// Ideal for handling neutrals that win alone.
|
||||
public static HashSet<byte> WinnerIds;
|
||||
|
||||
public static void Reset()
|
||||
@@ -31,20 +31,20 @@ public static class CustomWinnerHolder
|
||||
WinnerRoles.Clear();
|
||||
WinnerIds.Clear();
|
||||
}
|
||||
/// <summary><para>WinnerTeamに値を代入します。</para><para>すでに代入されている場合、AdditionalWinnerTeamsに追加します。</para></summary>
|
||||
/// <summary><para>Assign a value to WinnerTeam. </para><para>Add to AdditionalWinnerTeams if already assigned.</para></summary>
|
||||
public static void SetWinnerOrAdditonalWinner(CustomWinner winner)
|
||||
{
|
||||
if (WinnerTeam == CustomWinner.Default) WinnerTeam = winner;
|
||||
else AdditionalWinnerTeams.Add((AdditionalWinners)winner);
|
||||
}
|
||||
/// <summary><para>WinnerTeamに値を代入します。</para><para>すでに代入されている場合、既存の値をAdditionalWinnerTeamsに追加してから代入します。</para></summary>
|
||||
/// <summary><para>Assign a value to WinnerTeam. </para><para>If it is already assigned, add the existing value to AdditionalWinnerTeams and then assign it.</para></summary>
|
||||
public static void ShiftWinnerAndSetWinner(CustomWinner winner)
|
||||
{
|
||||
if (WinnerTeam != CustomWinner.Default)
|
||||
AdditionalWinnerTeams.Add((AdditionalWinners)WinnerTeam);
|
||||
WinnerTeam = winner;
|
||||
}
|
||||
/// <summary><para>既存の値をすべて削除してから、WinnerTeamに値を代入します。</para></summary>
|
||||
/// <summary><para>Delete any existing values and then assign the values to WinnerTeam.</para></summary>
|
||||
public static void ResetAndSetWinner(CustomWinner winner)
|
||||
{
|
||||
Reset();
|
||||
|
||||
@@ -384,7 +384,7 @@ static class ExtendedPlayerControl
|
||||
public static string GetSubRoleName(this PlayerControl player, bool forUser = false)
|
||||
{
|
||||
var SubRoles = Main.PlayerStates[player.PlayerId].SubRoles.ToArray();
|
||||
if (!SubRoles.Any()) return string.Empty;
|
||||
if (SubRoles.Length == 0) return string.Empty;
|
||||
var sb = new StringBuilder();
|
||||
foreach (CustomRoles role in SubRoles)
|
||||
{
|
||||
@@ -885,7 +885,7 @@ static class ExtendedPlayerControl
|
||||
public static void AddKillTimerToDict(this PlayerControl pc, bool half = false, float CD = -1f)
|
||||
{
|
||||
float resultKCD;
|
||||
if (CD == -1)
|
||||
if (CD == -1f)
|
||||
{
|
||||
if (Main.AllPlayerKillCooldown.TryGetValue(pc.PlayerId, out var kcd)) resultKCD = kcd;
|
||||
else resultKCD = 0f;
|
||||
|
||||
@@ -41,7 +41,7 @@ public class PlayerGameOptionsSender(PlayerControl player) : GameOptionsSender
|
||||
|
||||
public static void SetDirtyToAllV3()
|
||||
{
|
||||
foreach (var sender in AllSenders.OfType<PlayerGameOptionsSender>().Where(sender => !sender.IsDirty && sender.player.IsAlive() && ((Main.GrenadierBlinding.Any() && (sender.player.GetCustomRole().IsImpostor() || (sender.player.GetCustomRole().IsNeutral() && Options.GrenadierCanAffectNeutral.GetBool()))) || (Main.MadGrenadierBlinding.Any() && !sender.player.GetCustomRole().IsImpostorTeam() && !sender.player.Is(CustomRoles.Madmate)))).ToArray())
|
||||
foreach (var sender in AllSenders.OfType<PlayerGameOptionsSender>().Where(sender => !sender.IsDirty && sender.player.IsAlive() && ((Main.GrenadierBlinding.Count > 0 && (sender.player.GetCustomRole().IsImpostor() || (sender.player.GetCustomRole().IsNeutral() && Options.GrenadierCanAffectNeutral.GetBool()))) || (Main.MadGrenadierBlinding.Count > 0 && !sender.player.GetCustomRole().IsImpostorTeam() && !sender.player.Is(CustomRoles.Madmate)))).ToArray())
|
||||
{
|
||||
sender.SetDirty();
|
||||
}
|
||||
@@ -668,11 +668,11 @@ public class PlayerGameOptionsSender(PlayerControl player) : GameOptionsSender
|
||||
Main.KillGhoul.Add(player.PlayerId);
|
||||
}
|
||||
if (
|
||||
(Main.GrenadierBlinding.Any() &&
|
||||
(Main.GrenadierBlinding.Count > 0 &&
|
||||
(player.GetCustomRole().IsImpostor() ||
|
||||
(player.GetCustomRole().IsNeutral() && Options.GrenadierCanAffectNeutral.GetBool()))
|
||||
) || (
|
||||
Main.MadGrenadierBlinding.Any() && !player.GetCustomRole().IsImpostorTeam() && !player.Is(CustomRoles.Madmate))
|
||||
Main.MadGrenadierBlinding.Count > 0 && !player.GetCustomRole().IsImpostorTeam() && !player.Is(CustomRoles.Madmate))
|
||||
)
|
||||
{
|
||||
{
|
||||
@@ -684,7 +684,7 @@ public class PlayerGameOptionsSender(PlayerControl player) : GameOptionsSender
|
||||
|
||||
switch (player.GetCustomRole())
|
||||
{
|
||||
case CustomRoles.Lighter when Main.Lighter.Any():
|
||||
case CustomRoles.Lighter when Main.Lighter.Count > 0:
|
||||
opt.SetVisionV2();
|
||||
if (Utils.IsActive(SystemTypes.Electrical)) opt.SetFloat(FloatOptionNames.CrewLightMod, Options.LighterVisionOnLightsOut.GetFloat() * 5);
|
||||
else opt.SetFloat(FloatOptionNames.CrewLightMod, Options.LighterVisionNormal.GetFloat());
|
||||
@@ -710,7 +710,7 @@ public class PlayerGameOptionsSender(PlayerControl player) : GameOptionsSender
|
||||
opt.SetFloat(FloatOptionNames.ImpostorLightMod, Sentinel.LoweredVision.GetFloat());
|
||||
}
|
||||
|
||||
/* if ((Main.FlashbangInProtect.Any() && Main.ForFlashbang.Contains(player.PlayerId) && (!player.GetCustomRole().IsCrewmate())))
|
||||
/* if ((Main.FlashbangInProtect.Count > 0 && Main.ForFlashbang.Contains(player.PlayerId) && (!player.GetCustomRole().IsCrewmate())))
|
||||
{
|
||||
opt.SetVision(false);
|
||||
opt.SetFloat(FloatOptionNames.CrewLightMod, Options.FlashbangVision.GetFloat());
|
||||
|
||||
@@ -322,7 +322,7 @@ public class TaskState
|
||||
foreach (SystemTypes sys in Enum.GetValues(typeof(SystemTypes)))
|
||||
if (Utils.IsActive(sys)) SysList.Add(sys);
|
||||
|
||||
if (SysList.Any())
|
||||
if (SysList.Count > 0)
|
||||
{
|
||||
var SbSys = SysList[IRandom.Instance.Next(0, SysList.Count)];
|
||||
|
||||
|
||||
@@ -257,6 +257,7 @@ public static class Options
|
||||
public static OptionItem WarlockCanKillSelf;
|
||||
public static OptionItem WarlockShiftDuration;
|
||||
public static OptionItem ScavengerKillCooldown;
|
||||
public static OptionItem ScavengerKillDuration;
|
||||
public static OptionItem ZombieKillCooldown;
|
||||
public static OptionItem ZombieSpeedReduce;
|
||||
public static OptionItem EvilWatcherChance;
|
||||
@@ -1409,6 +1410,9 @@ public static class Options
|
||||
ScavengerKillCooldown = FloatOptionItem.Create(4010, "KillCooldown", new(0f, 180f, 2.5f), 40f, TabGroup.ImpostorRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Scavenger])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
ScavengerKillDuration = FloatOptionItem.Create(4011, "ScavengerKillDuration", new(0f, 90f, 0.5f), 5f, TabGroup.ImpostorRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Scavenger])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
RoleLoadingText = "Impostor roles\nShapemaster";
|
||||
//SetupRoleOptions(4100, TabGroup.ImpostorRoles, CustomRoles.ShapeMaster);
|
||||
//ShapeMasterShapeshiftDuration = FloatOptionItem.Create(4110, "ShapeshiftDuration", new(0, 180, 1), 10, TabGroup.ImpostorRoles, false)
|
||||
@@ -1513,6 +1517,8 @@ public static class Options
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Demolitionist]);
|
||||
RoleLoadingText = "Crewmate roles\nTask Manager";
|
||||
SetupRoleOptions(5575, TabGroup.CrewmateRoles, CustomRoles.TaskManager);
|
||||
RoleLoadingText = "Crewmate roles\nShiftguard";
|
||||
SetupRoleOptions(5594, TabGroup.CrewmateRoles, CustomRoles.Shiftguard);
|
||||
RoleLoadingText = "Crewmate roles\nMole";
|
||||
Mole.SetupCustomOption();
|
||||
RoleLoadingText = "Crewmate roles\nSentinel";
|
||||
@@ -3051,7 +3057,7 @@ public static class Options
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
.SetHidden(true)
|
||||
.SetColor(new Color32(255, 153, 153, byte.MaxValue));
|
||||
DisableShapeshiftAnimations = BooleanOptionItem.Create(22604, "DisableShapeshiftAnimations", false, TabGroup.GameSettings, false)
|
||||
DisableShapeshiftAnimations = BooleanOptionItem.Create(22604, "DisableShapeshiftAnimations", true, TabGroup.GameSettings, false)
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
.SetColor(new Color32(255, 153, 153, byte.MaxValue));
|
||||
DisableVanillaRoles = BooleanOptionItem.Create(22600, "DisableVanillaRoles", true, TabGroup.GameSettings, false)
|
||||
|
||||
+9
-3
@@ -66,7 +66,7 @@ public static class Utils
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
AmongUsClient.Instance.ExitGame(DisconnectReasons.Custom);
|
||||
Logger.Fatal($"{text} 错误,已断开游戏", "Anti-black");
|
||||
Logger.Fatal($"{text} error, disconnected from game", "Anti-black");
|
||||
}, 8f, "Anti-Black Exit Game");
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,7 @@ public static class Utils
|
||||
{
|
||||
foreach (PlayerControl pc in Main.AllAlivePlayerControls)
|
||||
{
|
||||
TP(pc.NetTransform, location);
|
||||
pc.TP(location);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -750,6 +750,12 @@ public static class Utils
|
||||
case CustomRoles.Sprayer:
|
||||
ProgressText.Append(Sprayer.ProgressText);
|
||||
break;
|
||||
case CustomRoles.Maverick:
|
||||
int kills = Maverick.NumOfKills;
|
||||
int min = Maverick.MinKillsToWin.GetInt();
|
||||
Color color = kills >= min ? Color.green : Color.red;
|
||||
ProgressText.Append(ColorString(color, $"{kills}/{min}"));
|
||||
break;
|
||||
case CustomRoles.Alchemist:
|
||||
ProgressText.Append(Alchemist.GetProgressText(playerId));
|
||||
break;
|
||||
@@ -1920,7 +1926,7 @@ public static class Utils
|
||||
}
|
||||
}
|
||||
}
|
||||
return playerRooms.Any() ? playerRooms : null;
|
||||
return playerRooms.Count > 0 ? playerRooms : null;
|
||||
}
|
||||
public static PlayerControl GetPlayerById(int PlayerId) => Main.AllPlayerControls.FirstOrDefault(pc => pc.PlayerId == PlayerId);
|
||||
public static GameData.PlayerInfo GetPlayerInfoById(int PlayerId) => GameData.Instance.AllPlayers.ToArray().FirstOrDefault(info => info.PlayerId == PlayerId);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TOHE.Patches;
|
||||
|
||||
@@ -17,5 +18,10 @@ class ChatBubbleSetNamePatch
|
||||
{
|
||||
if (GameStates.IsInGame && __instance.playerInfo.PlayerId == PlayerControl.LocalPlayer.PlayerId)
|
||||
__instance.NameText.color = PlayerControl.LocalPlayer.GetRoleColor();
|
||||
if (Main.DarkTheme.Value)
|
||||
{
|
||||
__instance.Background.color = Color.black;
|
||||
__instance.TextArea.color = Color.white;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ using TOHE.Modules;
|
||||
using TOHE.Roles.Crewmate;
|
||||
using TOHE.Roles.Impostor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using static TOHE.Translator;
|
||||
|
||||
|
||||
@@ -1142,19 +1143,33 @@ internal class ChatUpdatePatch
|
||||
public static bool DoBlockChat;
|
||||
public static void Postfix(ChatController __instance)
|
||||
{
|
||||
var chatBubble = __instance.chatBubblePool.Prefab.Cast<ChatBubble>();
|
||||
chatBubble.TextArea.overrideColorTags = false;
|
||||
if (Main.DarkTheme.Value)
|
||||
{
|
||||
chatBubble.TextArea.color = Color.white;
|
||||
chatBubble.Background.color = Color.black;
|
||||
}
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost || Main.MessagesToSend.Count == 0 || (Main.MessagesToSend[0].RECEIVER_ID == byte.MaxValue && Main.MessageWait.Value > __instance.timeSinceLastMessage) || DoBlockChat) return;
|
||||
|
||||
var player = Main.AllAlivePlayerControls.OrderBy(x => x.PlayerId).FirstOrDefault() ?? Main.AllPlayerControls.OrderBy(x => x.PlayerId).FirstOrDefault() ?? PlayerControl.LocalPlayer;
|
||||
if (player == null) return;
|
||||
|
||||
(string msg, byte sendTo, string title) = Main.MessagesToSend[0];
|
||||
Main.MessagesToSend.RemoveAt(0);
|
||||
|
||||
int clientId = sendTo == byte.MaxValue ? -1 : Utils.GetPlayerById(sendTo).GetClientId();
|
||||
|
||||
var name = player.Data.PlayerName;
|
||||
|
||||
if (clientId == -1)
|
||||
{
|
||||
player.SetName(title);
|
||||
DestroyableSingleton<HudManager>.Instance.Chat.AddChat(player, msg);
|
||||
player.SetName(name);
|
||||
}
|
||||
|
||||
var writer = CustomRpcSender.Create("MessagesToSend", SendOption.None);
|
||||
_ = writer.StartMessage(clientId);
|
||||
_ = writer.StartRpc(player.NetId, (byte)RpcCalls.SetName)
|
||||
@@ -1168,6 +1183,7 @@ internal class ChatUpdatePatch
|
||||
.EndRpc();
|
||||
_ = writer.EndMessage();
|
||||
writer.SendMessage();
|
||||
|
||||
__instance.timeSinceLastMessage = 0f;
|
||||
}
|
||||
}
|
||||
@@ -1196,7 +1212,7 @@ internal class UpdateCharCountPatch
|
||||
__instance.charCountText.enableWordWrapping = false;
|
||||
if (length < (AmongUsClient.Instance.AmHost ? 1700 : 250))
|
||||
__instance.charCountText.color = Color.black;
|
||||
else if (length < (AmongUsClient.Instance.AmHost ? 1900 : 300))
|
||||
else if (length < (AmongUsClient.Instance.AmHost ? 2000 : 300))
|
||||
__instance.charCountText.color = new Color(1f, 1f, 0f, 1f);
|
||||
else
|
||||
__instance.charCountText.color = Color.red;
|
||||
|
||||
@@ -28,7 +28,7 @@ class GameEndChecker
|
||||
|
||||
if (Options.CurrentGameMode is CustomGameMode.SoloKombat or CustomGameMode.FFA or CustomGameMode.MoveAndStop)
|
||||
{
|
||||
if (CustomWinnerHolder.WinnerIds.Any() || CustomWinnerHolder.WinnerTeam != CustomWinner.Default)
|
||||
if (CustomWinnerHolder.WinnerIds.Count > 0 || CustomWinnerHolder.WinnerTeam != CustomWinner.Default)
|
||||
{
|
||||
ShipStatus.Instance.enabled = false;
|
||||
StartEndGame(reason);
|
||||
@@ -140,7 +140,7 @@ class GameEndChecker
|
||||
CustomWinnerHolder.WinnerIds.Add(pc.PlayerId);
|
||||
CustomWinnerHolder.AdditionalWinnerTeams.Add(AdditionalWinners.Sunnyboy);
|
||||
break;
|
||||
case CustomRoles.Maverick when pc.IsAlive():
|
||||
case CustomRoles.Maverick when pc.IsAlive() && Maverick.NumOfKills >= Maverick.MinKillsToWin.GetInt():
|
||||
CustomWinnerHolder.WinnerIds.Add(pc.PlayerId);
|
||||
CustomWinnerHolder.AdditionalWinnerTeams.Add(AdditionalWinners.Maverick);
|
||||
break;
|
||||
@@ -533,7 +533,7 @@ class GameEndChecker
|
||||
public override bool CheckForEndGame(out GameOverReason reason)
|
||||
{
|
||||
reason = GameOverReason.ImpostorByKill;
|
||||
if (CustomWinnerHolder.WinnerIds.Any()) return false;
|
||||
if (CustomWinnerHolder.WinnerIds.Count > 0) return false;
|
||||
if (CheckGameEndByLivingPlayers(out reason)) return true;
|
||||
return false;
|
||||
}
|
||||
@@ -561,7 +561,7 @@ class GameEndChecker
|
||||
public override bool CheckForEndGame(out GameOverReason reason)
|
||||
{
|
||||
reason = GameOverReason.ImpostorByKill;
|
||||
if (CustomWinnerHolder.WinnerIds.Any()) return false;
|
||||
if (CustomWinnerHolder.WinnerIds.Count > 0) return false;
|
||||
if (CheckGameEndByLivingPlayers(out reason)) return true;
|
||||
return false;
|
||||
}
|
||||
@@ -618,7 +618,7 @@ class GameEndChecker
|
||||
public override bool CheckForEndGame(out GameOverReason reason)
|
||||
{
|
||||
reason = GameOverReason.ImpostorByKill;
|
||||
if (CustomWinnerHolder.WinnerIds.Any()) return false;
|
||||
if (CustomWinnerHolder.WinnerIds.Count > 0) return false;
|
||||
if (CheckGameEndByLivingPlayers(out reason)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -14,8 +14,9 @@ public static class OptionsMenuBehaviourStartPatch
|
||||
private static ClientOptionItem EnableCustomButton;
|
||||
private static ClientOptionItem EnableCustomSoundEffect;
|
||||
private static ClientOptionItem SwitchVanilla;
|
||||
public static ClientOptionItem UseVersionProtocol;
|
||||
private static ClientOptionItem DarkTheme;
|
||||
#if DEBUG
|
||||
public static ClientOptionItem UseVersionProtocol;
|
||||
private static ClientOptionItem VersionCheat;
|
||||
private static ClientOptionItem GodMode;
|
||||
#endif
|
||||
@@ -78,6 +79,10 @@ public static class OptionsMenuBehaviourStartPatch
|
||||
Main.Instance.Unload();
|
||||
}
|
||||
}
|
||||
if (DarkTheme == null || DarkTheme.ToggleButton == null)
|
||||
{
|
||||
DarkTheme = ClientOptionItem.Create("EnableDarkTheme", Main.DarkTheme, __instance);
|
||||
}
|
||||
#if DEBUG
|
||||
if (UseVersionProtocol == null || UseVersionProtocol.ToggleButton == null)
|
||||
{
|
||||
|
||||
+2
-2
@@ -69,7 +69,7 @@ class HudManagerPatch
|
||||
OverriddenRolesText.fontSize = OverriddenRolesText.fontSizeMax = OverriddenRolesText.fontSizeMin = 2f;
|
||||
}
|
||||
|
||||
if (Main.SetRoles.Any() || Main.SetAddOns.Any())
|
||||
if (Main.SetRoles.Count > 0 || Main.SetAddOns.Count > 0)
|
||||
{
|
||||
Dictionary<byte, string> resultText = [];
|
||||
bool first = true;
|
||||
@@ -81,7 +81,7 @@ class HudManagerPatch
|
||||
resultText[item.Key] = text;
|
||||
first = false;
|
||||
}
|
||||
if (!Main.SetRoles.Any()) first = true;
|
||||
if (Main.SetRoles.Count == 0) first = true;
|
||||
foreach (var item in Main.SetAddOns)
|
||||
{
|
||||
for (int i = 0; i < item.Value.Count; i++)
|
||||
|
||||
@@ -279,6 +279,7 @@ class BeginCrewmatePatch
|
||||
=> ShipStatus.Instance.SabotageSound,
|
||||
|
||||
CustomRoles.Mastermind or
|
||||
CustomRoles.Shiftguard or
|
||||
CustomRoles.Gambler
|
||||
=> GetIntroSound(RoleTypes.Shapeshifter),
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ using HarmonyLib;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using TOHE.Modules;
|
||||
using TOHE.Roles.Crewmate;
|
||||
using TOHE.Roles.Impostor;
|
||||
@@ -95,6 +96,8 @@ class ExternalRpcPetPatch
|
||||
|
||||
if (pc.HasAbilityCD()) return;
|
||||
|
||||
PlayerControl[] AllAlivePlayers = Main.AllAlivePlayerControls;
|
||||
|
||||
switch (pc.GetCustomRole())
|
||||
{
|
||||
// Crewmates
|
||||
@@ -214,7 +217,7 @@ class ExternalRpcPetPatch
|
||||
{
|
||||
Main.DovesOfNeaceNumOfUsed[pc.PlayerId] -= 1;
|
||||
//pc.RpcGuardAndKill(pc);
|
||||
Main.AllAlivePlayerControls.Where(x =>
|
||||
AllAlivePlayers.Where(x =>
|
||||
pc.Is(CustomRoles.Madmate) ?
|
||||
(x.CanUseKillButton() && x.GetCustomRole().IsCrewmate()) :
|
||||
x.CanUseKillButton()
|
||||
@@ -284,11 +287,26 @@ class ExternalRpcPetPatch
|
||||
case CustomRoles.Sentinel:
|
||||
Sentinel.StartPatrolling(pc);
|
||||
break;
|
||||
case CustomRoles.Lookout:
|
||||
var sb = new StringBuilder();
|
||||
for (int i = 0; i < AllAlivePlayers.Length; i++) if (i % 3 == 0) sb.AppendLine();
|
||||
for (int i = 0; i < AllAlivePlayers.Length; i++)
|
||||
{
|
||||
PlayerControl player = AllAlivePlayers[i];
|
||||
if (player == null) continue;
|
||||
if (i != 0) sb.Append("; ");
|
||||
string name = player.GetRealName();
|
||||
byte id = player.PlayerId;
|
||||
if (Main.PlayerColors.TryGetValue(id, out var color)) name = Utils.ColorString(color, name);
|
||||
sb.Append($"{name} {id}");
|
||||
if (i % 3 == 0 && i != AllAlivePlayers.Length - 1) sb.AppendLine();
|
||||
}
|
||||
pc.Notify(sb.ToString());
|
||||
break;
|
||||
|
||||
// Impostors
|
||||
|
||||
case CustomRoles.Sniper:
|
||||
if (!Sniper.IsAim[pc.PlayerId]) Main.AbilityCD.Remove(pc.PlayerId);
|
||||
Sniper.OnShapeshift(pc, !Sniper.IsAim[pc.PlayerId]);
|
||||
break;
|
||||
case CustomRoles.Warlock:
|
||||
@@ -301,7 +319,7 @@ class ExternalRpcPetPatch
|
||||
UnityEngine.Vector2 cppos = cp.Pos();
|
||||
Dictionary<PlayerControl, float> cpdistance = [];
|
||||
float dis;
|
||||
foreach (PlayerControl p in Main.AllAlivePlayerControls)
|
||||
foreach (PlayerControl p in AllAlivePlayers)
|
||||
{
|
||||
if (p.PlayerId == cp.PlayerId) continue;
|
||||
if (!Options.WarlockCanKillSelf.GetBool() && p.PlayerId == pc.PlayerId) continue;
|
||||
@@ -312,7 +330,7 @@ class ExternalRpcPetPatch
|
||||
cpdistance.Add(p, dis);
|
||||
Logger.Info($"{p?.Data?.PlayerName}'s distance: {dis}", "Warlock");
|
||||
}
|
||||
if (cpdistance.Any())
|
||||
if (cpdistance.Count > 0)
|
||||
{
|
||||
var min = cpdistance.OrderBy(c => c.Value).FirstOrDefault();
|
||||
PlayerControl targetw = min.Key;
|
||||
@@ -383,7 +401,7 @@ class ExternalRpcPetPatch
|
||||
}
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
var totalAlive = Main.AllAlivePlayerControls.Length;
|
||||
var totalAlive = AllAlivePlayers.Length;
|
||||
if (Options.BomberDiesInExplosion.GetBool() && totalAlive > 1 && !GameStates.IsEnded)
|
||||
{
|
||||
pc.Suicide(PlayerState.DeathReason.Bombed);
|
||||
@@ -408,7 +426,7 @@ class ExternalRpcPetPatch
|
||||
}
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
var totalAlive = Main.AllAlivePlayerControls.Length;
|
||||
var totalAlive = AllAlivePlayers.Length;
|
||||
if (totalAlive > 1 && !GameStates.IsEnded)
|
||||
{
|
||||
pc.Suicide(PlayerState.DeathReason.Bombed);
|
||||
@@ -451,6 +469,8 @@ class ExternalRpcPetPatch
|
||||
break;
|
||||
}
|
||||
|
||||
if (pc.Is(CustomRoles.Sniper) && Sniper.IsAim[pc.PlayerId]) return;
|
||||
|
||||
pc.AddAbilityCD();
|
||||
}
|
||||
}
|
||||
+170
-136
@@ -688,17 +688,22 @@ class CheckMurderPatch
|
||||
{
|
||||
if (!target.Is(CustomRoles.Pestilence))
|
||||
{
|
||||
TP(target.NetTransform, Pelican.GetBlackRoomPS());
|
||||
target.Suicide(PlayerState.DeathReason.Kill, killer);
|
||||
killer.SetKillCooldown();
|
||||
RPC.PlaySoundRPC(killer.PlayerId, Sounds.KillSound);
|
||||
target.Notify(ColorString(GetRoleColor(CustomRoles.Scavenger), GetString("KilledByScavenger")));
|
||||
float dur = Options.ScavengerKillDuration.GetFloat();
|
||||
killer.Notify("....", dur);
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
if (Vector2.Distance(killer.Pos(), target.Pos()) > 2f) return;
|
||||
target.TP(Pelican.GetBlackRoomPS());
|
||||
target.Suicide(PlayerState.DeathReason.Kill, killer);
|
||||
killer.SetKillCooldown();
|
||||
RPC.PlaySoundRPC(killer.PlayerId, Sounds.KillSound);
|
||||
target.Notify(ColorString(GetRoleColor(CustomRoles.Scavenger), GetString("KilledByScavenger")));
|
||||
}, dur, "Scavenger Kill");
|
||||
return false;
|
||||
}
|
||||
if (target.Is(CustomRoles.Pestilence))
|
||||
else
|
||||
{
|
||||
target.Kill(target);
|
||||
target.SetRealKiller(killer);
|
||||
killer.Suicide(PlayerState.DeathReason.Kill, target);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -710,9 +715,18 @@ class CheckMurderPatch
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
if (!Main.OverDeadPlayerList.Contains(target.PlayerId)) Main.OverDeadPlayerList.Add(target.PlayerId);
|
||||
if (target.Is(CustomRoles.Avanger))
|
||||
{
|
||||
foreach (var pc in Main.AllAlivePlayerControls)
|
||||
{
|
||||
pc.Suicide(PlayerState.DeathReason.Revenge, target);
|
||||
}
|
||||
CustomWinnerHolder.ResetAndSetWinner(CustomWinner.None);
|
||||
return;
|
||||
}
|
||||
var ops = target.Pos();
|
||||
var rd = IRandom.Instance;
|
||||
for (int i = 0; i < 20; i++)
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
Vector2 location = new(ops.x + ((float)(rd.Next(0, 201) - 100) / 100), ops.y + ((float)(rd.Next(0, 201) - 100) / 100));
|
||||
location += new Vector2(0, 0.3636f);
|
||||
@@ -737,7 +751,7 @@ class CheckMurderPatch
|
||||
messageWriter.Write((byte)ExtendedPlayerControl.ResultFlags);
|
||||
AmongUsClient.Instance.FinishRpcImmediately(messageWriter);
|
||||
}
|
||||
TP(killer.NetTransform, ops);
|
||||
killer.TP(ops);
|
||||
}, 0.05f, "OverKiller Murder");
|
||||
}
|
||||
|
||||
@@ -1180,6 +1194,9 @@ class MurderPlayerPatch
|
||||
case CustomRoles.BloodKnight:
|
||||
BloodKnight.OnMurderPlayer(killer, target);
|
||||
break;
|
||||
case CustomRoles.Maverick:
|
||||
Maverick.NumOfKills++;
|
||||
break;
|
||||
case CustomRoles.Mafioso:
|
||||
Mafioso.OnMurder();
|
||||
break;
|
||||
@@ -1315,7 +1332,7 @@ class CmdCheckShapeshiftPatch
|
||||
}
|
||||
|
||||
// Triggered when the egg animation starts playing
|
||||
//[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.Shapeshift))]
|
||||
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.Shapeshift))]
|
||||
class ShapeshiftPatch
|
||||
{
|
||||
public static List<byte> IgnoreNextSS = [];
|
||||
@@ -1409,7 +1426,7 @@ class ShapeshiftPatch
|
||||
cpdistance.Add(p, dis);
|
||||
Logger.Info($"{p?.Data?.PlayerName}の位置{dis}", "Warlock");
|
||||
}
|
||||
if (cpdistance.Any())
|
||||
if (cpdistance.Count > 0)
|
||||
{
|
||||
var min = cpdistance.OrderBy(c => c.Value).FirstOrDefault();
|
||||
PlayerControl targetw = min.Key;
|
||||
@@ -1605,7 +1622,7 @@ class ShapeshiftPatch
|
||||
|
||||
if (!shapeshifting || !isSSneeded)
|
||||
{
|
||||
_ = new LateTask(shapeshifter.RpcResetAbilityCooldown, 0.01f, "Reset SS CD");
|
||||
_ = new LateTask(shapeshifter.RpcResetAbilityCooldown, 0.01f, log: false);
|
||||
}
|
||||
|
||||
if (!isSSneeded)
|
||||
@@ -1617,6 +1634,21 @@ class ShapeshiftPatch
|
||||
|
||||
return isSSneeded || !Options.DisableShapeshiftAnimations.GetBool() || !shapeshifting;
|
||||
}
|
||||
|
||||
// Tasks that should run when someone performs a shapeshift (with the egg animation) should be here.
|
||||
public static void Postfix(PlayerControl __instance, [HarmonyArgument(0)] PlayerControl target)
|
||||
{
|
||||
bool shapeshifting = __instance.PlayerId != target.PlayerId;
|
||||
|
||||
foreach (var pc in Main.AllAlivePlayerControls)
|
||||
{
|
||||
if (pc.Is(CustomRoles.Shiftguard))
|
||||
{
|
||||
if (shapeshifting) pc.Notify(GetString("ShiftguardNotifySS"));
|
||||
else pc.Notify("ShiftguardNotifyUnshift");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.ReportDeadBody))]
|
||||
class ReportDeadBodyPatch
|
||||
@@ -1987,7 +2019,7 @@ class FixedUpdatePatch
|
||||
|
||||
public static async void Postfix(PlayerControl __instance)
|
||||
{
|
||||
if (!DevManager.DevUserList.Any(x => x.Code == EOSManager.Instance.friendCode && x.IsUp) && !Main.UseVersionProtocol.Value)
|
||||
if (!Main.UseVersionProtocol.Value && !DevManager.DevUserList.Any(x => x.Code == EOSManager.Instance.friendCode && x.IsUp))
|
||||
{
|
||||
Main.UseVersionProtocol.Value = true;
|
||||
}
|
||||
@@ -1995,18 +2027,19 @@ class FixedUpdatePatch
|
||||
if (__instance == null) return;
|
||||
if (!GameStates.IsModHost) return;
|
||||
|
||||
if (GameStates.IsInTask && ReportDeadBodyPatch.CanReport[__instance.PlayerId] && ReportDeadBodyPatch.WaitReport[__instance.PlayerId].Any())
|
||||
byte id = __instance.PlayerId;
|
||||
if (GameStates.IsInTask && ReportDeadBodyPatch.CanReport[id] && ReportDeadBodyPatch.WaitReport[id].Count > 0)
|
||||
{
|
||||
if (Glitch.hackedIdList.ContainsKey(__instance.PlayerId))
|
||||
if (Glitch.hackedIdList.ContainsKey(id))
|
||||
{
|
||||
__instance.Notify(string.Format(GetString("HackedByGlitch"), "Report"));
|
||||
Logger.Info("Dead Body Report Blocked (player is hacked by Glitch)", "FixedUpdate.ReportDeadBody");
|
||||
ReportDeadBodyPatch.WaitReport[__instance.PlayerId].Clear();
|
||||
ReportDeadBodyPatch.WaitReport[id].Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
var info = ReportDeadBodyPatch.WaitReport[__instance.PlayerId][0];
|
||||
ReportDeadBodyPatch.WaitReport[__instance.PlayerId].Clear();
|
||||
var info = ReportDeadBodyPatch.WaitReport[id][0];
|
||||
ReportDeadBodyPatch.WaitReport[id].Clear();
|
||||
Logger.Info($"{__instance.GetNameWithRole().RemoveHtmlTags()}:通報可能になったため通報処理を行います", "ReportDeadbody");
|
||||
__instance.ReportDeadBody(info);
|
||||
}
|
||||
@@ -2014,17 +2047,17 @@ class FixedUpdatePatch
|
||||
|
||||
if (Options.DontUpdateDeadPlayers.GetBool() && !__instance.IsAlive())
|
||||
{
|
||||
DeadBufferTime.TryAdd(__instance.PlayerId, IRandom.Instance.Next(50, 70));
|
||||
DeadBufferTime[__instance.PlayerId]--;
|
||||
if (DeadBufferTime[__instance.PlayerId] > 0) return;
|
||||
else DeadBufferTime[__instance.PlayerId] = IRandom.Instance.Next(50, 70);
|
||||
DeadBufferTime.TryAdd(id, IRandom.Instance.Next(50, 70));
|
||||
DeadBufferTime[id]--;
|
||||
if (DeadBufferTime[id] > 0) return;
|
||||
else DeadBufferTime[id] = IRandom.Instance.Next(50, 70);
|
||||
}
|
||||
|
||||
if (Options.LowLoadMode.GetBool())
|
||||
{
|
||||
BufferTime.TryAdd(__instance.PlayerId, 10);
|
||||
BufferTime[__instance.PlayerId]--;
|
||||
if (BufferTime[__instance.PlayerId] % 2 == 1 && Options.DeepLowLoad.GetBool()) return;
|
||||
BufferTime.TryAdd(id, 10);
|
||||
BufferTime[id]--;
|
||||
if (BufferTime[id] % 2 == 1 && Options.DeepLowLoad.GetBool()) return;
|
||||
}
|
||||
|
||||
//if (Options.DeepLowLoad.GetBool()) await Task.Run(() => { DoPostfix(__instance); });
|
||||
@@ -2042,12 +2075,13 @@ class FixedUpdatePatch
|
||||
public static Task DoPostfix(PlayerControl __instance)
|
||||
{
|
||||
var player = __instance;
|
||||
var playerId = player.PlayerId;
|
||||
|
||||
bool lowLoad = false;
|
||||
if (Options.LowLoadMode.GetBool())
|
||||
{
|
||||
if (BufferTime[player.PlayerId] > 0) lowLoad = true;
|
||||
else BufferTime[player.PlayerId] = 10;
|
||||
if (BufferTime[playerId] > 0) lowLoad = true;
|
||||
else BufferTime[playerId] = 10;
|
||||
}
|
||||
|
||||
if (Sniper.IsEnable) Sniper.OnFixedUpdate(player);
|
||||
@@ -2057,11 +2091,8 @@ class FixedUpdatePatch
|
||||
NameNotifyManager.OnFixedUpdate(player);
|
||||
TargetArrow.OnFixedUpdate(player);
|
||||
LocateArrow.OnFixedUpdate(player);
|
||||
}
|
||||
|
||||
if (!lowLoad)
|
||||
{
|
||||
if (RPCHandlerPatch.ReportDeadBodyRPCs.Remove(player.PlayerId))
|
||||
if (RPCHandlerPatch.ReportDeadBodyRPCs.Remove(playerId))
|
||||
Logger.Info($"Cleared ReportDeadBodyRPC Count for {player.GetRealName().RemoveHtmlTags()}", "FixedUpdatePatch");
|
||||
}
|
||||
|
||||
@@ -2092,14 +2123,14 @@ class FixedUpdatePatch
|
||||
}
|
||||
}
|
||||
|
||||
if (!Main.KillTimers.ContainsKey(player.PlayerId))
|
||||
Main.KillTimers.Add(player.PlayerId, 10f);
|
||||
else if (!player.inVent && !player.MyPhysics.Animations.IsPlayingEnterVentAnimation() && Main.KillTimers[player.PlayerId] > 0)
|
||||
Main.KillTimers[player.PlayerId] -= Time.fixedDeltaTime;
|
||||
if (!Main.KillTimers.ContainsKey(playerId))
|
||||
Main.KillTimers.Add(playerId, 10f);
|
||||
else if (!player.inVent && !player.MyPhysics.Animations.IsPlayingEnterVentAnimation() && Main.KillTimers[playerId] > 0)
|
||||
Main.KillTimers[playerId] -= Time.fixedDeltaTime;
|
||||
|
||||
if (GameStates.IsInTask) KeepProtection.OnFixedUpdate();
|
||||
|
||||
if (DoubleTrigger.FirstTriggerTimer.Any()) DoubleTrigger.OnFixedUpdate(player);
|
||||
if (DoubleTrigger.FirstTriggerTimer.Count > 0) DoubleTrigger.OnFixedUpdate(player);
|
||||
switch (player.GetCustomRole())
|
||||
{
|
||||
case CustomRoles.Vampire:
|
||||
@@ -2186,13 +2217,13 @@ class FixedUpdatePatch
|
||||
player.RpcSetCustomRole(CustomRoles.Pestilence);
|
||||
player.Notify(GetString("PlagueBearerToPestilence"));
|
||||
player.RpcGuardAndKill(player);
|
||||
if (!PlagueBearer.PestilenceList.Contains(player.PlayerId))
|
||||
PlagueBearer.PestilenceList.Add(player.PlayerId);
|
||||
PlagueBearer.SetKillCooldownPestilence(player.PlayerId);
|
||||
PlagueBearer.playerIdList.Remove(player.PlayerId);
|
||||
if (!PlagueBearer.PestilenceList.Contains(playerId))
|
||||
PlagueBearer.PestilenceList.Add(playerId);
|
||||
PlagueBearer.SetKillCooldownPestilence(playerId);
|
||||
PlagueBearer.playerIdList.Remove(playerId);
|
||||
}
|
||||
|
||||
if (!lowLoad && Main.PlayerStates.TryGetValue(player.PlayerId, out var playerState) && GameStates.IsInTask)
|
||||
if (!lowLoad && Main.PlayerStates.TryGetValue(playerId, out var playerState) && GameStates.IsInTask)
|
||||
{
|
||||
if (playerState.SubRoles.Contains(CustomRoles.Damocles))
|
||||
{
|
||||
@@ -2206,12 +2237,16 @@ class FixedUpdatePatch
|
||||
|
||||
if (!lowLoad && Options.UsePets.GetBool() && GameStates.IsInTask)
|
||||
{
|
||||
if (Main.AbilityCD.TryGetValue(player.PlayerId, out var timer) && timer.START_TIMESTAMP + timer.TOTALCD < GetTimeStamp())
|
||||
if (Main.AbilityCD.TryGetValue(playerId, out var timer))
|
||||
{
|
||||
Main.AbilityCD.Remove(player.PlayerId);
|
||||
if (timer.START_TIMESTAMP + timer.TOTALCD < GetTimeStamp())
|
||||
{
|
||||
Main.AbilityCD.Remove(playerId);
|
||||
}
|
||||
if (!player.IsModClient()) NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
|
||||
}
|
||||
if (Main.AbilityCD.ContainsKey(player.PlayerId) && !player.IsModClient()) NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
|
||||
|
||||
if (Main.AbilityCD.ContainsKey(playerId) && !player.IsModClient()) NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2221,7 +2256,7 @@ class FixedUpdatePatch
|
||||
Duellist.OnFixedUpdate();
|
||||
}
|
||||
|
||||
if (GameStates.IsInTask && Agitater.IsEnable && Agitater.AgitaterHasBombed && Agitater.CurrentBombedPlayer == player.PlayerId)
|
||||
if (GameStates.IsInTask && Agitater.IsEnable && Agitater.AgitaterHasBombed && Agitater.CurrentBombedPlayer == playerId)
|
||||
{
|
||||
if (!player.IsAlive())
|
||||
{
|
||||
@@ -2235,13 +2270,13 @@ class FixedUpdatePatch
|
||||
foreach (var target in PlayerControl.AllPlayerControls)
|
||||
{
|
||||
if (!target.IsAlive()) continue;
|
||||
if (target.PlayerId != player.PlayerId && target.PlayerId != Agitater.LastBombedPlayer && !target.Data.IsDead)
|
||||
if (target.PlayerId != playerId && target.PlayerId != Agitater.LastBombedPlayer && !target.Data.IsDead)
|
||||
{
|
||||
dis = Vector2.Distance(agitaterPos, target.transform.position);
|
||||
targetDistance.Add(target.PlayerId, dis);
|
||||
}
|
||||
}
|
||||
if (targetDistance.Any())
|
||||
if (targetDistance.Count > 0)
|
||||
{
|
||||
var min = targetDistance.OrderBy(c => c.Value).FirstOrDefault();
|
||||
PlayerControl target = GetPlayerById(min.Key);
|
||||
@@ -2254,53 +2289,53 @@ class FixedUpdatePatch
|
||||
|
||||
|
||||
#region 女巫处理
|
||||
if (GameStates.IsInTask && Main.WarlockTimer.ContainsKey(player.PlayerId))//処理を1秒遅らせる
|
||||
if (GameStates.IsInTask && Main.WarlockTimer.ContainsKey(playerId))//処理を1秒遅らせる
|
||||
{
|
||||
if (player.IsAlive())
|
||||
{
|
||||
if (Main.WarlockTimer[player.PlayerId] >= 1f)
|
||||
if (Main.WarlockTimer[playerId] >= 1f)
|
||||
{
|
||||
player.RpcResetAbilityCooldown();
|
||||
Main.isCursed = false;//変身クールを1秒に変更
|
||||
player.MarkDirtySettings();
|
||||
Main.WarlockTimer.Remove(player.PlayerId);
|
||||
Main.WarlockTimer.Remove(playerId);
|
||||
}
|
||||
else Main.WarlockTimer[player.PlayerId] = Main.WarlockTimer[player.PlayerId] + Time.fixedDeltaTime;//時間をカウント
|
||||
else Main.WarlockTimer[playerId] = Main.WarlockTimer[playerId] + Time.fixedDeltaTime;//時間をカウント
|
||||
}
|
||||
else
|
||||
{
|
||||
Main.WarlockTimer.Remove(player.PlayerId);
|
||||
Main.WarlockTimer.Remove(playerId);
|
||||
}
|
||||
}
|
||||
//ターゲットのリセット
|
||||
#endregion
|
||||
|
||||
#region 纵火犯浇油处理
|
||||
if (GameStates.IsInTask && Main.ArsonistTimer.ContainsKey(player.PlayerId))//アーソニストが誰かを塗っているとき
|
||||
if (GameStates.IsInTask && Main.ArsonistTimer.ContainsKey(playerId))//アーソニストが誰かを塗っているとき
|
||||
{
|
||||
var arTarget = Main.ArsonistTimer[player.PlayerId].PLAYER;
|
||||
if (!player.IsAlive() || Pelican.IsEaten(player.PlayerId))
|
||||
var arTarget = Main.ArsonistTimer[playerId].PLAYER;
|
||||
if (!player.IsAlive() || Pelican.IsEaten(playerId))
|
||||
{
|
||||
Main.ArsonistTimer.Remove(player.PlayerId);
|
||||
Main.ArsonistTimer.Remove(playerId);
|
||||
NotifyRoles(SpecifySeer: __instance, SpecifyTarget: arTarget, ForceLoop: true);
|
||||
RPC.ResetCurrentDousingTarget(player.PlayerId);
|
||||
RPC.ResetCurrentDousingTarget(playerId);
|
||||
}
|
||||
else
|
||||
{
|
||||
var ar_target = Main.ArsonistTimer[player.PlayerId].PLAYER;//塗られる人
|
||||
var ar_time = Main.ArsonistTimer[player.PlayerId].TIMER;//塗った時間
|
||||
var ar_target = Main.ArsonistTimer[playerId].PLAYER;//塗られる人
|
||||
var ar_time = Main.ArsonistTimer[playerId].TIMER;//塗った時間
|
||||
if (!ar_target.IsAlive())
|
||||
{
|
||||
Main.ArsonistTimer.Remove(player.PlayerId);
|
||||
Main.ArsonistTimer.Remove(playerId);
|
||||
}
|
||||
else if (ar_time >= Options.ArsonistDouseTime.GetFloat())//時間以上一緒にいて塗れた時
|
||||
{
|
||||
player.SetKillCooldown();
|
||||
Main.ArsonistTimer.Remove(player.PlayerId);//塗が完了したのでDictionaryから削除
|
||||
Main.isDoused[(player.PlayerId, ar_target.PlayerId)] = true;//塗り完了
|
||||
Main.ArsonistTimer.Remove(playerId);//塗が完了したのでDictionaryから削除
|
||||
Main.isDoused[(playerId, ar_target.PlayerId)] = true;//塗り完了
|
||||
player.RpcSetDousedPlayer(ar_target, true);
|
||||
NotifyRoles(SpecifySeer: player, SpecifyTarget: arTarget, ForceLoop: true);//名前変更
|
||||
RPC.ResetCurrentDousingTarget(player.PlayerId);
|
||||
RPC.ResetCurrentDousingTarget(playerId);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2309,13 +2344,13 @@ class FixedUpdatePatch
|
||||
float dis = Vector2.Distance(player.transform.position, ar_target.transform.position);//距離を出す
|
||||
if (dis <= range)//一定の距離にターゲットがいるならば時間をカウント
|
||||
{
|
||||
Main.ArsonistTimer[player.PlayerId] = (ar_target, ar_time + Time.fixedDeltaTime);
|
||||
Main.ArsonistTimer[playerId] = (ar_target, ar_time + Time.fixedDeltaTime);
|
||||
}
|
||||
else//それ以外は削除
|
||||
{
|
||||
Main.ArsonistTimer.Remove(player.PlayerId);
|
||||
Main.ArsonistTimer.Remove(playerId);
|
||||
NotifyRoles(SpecifySeer: player, SpecifyTarget: arTarget, ForceLoop: true);
|
||||
RPC.ResetCurrentDousingTarget(player.PlayerId);
|
||||
RPC.ResetCurrentDousingTarget(playerId);
|
||||
|
||||
Logger.Info($"Canceled: {player.GetNameWithRole().RemoveHtmlTags()}", "Arsonist");
|
||||
}
|
||||
@@ -2325,31 +2360,31 @@ class FixedUpdatePatch
|
||||
#endregion
|
||||
|
||||
#region 革命家拉人处理
|
||||
if (GameStates.IsInTask && Main.RevolutionistTimer.ContainsKey(player.PlayerId))//当革命家拉拢一个玩家时
|
||||
if (GameStates.IsInTask && Main.RevolutionistTimer.ContainsKey(playerId))//当革命家拉拢一个玩家时
|
||||
{
|
||||
var rvTarget = Main.RevolutionistTimer[player.PlayerId].PLAYER;
|
||||
if (!player.IsAlive() || Pelican.IsEaten(player.PlayerId))
|
||||
var rvTarget = Main.RevolutionistTimer[playerId].PLAYER;
|
||||
if (!player.IsAlive() || Pelican.IsEaten(playerId))
|
||||
{
|
||||
Main.RevolutionistTimer.Remove(player.PlayerId);
|
||||
Main.RevolutionistTimer.Remove(playerId);
|
||||
NotifyRoles(SpecifySeer: player, SpecifyTarget: rvTarget, ForceLoop: true);
|
||||
RPC.ResetCurrentDrawTarget(player.PlayerId);
|
||||
RPC.ResetCurrentDrawTarget(playerId);
|
||||
}
|
||||
else
|
||||
{
|
||||
var rv_target = Main.RevolutionistTimer[player.PlayerId].PLAYER;//拉拢的人
|
||||
var rv_time = Main.RevolutionistTimer[player.PlayerId].TIMER;//拉拢时间
|
||||
var rv_target = Main.RevolutionistTimer[playerId].PLAYER;//拉拢的人
|
||||
var rv_time = Main.RevolutionistTimer[playerId].TIMER;//拉拢时间
|
||||
if (!rv_target.IsAlive())
|
||||
{
|
||||
Main.RevolutionistTimer.Remove(player.PlayerId);
|
||||
Main.RevolutionistTimer.Remove(playerId);
|
||||
}
|
||||
else if (rv_time >= Options.RevolutionistDrawTime.GetFloat())//在一起时间超过多久
|
||||
{
|
||||
player.SetKillCooldown();
|
||||
Main.RevolutionistTimer.Remove(player.PlayerId);//拉拢完成从字典中删除
|
||||
Main.isDraw[(player.PlayerId, rv_target.PlayerId)] = true;//完成拉拢
|
||||
Main.RevolutionistTimer.Remove(playerId);//拉拢完成从字典中删除
|
||||
Main.isDraw[(playerId, rv_target.PlayerId)] = true;//完成拉拢
|
||||
player.RpcSetDrawPlayer(rv_target, true);
|
||||
NotifyRoles(SpecifySeer: player, SpecifyTarget: rv_target, ForceLoop: true);
|
||||
RPC.ResetCurrentDrawTarget(player.PlayerId);
|
||||
RPC.ResetCurrentDrawTarget(playerId);
|
||||
if (IRandom.Instance.Next(1, 100) <= Options.RevolutionistKillProbability.GetInt())
|
||||
{
|
||||
rv_target.SetRealKiller(player);
|
||||
@@ -2365,13 +2400,13 @@ class FixedUpdatePatch
|
||||
float dis = Vector2.Distance(player.transform.position, rv_target.transform.position);//超出距离
|
||||
if (dis <= range)//在一定距离内则计算时间
|
||||
{
|
||||
Main.RevolutionistTimer[player.PlayerId] = (rv_target, rv_time + Time.fixedDeltaTime);
|
||||
Main.RevolutionistTimer[playerId] = (rv_target, rv_time + Time.fixedDeltaTime);
|
||||
}
|
||||
else//否则删除
|
||||
{
|
||||
Main.RevolutionistTimer.Remove(player.PlayerId);
|
||||
Main.RevolutionistTimer.Remove(playerId);
|
||||
NotifyRoles(SpecifySeer: __instance, SpecifyTarget: rv_target);
|
||||
RPC.ResetCurrentDrawTarget(player.PlayerId);
|
||||
RPC.ResetCurrentDrawTarget(playerId);
|
||||
|
||||
Logger.Info($"Canceled: {__instance.GetNameWithRole().RemoveHtmlTags()}", "Revolutionist");
|
||||
}
|
||||
@@ -2380,18 +2415,18 @@ class FixedUpdatePatch
|
||||
}
|
||||
if (GameStates.IsInTask && player.IsDrawDone() && player.IsAlive())
|
||||
{
|
||||
if (Main.RevolutionistStart.ContainsKey(player.PlayerId)) //如果存在字典
|
||||
if (Main.RevolutionistStart.ContainsKey(playerId)) //如果存在字典
|
||||
{
|
||||
if (Main.RevolutionistLastTime.ContainsKey(player.PlayerId))
|
||||
if (Main.RevolutionistLastTime.ContainsKey(playerId))
|
||||
{
|
||||
long nowtime = GetTimeStamp();
|
||||
if (Main.RevolutionistLastTime[player.PlayerId] != nowtime) Main.RevolutionistLastTime[player.PlayerId] = nowtime;
|
||||
int time = (int)(Main.RevolutionistLastTime[player.PlayerId] - Main.RevolutionistStart[player.PlayerId]);
|
||||
if (Main.RevolutionistLastTime[playerId] != nowtime) Main.RevolutionistLastTime[playerId] = nowtime;
|
||||
int time = (int)(Main.RevolutionistLastTime[playerId] - Main.RevolutionistStart[playerId]);
|
||||
int countdown = Options.RevolutionistVentCountDown.GetInt() - time;
|
||||
Main.RevolutionistCountdown.Clear();
|
||||
if (countdown <= 0)//倒计时结束
|
||||
{
|
||||
GetDrawPlayerCount(player.PlayerId, out var y);
|
||||
GetDrawPlayerCount(playerId, out var y);
|
||||
foreach (var pc in y.Where(x => x != null && x.IsAlive()))
|
||||
{
|
||||
pc.Suicide(PlayerState.DeathReason.Sacrifice);
|
||||
@@ -2401,17 +2436,17 @@ class FixedUpdatePatch
|
||||
}
|
||||
else
|
||||
{
|
||||
Main.RevolutionistCountdown.Add(player.PlayerId, countdown);
|
||||
Main.RevolutionistCountdown.Add(playerId, countdown);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Main.RevolutionistLastTime.TryAdd(player.PlayerId, Main.RevolutionistStart[player.PlayerId]);
|
||||
Main.RevolutionistLastTime.TryAdd(playerId, Main.RevolutionistStart[playerId]);
|
||||
}
|
||||
}
|
||||
else //如果不存在字典
|
||||
{
|
||||
Main.RevolutionistStart.TryAdd(player.PlayerId, GetTimeStamp());
|
||||
Main.RevolutionistStart.TryAdd(playerId, GetTimeStamp());
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@@ -2426,44 +2461,44 @@ class FixedUpdatePatch
|
||||
switch (player.GetCustomRole())
|
||||
{
|
||||
case CustomRoles.Veteran when GameStates.IsInTask:
|
||||
if (Main.VeteranInProtect.TryGetValue(player.PlayerId, out var vtime) && vtime + Options.VeteranSkillDuration.GetInt() < now)
|
||||
if (Main.VeteranInProtect.TryGetValue(playerId, out var vtime) && vtime + Options.VeteranSkillDuration.GetInt() < now)
|
||||
{
|
||||
Main.VeteranInProtect.Remove(player.PlayerId);
|
||||
Main.VeteranInProtect.Remove(playerId);
|
||||
player.RpcResetAbilityCooldown();
|
||||
player.Notify(string.Format(GetString("VeteranOffGuard"), (int)Main.VeteranNumOfUsed[player.PlayerId]));
|
||||
player.Notify(string.Format(GetString("VeteranOffGuard"), (int)Main.VeteranNumOfUsed[playerId]));
|
||||
}
|
||||
break;
|
||||
|
||||
case CustomRoles.Express when GameStates.IsInTask:
|
||||
if (Main.ExpressSpeedUp.TryGetValue(player.PlayerId, out var etime) && etime + Options.ExpressSpeedDur.GetInt() < now)
|
||||
if (Main.ExpressSpeedUp.TryGetValue(playerId, out var etime) && etime + Options.ExpressSpeedDur.GetInt() < now)
|
||||
{
|
||||
Main.ExpressSpeedUp.Remove(player.PlayerId);
|
||||
Main.AllPlayerSpeed[player.PlayerId] = Main.ExpressSpeedNormal;
|
||||
Main.ExpressSpeedUp.Remove(playerId);
|
||||
Main.AllPlayerSpeed[playerId] = Main.ExpressSpeedNormal;
|
||||
player.MarkDirtySettings();
|
||||
}
|
||||
break;
|
||||
|
||||
case CustomRoles.Grenadier when GameStates.IsInTask:
|
||||
if (Main.GrenadierBlinding.TryGetValue(player.PlayerId, out var gtime) && gtime + Options.GrenadierSkillDuration.GetInt() < now)
|
||||
if (Main.GrenadierBlinding.TryGetValue(playerId, out var gtime) && gtime + Options.GrenadierSkillDuration.GetInt() < now)
|
||||
{
|
||||
Main.GrenadierBlinding.Remove(player.PlayerId);
|
||||
Main.GrenadierBlinding.Remove(playerId);
|
||||
player.RpcResetAbilityCooldown();
|
||||
player.Notify(string.Format(GetString("GrenadierSkillStop"), (int)Main.GrenadierNumOfUsed[player.PlayerId]));
|
||||
player.Notify(string.Format(GetString("GrenadierSkillStop"), (int)Main.GrenadierNumOfUsed[playerId]));
|
||||
MarkEveryoneDirtySettingsV3();
|
||||
}
|
||||
if (Main.MadGrenadierBlinding.TryGetValue(player.PlayerId, out var mgtime) && mgtime + Options.GrenadierSkillDuration.GetInt() < now)
|
||||
if (Main.MadGrenadierBlinding.TryGetValue(playerId, out var mgtime) && mgtime + Options.GrenadierSkillDuration.GetInt() < now)
|
||||
{
|
||||
Main.MadGrenadierBlinding.Remove(player.PlayerId);
|
||||
Main.MadGrenadierBlinding.Remove(playerId);
|
||||
player.RpcResetAbilityCooldown();
|
||||
player.Notify(string.Format(GetString("GrenadierSkillStop"), (int)Main.GrenadierNumOfUsed[player.PlayerId]));
|
||||
player.Notify(string.Format(GetString("GrenadierSkillStop"), (int)Main.GrenadierNumOfUsed[playerId]));
|
||||
MarkEveryoneDirtySettingsV3();
|
||||
}
|
||||
break;
|
||||
|
||||
case CustomRoles.Lighter when GameStates.IsInTask:
|
||||
if (Main.Lighter.TryGetValue(player.PlayerId, out var ltime) && ltime + Options.LighterSkillDuration.GetInt() < now)
|
||||
if (Main.Lighter.TryGetValue(playerId, out var ltime) && ltime + Options.LighterSkillDuration.GetInt() < now)
|
||||
{
|
||||
Main.Lighter.Remove(player.PlayerId);
|
||||
Main.Lighter.Remove(playerId);
|
||||
player.RpcResetAbilityCooldown();
|
||||
player.Notify(GetString("LighterSkillStop"));
|
||||
player.MarkDirtySettings();
|
||||
@@ -2471,33 +2506,33 @@ class FixedUpdatePatch
|
||||
break;
|
||||
|
||||
case CustomRoles.SecurityGuard when GameStates.IsInTask:
|
||||
if (Main.BlockSabo.TryGetValue(player.PlayerId, out var stime) && stime + Options.SecurityGuardSkillDuration.GetInt() < now)
|
||||
if (Main.BlockSabo.TryGetValue(playerId, out var stime) && stime + Options.SecurityGuardSkillDuration.GetInt() < now)
|
||||
{
|
||||
Main.BlockSabo.Remove(player.PlayerId);
|
||||
Main.BlockSabo.Remove(playerId);
|
||||
player.RpcResetAbilityCooldown();
|
||||
player.Notify(GetString("SecurityGuardSkillStop"));
|
||||
}
|
||||
break;
|
||||
|
||||
case CustomRoles.TimeMaster when GameStates.IsInTask:
|
||||
if (Main.TimeMasterInProtect.TryGetValue(player.PlayerId, out var ttime) && ttime + Options.TimeMasterSkillDuration.GetInt() < now)
|
||||
if (Main.TimeMasterInProtect.TryGetValue(playerId, out var ttime) && ttime + Options.TimeMasterSkillDuration.GetInt() < now)
|
||||
{
|
||||
Main.TimeMasterInProtect.Remove(player.PlayerId);
|
||||
Main.TimeMasterInProtect.Remove(playerId);
|
||||
player.RpcResetAbilityCooldown();
|
||||
player.Notify(GetString("TimeMasterSkillStop"), (int)Main.TimeMasterNumOfUsed[player.PlayerId]);
|
||||
player.Notify(GetString("TimeMasterSkillStop"), (int)Main.TimeMasterNumOfUsed[playerId]);
|
||||
}
|
||||
break;
|
||||
|
||||
case CustomRoles.Mario when Main.MarioVentCount[player.PlayerId] > Options.MarioVentNumWin.GetInt() && GameStates.IsInTask:
|
||||
Main.MarioVentCount[player.PlayerId] = Options.MarioVentNumWin.GetInt();
|
||||
case CustomRoles.Mario when Main.MarioVentCount[playerId] > Options.MarioVentNumWin.GetInt() && GameStates.IsInTask:
|
||||
Main.MarioVentCount[playerId] = Options.MarioVentNumWin.GetInt();
|
||||
CustomWinnerHolder.ResetAndSetWinner(CustomWinner.Mario); //马里奥这个多动症赢了
|
||||
CustomWinnerHolder.WinnerIds.Add(player.PlayerId);
|
||||
CustomWinnerHolder.WinnerIds.Add(playerId);
|
||||
break;
|
||||
|
||||
case CustomRoles.Vulture when Vulture.BodyReportCount[player.PlayerId] >= Vulture.NumberOfReportsToWin.GetInt() && GameStates.IsInTask:
|
||||
Vulture.BodyReportCount[player.PlayerId] = Vulture.NumberOfReportsToWin.GetInt();
|
||||
case CustomRoles.Vulture when Vulture.BodyReportCount[playerId] >= Vulture.NumberOfReportsToWin.GetInt() && GameStates.IsInTask:
|
||||
Vulture.BodyReportCount[playerId] = Vulture.NumberOfReportsToWin.GetInt();
|
||||
CustomWinnerHolder.ResetAndSetWinner(CustomWinner.Vulture);
|
||||
CustomWinnerHolder.WinnerIds.Add(player.PlayerId);
|
||||
CustomWinnerHolder.WinnerIds.Add(playerId);
|
||||
break;
|
||||
|
||||
case CustomRoles.Pelican:
|
||||
@@ -2545,41 +2580,41 @@ class FixedUpdatePatch
|
||||
break;
|
||||
}
|
||||
|
||||
if (Main.AllKillers.TryGetValue(player.PlayerId, out var ktime) && ktime + Options.WitnessTime.GetInt() < now) Main.AllKillers.Remove(player.PlayerId);
|
||||
if (Main.AllKillers.TryGetValue(playerId, out var ktime) && ktime + Options.WitnessTime.GetInt() < now) Main.AllKillers.Remove(playerId);
|
||||
if (GameStates.IsInTask && player.IsAlive() && Options.LadderDeath.GetBool()) FallFromLadder.FixedUpdate(player);
|
||||
if (GameStates.IsInGame) LoversSuicide();
|
||||
|
||||
#region 傀儡师处理
|
||||
if (GameStates.IsInTask && Main.PuppeteerList.ContainsKey(player.PlayerId))
|
||||
if (GameStates.IsInTask && Main.PuppeteerList.ContainsKey(playerId))
|
||||
{
|
||||
if (!player.IsAlive() || Pelican.IsEaten(player.PlayerId))
|
||||
if (!player.IsAlive() || Pelican.IsEaten(playerId))
|
||||
{
|
||||
Main.PuppeteerList.Remove(player.PlayerId);
|
||||
Main.PuppeteerDelayList.Remove(player.PlayerId);
|
||||
Main.PuppeteerDelay.Remove(player.PlayerId);
|
||||
Main.PuppeteerList.Remove(playerId);
|
||||
Main.PuppeteerDelayList.Remove(playerId);
|
||||
Main.PuppeteerDelay.Remove(playerId);
|
||||
}
|
||||
else if (Main.PuppeteerDelayList[player.PlayerId] + Options.PuppeteerManipulationEndsAfterTime.GetInt() < now && Options.PuppeteerManipulationEndsAfterFixedTime.GetBool())
|
||||
else if (Main.PuppeteerDelayList[playerId] + Options.PuppeteerManipulationEndsAfterTime.GetInt() < now && Options.PuppeteerManipulationEndsAfterFixedTime.GetBool())
|
||||
{
|
||||
Main.PuppeteerList.Remove(player.PlayerId);
|
||||
Main.PuppeteerDelayList.Remove(player.PlayerId);
|
||||
Main.PuppeteerDelay.Remove(player.PlayerId);
|
||||
Main.PuppeteerList.Remove(playerId);
|
||||
Main.PuppeteerDelayList.Remove(playerId);
|
||||
Main.PuppeteerDelay.Remove(playerId);
|
||||
Main.AllAlivePlayerControls.Where(x => x.Is(CustomRoles.Puppeteer)).Do(x => NotifyRoles(SpecifySeer: x, SpecifyTarget: player));
|
||||
}
|
||||
else if (Main.PuppeteerDelayList[player.PlayerId] + Main.PuppeteerDelay[player.PlayerId] < now)
|
||||
else if (Main.PuppeteerDelayList[playerId] + Main.PuppeteerDelay[playerId] < now)
|
||||
{
|
||||
Vector2 puppeteerPos = player.transform.position;//PuppeteerListのKeyの位置
|
||||
Dictionary<byte, float> targetDistance = [];
|
||||
float dis;
|
||||
foreach (PlayerControl target in Main.AllAlivePlayerControls)
|
||||
{
|
||||
if (target.PlayerId == player.PlayerId || target.Is(CustomRoles.Pestilence)) continue;
|
||||
if (target.PlayerId == playerId || target.Is(CustomRoles.Pestilence)) continue;
|
||||
if (target.Is(CustomRoles.Puppeteer) && !Options.PuppeteerPuppetCanKillPuppeteer.GetBool()) continue;
|
||||
if (target.Is(CustomRoleTypes.Impostor) && !Options.PuppeteerPuppetCanKillImpostors.GetBool()) continue;
|
||||
|
||||
dis = Vector2.Distance(puppeteerPos, target.transform.position);
|
||||
targetDistance.Add(target.PlayerId, dis);
|
||||
}
|
||||
if (targetDistance.Any())
|
||||
if (targetDistance.Count > 0)
|
||||
{
|
||||
var min = targetDistance.OrderBy(c => c.Value).FirstOrDefault();//一番値が小さい
|
||||
PlayerControl target = GetPlayerById(min.Key);
|
||||
@@ -2588,15 +2623,15 @@ class FixedUpdatePatch
|
||||
{
|
||||
if (player.RpcCheckAndMurder(target, true))
|
||||
{
|
||||
var puppeteerId = Main.PuppeteerList[player.PlayerId];
|
||||
var puppeteerId = Main.PuppeteerList[playerId];
|
||||
RPC.PlaySoundRPC(puppeteerId, Sounds.KillSound);
|
||||
target.SetRealKiller(GetPlayerById(puppeteerId));
|
||||
player.Kill(target);
|
||||
player.MarkDirtySettings();
|
||||
target.MarkDirtySettings();
|
||||
Main.PuppeteerList.Remove(player.PlayerId);
|
||||
Main.PuppeteerDelayList.Remove(player.PlayerId);
|
||||
Main.PuppeteerDelay.Remove(player.PlayerId);
|
||||
Main.PuppeteerList.Remove(playerId);
|
||||
Main.PuppeteerDelayList.Remove(playerId);
|
||||
Main.PuppeteerDelay.Remove(playerId);
|
||||
NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
|
||||
NotifyRoles(SpecifySeer: target, SpecifyTarget: target);
|
||||
}
|
||||
@@ -2647,7 +2682,7 @@ class FixedUpdatePatch
|
||||
{
|
||||
if (GameStates.IsLobby)
|
||||
{
|
||||
if (Main.playerVersion.TryGetValue(__instance.PlayerId, out var ver))
|
||||
if (Main.playerVersion.TryGetValue(playerId, out var ver))
|
||||
{
|
||||
if (Main.ForkId != ver.forkId) // フォークIDが違う場合
|
||||
__instance.cosmetics.nameText.text = $"<color=#ff0000><size=1.2>{ver.forkId}</size>\n{__instance?.name}</color>";
|
||||
@@ -2659,11 +2694,11 @@ class FixedUpdatePatch
|
||||
}
|
||||
if (GameStates.IsInGame)
|
||||
{
|
||||
var RoleTextData = GetRoleText(PlayerControl.LocalPlayer.PlayerId, __instance.PlayerId);
|
||||
var RoleTextData = GetRoleText(PlayerControl.LocalPlayer.PlayerId, playerId);
|
||||
|
||||
//if (Options.CurrentGameMode == CustomGameMode.HideAndSeek)
|
||||
//{
|
||||
// var hasRole = main.AllPlayerCustomRoles.TryGetValue(__instance.PlayerId, out var role);
|
||||
// var hasRole = main.AllPlayerCustomRoles.TryGetValue(playerId, out var role);
|
||||
// if (hasRole) RoleTextData = Utils.GetRoleTextHideAndSeek(__instance.Data.Role.Role, role);
|
||||
//}
|
||||
RoleText.text = RoleTextData.Item1;
|
||||
@@ -2986,8 +3021,7 @@ class FixedUpdatePatch
|
||||
}*/
|
||||
|
||||
//Devourer
|
||||
bool targetDevoured = Devourer.HideNameOfConsumedPlayer.GetBool() && Devourer.PlayerSkinsCosumed.Any(a => a.Value.Contains(target.PlayerId));
|
||||
if (targetDevoured)
|
||||
if (Devourer.HideNameOfConsumedPlayer.GetBool() && Devourer.PlayerSkinsCosumed.Any(a => a.Value.Contains(target.PlayerId)))
|
||||
RealName = GetString("DevouredName");
|
||||
|
||||
// Camouflage
|
||||
|
||||
@@ -257,7 +257,7 @@ class CreatePlayerPatch
|
||||
if (Main.OverrideWelcomeMsg != string.Empty) Utils.SendMessage(Main.OverrideWelcomeMsg, client.Character.PlayerId);
|
||||
else TemplateManager.SendTemplate("welcome", client.Character.PlayerId, true);
|
||||
}, 3f, "Welcome Message");
|
||||
if (Main.OverrideWelcomeMsg == string.Empty && Main.PlayerStates.Any() && Main.clientIdList.Contains(client.Id))
|
||||
if (Main.OverrideWelcomeMsg == string.Empty && Main.PlayerStates.Count > 0 && Main.clientIdList.Contains(client.Id))
|
||||
{
|
||||
if (Options.AutoDisplayKillLog.GetBool())
|
||||
{
|
||||
|
||||
@@ -96,7 +96,7 @@ class RepairSystemPatch
|
||||
if (Options.DisableAirshipCargoLightsPanel.GetBool() && Vector2.Distance(player.transform.position, new(30.56f, 2.12f)) <= 2f) return false;
|
||||
break;
|
||||
case SystemTypes.Sabotage when AmongUsClient.Instance.NetworkMode != NetworkModes.FreePlay:
|
||||
if (Main.BlockSabo.Any()) return false;
|
||||
if (Main.BlockSabo.Count > 0) return false;
|
||||
if (Glitch.hackedIdList.ContainsKey(player.PlayerId))
|
||||
{
|
||||
player.Notify(string.Format(Translator.GetString("HackedByGlitch"), "Sabotage"));
|
||||
@@ -218,7 +218,7 @@ class CloseDoorsPatch
|
||||
{
|
||||
bool allow = !Options.DisableSabotage.GetBool() && Options.CurrentGameMode is not CustomGameMode.SoloKombat and not CustomGameMode.FFA and not CustomGameMode.MoveAndStop;
|
||||
|
||||
if (Main.BlockSabo.Any()) allow = false;
|
||||
if (Main.BlockSabo.Count > 0) allow = false;
|
||||
if (Options.DisableCloseDoor.GetBool()) allow = false;
|
||||
|
||||
Logger.Info($"({room}) => {(allow ? "Allowed" : "Blocked")}", "DoorClose");
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TOHE.Patches;
|
||||
|
||||
|
||||
@@ -478,6 +478,9 @@ internal class SelectRolesPatch
|
||||
}
|
||||
}
|
||||
|
||||
if (nimbleList.Count == 0) nimbleSpawn = false;
|
||||
if (physicistList.Count == 0) physicistSpawn = false;
|
||||
|
||||
if (Main.SetAddOns.Values.Any(x => x.Contains(CustomRoles.Nimble)))
|
||||
{
|
||||
nimbleSpawn = true;
|
||||
@@ -574,8 +577,8 @@ internal class SelectRolesPatch
|
||||
AssignCustomRole(kv.Value, kv.Key);
|
||||
}
|
||||
|
||||
if (Main.NimblePlayer != byte.MaxValue) Main.PlayerStates[Main.NimblePlayer].SetSubRole(CustomRoles.Nimble);
|
||||
if (Main.PhysicistPlayer != byte.MaxValue) Main.PlayerStates[Main.PhysicistPlayer].SetSubRole(CustomRoles.Physicist);
|
||||
if (Main.PlayerStates.TryGetValue(Main.NimblePlayer, out var nimbleState)) nimbleState.SetSubRole(CustomRoles.Nimble);
|
||||
if (Main.PlayerStates.TryGetValue(Main.PhysicistPlayer, out var physicistState)) physicistState.SetSubRole(CustomRoles.Physicist);
|
||||
|
||||
foreach (var item in Main.SetAddOns)
|
||||
{
|
||||
@@ -1201,7 +1204,7 @@ internal class SelectRolesPatch
|
||||
catch (Exception ex)
|
||||
{
|
||||
Utils.ErrorEnd("Select Role Postfix");
|
||||
Logger.Fatal(ex.ToString(), "Select Role Prefix");
|
||||
Logger.Fatal(ex.ToString(), "Select Role Postfix");
|
||||
}
|
||||
}
|
||||
private static void AssignDesyncRole(CustomRoles role, PlayerControl player, Dictionary<byte, CustomRpcSender> senders, Dictionary<(byte, byte), RoleTypes> rolesMap, RoleTypes BaseRole, RoleTypes hostBaseRole = RoleTypes.Crewmate)
|
||||
@@ -1265,7 +1268,7 @@ internal class SelectRolesPatch
|
||||
count = Count;
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
if (!AllPlayers.Any()) break;
|
||||
if (AllPlayers.Count == 0) break;
|
||||
var rand = IRandom.Instance;
|
||||
var player = AllPlayers[rand.Next(0, AllPlayers.Count)];
|
||||
AllPlayers.Remove(player);
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
- This mode makes everyone a killer and the last player alive wins
|
||||
- Features: Random events, ranks and scoring, random ability gain for every kill, game timer, scoreboard (task list), unique end screen, fully customizable
|
||||
### Overall improvements
|
||||
- Role spawn chances are in percentages
|
||||
- Gain more ability uses for completing tasks as crewmate roles
|
||||
- Gain more ability uses for getting kills as impostor roles
|
||||
- Most shapeshifting roles that only used shapeshifting as an ability trigger or a target selector now don't actually shapeshift with the egg animation, it's automatically canceled
|
||||
@@ -129,6 +130,10 @@
|
||||
- Detour (Crewmate)
|
||||
- Gaulois (Crewmate)
|
||||
- Analyzer (Crewmate)
|
||||
- Electric (Crewmate)
|
||||
- Mole (Crewmate)
|
||||
- Tornado (Crewmate)
|
||||
- Sentinel (Crewmate)
|
||||
- Romantic (Neutral)
|
||||
- Werewolf (Neutral)
|
||||
- Imitator (Neutral)
|
||||
@@ -140,6 +145,11 @@
|
||||
- Postman (Neutral)
|
||||
- Reckless (Neutral)
|
||||
- Magician (Neutral)
|
||||
- Enderman (Neutral)
|
||||
- Mycologist (Neutral)
|
||||
- Bubble (Neutral)
|
||||
- Hookshot (Neutral)
|
||||
- Sprayer (Neutral)
|
||||
- Undertaker (Impostor)
|
||||
- Gambler (Impostor)
|
||||
- Mastermind (Impostor)
|
||||
@@ -165,13 +175,14 @@
|
||||
<br>
|
||||
|
||||
## Credit to these mods and their developers for the code and help:
|
||||
### :star: [TOH Enhanced](https://github.com/0xDrMoe/TownofHost-Enhanced) :
|
||||
### :star: [TOHEN](https://github.com/0xDrMoe/TownofHost-Enhanced) :
|
||||
>
|
||||
> - Our repo is forked from TOHE
|
||||
> - Our repo is forked from TOHEN
|
||||
>
|
||||
### :star: [TOH Edited](https://github.com/KARPED1EM/TownOfHostEdited) :
|
||||
### :star: [TOHE/TONX](https://github.com/KARPED1EM/TownOfHostEdited) :
|
||||
>
|
||||
> - Our repo is a continuation of TOHE
|
||||
> - TONX reference: Modify character limit for chat messages
|
||||
>
|
||||
### :star: [TOH](https://github.com/tukasa0001/TownOfHost) :
|
||||
>
|
||||
|
||||
+13
-3
@@ -1073,6 +1073,7 @@
|
||||
"ForceOwnLanguageRoleName","强制用您的语言显示职业名","Force role names in your language if possible","Использовать имя роли на вашем языке если возможно","強制用您的語言顯示職業名","强制用您的语言显示职业名"
|
||||
"VersionCheat","绕过版本同步检查","Bypass version synchronization check","Обходить проверку синхронизаций версий","繞過版本同步檢查","绕过版本同步检查"
|
||||
"GodMode","上帝模式","God Mode","Режим Бога","上帝模式",""
|
||||
"EnableDarkTheme","","Enable Dark Theme","","",""
|
||||
"AutoDisplayKillLog","结束后自动显示击杀记录","Display Kill-log","Показывать убийства","結束後自動顯示殺人紀錄","结束后自动显示击杀记录"
|
||||
"AutoDisplayLastRoles","结束后自动显示上局职业","Display Last Roles","Показывать роли в прошлой игре","結束後自動顯示上局職業","结束后自动显示上局职业"
|
||||
"AutoDisplayLastResult","结束后自动显示最终结果","Auto Display Last Result","Отображать результат последней игры в чате","結束後自動顯示最終結果","结束后自动显示最终结果"
|
||||
@@ -1303,6 +1304,7 @@
|
||||
"PuppeteerPuppetCanKillPuppeteer","","Puppet Can Kill The <color=#ff1919>Puppeteer</color>","","",""
|
||||
"PuppeteerMaxPuppets","","Maximum Number of Puppets","","",""
|
||||
"PuppeteerDiesAfterMaxPuppets","","<color=#ff1919>Puppeteer</color> Dies After Running Out Of Puppets","","",""
|
||||
"ScavengerKillDuration","","Time After Kill Completes","","",""
|
||||
"DeadImpCantSabotage","<color=#ff1919>内鬼</color>死后不能破坏","<color=#ff1919>Impostors</color> can't sabotage after they've died","Мертвые <color=#ff1919>Предатели</color> не могут саботажить","<color=#ff1919>内鬼</color>死后不能破坏",""
|
||||
"DeadCrewCantSabotage","<color=#8cffff>船员</color>死后不能破坏","<color=#8cffff>Crewmates</color> can't sabotage after they've died","Мертвые <color=#8cffff>Члены Экипажа</color> не могут саботажить","",""
|
||||
"DeadNeutralCantSabotage","<color=#7f8c8d>中立</color>死后不能破坏","<color=#7f8c8d>Neutrals</color> can't sabotage after they've died","Мертвые <color=#7f8c8d>Нейтралы</color> не могут саботажить","",""
|
||||
@@ -1527,6 +1529,7 @@
|
||||
"DeactivationIsVisibleOFF","<color=#ff4c6f>关闭</color>","<color=#ff4c6f>OFF</color>","<color=#ff4c6f>ВЫКЛ</color>","",""
|
||||
"MedicResetCooldown","在尝试击杀时,将杀手的冷却时间重置为","On kill attempt, reset murderer's cooldown to","При попытке убийства сбросывать откат убийства на","",""
|
||||
"MedicShieldedCanBeGuessed","猜测忽略<color=#00ff97>医疗</color>防护罩","Guessing ignores <color=#00ff97>Medic</color> shield","Игрока с щитом <color=#00ff97>Медика</color> можно угадать","",""
|
||||
"MedicAmountOfShields","","Number of Shields Per Game","","",""
|
||||
"DivinatorSkillLimit","调查员调查最大次数","(Initial) Max number of ability uses","Лимит Способности","占卜次數上限","占卜次数上限"
|
||||
"MadmateSpawnMode","<color=#ff1919>叛徒</color>生成模式","<color=#ff1919>Madmate</color> spawning mode","Режим появления <color=#ff1919>Безумца</color>","<color=#ff1919>叛徒</color>生成模式","<color=#ff1919>叛徒</color>生成模式"
|
||||
"MadmateSpawnMode.Assign","开局分配","Assign","Назначать","開局分配","开局分配"
|
||||
@@ -2522,12 +2525,12 @@
|
||||
"DivinatorCheck.Result7","<b>{0}</b>是保镖、自爆兵、烟花商人或核武器其中之一","<b>{0}</b> is either Bodyguard, Bomber, Lookout, Vengeful Romantic, Ruthless Romantic, Fireworker, or Nuker","","",""
|
||||
"DivinatorCheck.Result8","<b>{0}</b>是赏金猎人、侦探、FFF团、清理工、美杜莎或愚者其中之一","<b>{0}</b> is either Bounty Hunter, Sprayer, Mafioso, Detective, Hater, Cleaner, Medusa, or Psychic","","",""
|
||||
"DivinatorCheck.Result9","<b>{0}</b>是罪犯、处刑者、律师、告密者、分散者或法医其中之一","<b>{0}</b> is either Convict, Penguin, Hookshot, Executioner, Lawyer, Snitch, Disperser, or Doctor","","",""
|
||||
"DivinatorCheck.Result10","<b>{0}</b>是议员、独裁者、法官、被诅咒的灵魂或呪狼其中之一","<b>{0}</b> is either Councillor, Escort, Bubble, Dictator, Judge, Cleanser, or Cursed Wolf","","",""
|
||||
"DivinatorCheck.Result10","<b>{0}</b>是议员、独裁者、法官、被诅咒的灵魂或呪狼其中之一","<b>{0}</b> is either Councillor, Escort, Bubble, Shiftguard, Dictator, Judge, Cleanser, or Cursed Wolf","","",""
|
||||
"DivinatorCheck.Result11","<b>{0}</b>是瘾君子、逃亡者、矿工或化形者其中之一","<b>{0}</b> is either Addict, Alchemist, Mycologist, Escapist, Miner, Demolitionist, or Morphling","","",""
|
||||
"DivinatorCheck.Result12","<b>{0}</b>是玩家、僵尸、网红、大明星、死亡契约或吞噬者其中之一","<b>{0}</b> is either Demon, Enderman, Doormaster, Zombie, Celebrity, Super Star, Deathpact, or Devourer","","",""
|
||||
"DivinatorCheck.Result13","<b>{0}</b>是神,神谕,幻想家,检查员其中之一","<b>{0}</b> is either God, Oracle, Gambler, Insight, Visionary, Nice Eraser, Swapper, or Inspector","","",""
|
||||
"DivinatorCheck.Result14","<b>{0}</b>是隐匿者、市长、被害妄想症、小偷或卫道士其中之一","<b>{0}</b> is either Anonymous, Mastermind, Tunneler, Spy, Mayor, Paranoid, Pickpocket, or Vindicator","","",""
|
||||
"DivinatorCheck.Result15","<b>{0}</b>是传染性的、病毒的、君主的、革命者的或魅魔的其中之一","<b>{0}</b> is either Infectious, Detour, Virus, Agitater, Monarch, Revolutionist, Express, or Cultist","","",""
|
||||
"DivinatorCheck.Result15","<b>{0}</b>是传染性的、病毒的、君主的、革命者的或魅魔的其中之一","<b>{0}</b> is either Infectious, Detour, Virus, Agitator, Monarch, Revolutionist, Express, or Cultist","","",""
|
||||
"DivinatorCheck.Result16","<b>{0}</b>是冤罪师、受虐狂、抑制者、修理工或破坏者其中之一","<b>{0}</b> is either Innocent, Gaulois, Sapper, Refugee, Bandit, Inhibitor, Mechanic, or Saboteur","","",""
|
||||
"DivinatorCheck.Result17","<b>{0}</b>是医生、马里奥、小丑、潜伏者还是阳光开朗大男孩其中之一","<b>{0}</b> is either Medic, Vector, Analyzer, RiftMaker, Jester, The Glitch, Lurker, or Sunnyboy","","",""
|
||||
"DivinatorCheck.Result18","<b>{0}</b>是黑手党、惩罚者、教父、缺点者、幸运儿或失败者其中之一","<b>{0}</b> is either Nemesis, Hitman, Gangster, Glitch, Luckey, or Underdog","","",""
|
||||
@@ -2622,6 +2625,13 @@
|
||||
"JailedNotifyMsg","","You have been locked up in Jail by the Jailor. No one can guess or judge you and you can only guess Jailor.\n\nIf Jailor votes you, you will be executed after the meeting ends.","","",""
|
||||
"JailorTitle","","Jailor Message","","",""
|
||||
|
||||
"## Shiftguard"
|
||||
"Shiftguard","","Shiftguard","","",""
|
||||
"ShiftguardInfo","","Know When Someone Shapeshifts","","",""
|
||||
"ShiftguardInfoLong","","(Crewmates):\nAs the Shiftguard, when someone shapeshifts or unshifts, you will be notified","","",""
|
||||
"ShiftguardNotifySS","","Someone just shapeshifted as someone","","",""
|
||||
"ShiftguardNotifyUnshift","","Someone just unshifted","","",""
|
||||
|
||||
"## Insight"
|
||||
"Insight","","Insight","","",""
|
||||
"InsightInfo","","Know What Roles Spawned","","",""
|
||||
@@ -3366,7 +3376,7 @@
|
||||
"PrefixB.Physicist","","<color=#ffffff>(</color>Physicist<color=#ffffff>)</color> ","","",""
|
||||
|
||||
"## Agitater"
|
||||
"Agitater","煽动者","Agitater","Агитатор","","Agitador"
|
||||
"Agitater","煽动者","Agitator","Агитатор","","Agitador"
|
||||
"AgitaterInfo","这个炸弹给你了!","Pass a Bomb onto others","Вот тебе подарок в виде бомбы","","Pásale la patata caliente a otros"
|
||||
"AgitaterInfoLong","(中立阵营):\n煽动者的击杀是使用炸弹。对一名玩家使用你的击杀按钮来传递炸弹,每轮只能传递一次。收到炸弹的玩家收到炸弹时会收到通知,他们需要通过靠近一名玩家将炸弹传递给另一名玩家。","(Neutrals):\nAs the Agitater, your premise is essentially Hot Potato.\n\nUse your kill button on a player to pass the bomb.\nThis can only be done once per round.\n\nThe player who receives the bomb will be notified when receiving said bomb, in which they need to pass it to another player by getting near a player.\n\nWhen a meeting is called, the player with the bomb dies.\n\nIf trying to pass to Pestilence or a Veteran on alert, the bombed player dies instead.\nOptionally, the Agitater cannot receive the bomb.","(Нейтрал):\nКак Агитатор, ваша задача - это, по сути, Догонялки.\n\nИспользуйте кнопку Убийства на игроке, чтобы передать бомбу.\nЭто можно сделать только один раз за раунд.\n\nИгрок, получивший бомбу, будет уведомлен о получении бомбы, в котором он должен передать ее другому игроку, подойдя к нему. \n\nКогда объявляется собрание, игрок с бомбой погибает.\n\nЕсли он пытается передать бомбу Чуме или ветерану, находящемуся в состоянии боевой готовности, то вместо него погибает игрок, получивший бомбу.\nОпционально, Агитатор не может получить бомбу.","","(Neutros):\nTu función de Agitador es esencialmente el juego de la Patata Caliente.\n\nUsa tu botón de matar en un jugador para pasar una bomba.\nEsto solo se puede hacer una vez por ronda.\n\nEl jugador que reciba la bomba será notificado cuando la reciba, y deberá pasarla a otro jugador acercándose a el.\n\nCuando se llame una reunión, el jugador con la bomba morirá.\n\nIntentar pasar la bomba a la Pestilencia o a un Veterano en alerta te matará.\nOpcionalmente, el Agitador no podrá recibir la bomba."
|
||||
"AgitaterBombCooldown","<color=#F4A460>煽动者</color>炸弹冷却时间","<color=#F4A460>Agitater</color> bomb coolodown","Откат бомбы <color=#F4A460>Агитатора</color>","",""
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -89,6 +89,11 @@ namespace TOHE.Roles.AddOns.Crewmate
|
||||
{
|
||||
if (pc.Is(CustomRoles.Stressed))
|
||||
{
|
||||
if (!pc.GetPlayerTaskState().hasTasks)
|
||||
{
|
||||
Main.PlayerStates[pc.PlayerId].RemoveSubRole(CustomRoles.Stressed);
|
||||
continue;
|
||||
}
|
||||
Timers.Add(pc.PlayerId, StartingTime);
|
||||
LastUpdates.Add(pc.PlayerId, GetTimeStamp() + 1);
|
||||
}
|
||||
@@ -117,7 +122,7 @@ namespace TOHE.Roles.AddOns.Crewmate
|
||||
}
|
||||
|
||||
if (pc.IsModClient() && pc.PlayerId != 0) SendRPC(pc.PlayerId, Timers[pc.PlayerId], LastUpdates[pc.PlayerId]);
|
||||
if (pc.PlayerId != 0) NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
||||
if (!pc.IsModClient()) NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
||||
}
|
||||
|
||||
public static void SendRPC(byte id, int time, long lastUpdate)
|
||||
|
||||
@@ -66,9 +66,7 @@ namespace TOHE.Roles.Crewmate
|
||||
}
|
||||
public static void OnFixedUpdate(PlayerControl pc)
|
||||
{
|
||||
if (pc == null) return;
|
||||
if (!pc.Is(CustomRoles.Aid)) return;
|
||||
if (!ShieldedPlayers.Any()) return;
|
||||
if (pc == null || !pc.Is(CustomRoles.Aid) || ShieldedPlayers.Count == 0) return;
|
||||
|
||||
bool change = false;
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace TOHE.Roles.Crewmate
|
||||
{
|
||||
shieldedPlayers.Remove(shieldedId);
|
||||
}
|
||||
if (clearAll && shieldedPlayers.Any()) shieldedPlayers.Clear();
|
||||
if (clearAll && shieldedPlayers.Count > 0) shieldedPlayers.Clear();
|
||||
}
|
||||
public static string GetProgressText(byte playerId)
|
||||
{
|
||||
|
||||
@@ -163,7 +163,7 @@
|
||||
if (!seer.Is(CustomRoles.Bloodhound)) return string.Empty;
|
||||
if (target != null && seer.PlayerId != target.PlayerId) return string.Empty;
|
||||
if (GameStates.IsMeeting) return string.Empty;
|
||||
if (BloodhoundTargets.ContainsKey(seer.PlayerId) && BloodhoundTargets[seer.PlayerId].Any())
|
||||
if (BloodhoundTargets.ContainsKey(seer.PlayerId) && BloodhoundTargets[seer.PlayerId].Count > 0)
|
||||
{
|
||||
var arrows = string.Empty;
|
||||
foreach (byte targetId in BloodhoundTargets[seer.PlayerId].ToArray())
|
||||
|
||||
@@ -193,6 +193,7 @@ public static class Divinator
|
||||
CustomRoles.Judge or
|
||||
CustomRoles.Escort or
|
||||
CustomRoles.Bubble or
|
||||
CustomRoles.Shiftguard or
|
||||
//CustomRoles.CursedSoul or
|
||||
CustomRoles.Cleanser or
|
||||
CustomRoles.CursedWolf
|
||||
|
||||
@@ -171,13 +171,11 @@ namespace TOHE.Roles.Crewmate
|
||||
|
||||
public static void OnFixedUpdate()
|
||||
{
|
||||
if (!IsEnable) return;
|
||||
if (!GameStates.IsInTask) return;
|
||||
if (!Triggers.Any() && !TriggerDelays.Any()) return;
|
||||
if (!IsEnable || !GameStates.IsInTask || Triggers.Count == 0 && TriggerDelays.Count == 0) return;
|
||||
|
||||
long now = GetTimeStamp();
|
||||
|
||||
if (TriggerDelays.Any())
|
||||
if (TriggerDelays.Count > 0)
|
||||
{
|
||||
foreach (var x in TriggerDelays.ToArray())
|
||||
{
|
||||
@@ -200,7 +198,7 @@ namespace TOHE.Roles.Crewmate
|
||||
}
|
||||
}
|
||||
|
||||
if (Triggers.Any())
|
||||
if (Triggers.Count > 0)
|
||||
{
|
||||
foreach (var pc in Main.AllAlivePlayerControls.Where(pc => !playerIdList.Contains(pc.PlayerId)).ToArray()) // Check for all alive players except Druids - Worst case scenario it's 14 loops
|
||||
{
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace TOHE.Roles.Crewmate
|
||||
CustomRoles.Express,
|
||||
CustomRoles.NiceEraser,
|
||||
CustomRoles.TaskManager,
|
||||
CustomRoles.Shiftguard,
|
||||
CustomRoles.Mole,
|
||||
CustomRoles.Sentinel,
|
||||
CustomRoles.Electric,
|
||||
|
||||
+13
-11
@@ -22,6 +22,7 @@ public static class Medic
|
||||
private static OptionItem ShieldDeactivationIsVisible;
|
||||
private static OptionItem ResetCooldown;
|
||||
public static OptionItem GuesserIgnoreShield;
|
||||
private static OptionItem AmountOfShields;
|
||||
|
||||
public static readonly string[] MedicWhoCanSeeProtectName =
|
||||
[
|
||||
@@ -52,7 +53,7 @@ public static class Medic
|
||||
WhoCanSeeProtect = StringOptionItem.Create(Id + 10, "MedicWhoCanSeeProtect", MedicWhoCanSeeProtectName, 0, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Medic]);
|
||||
KnowShieldBroken = StringOptionItem.Create(Id + 16, "MedicKnowShieldBroken", KnowShieldBrokenOption, 1, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Medic]);
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Medic]);
|
||||
ShieldDeactivatesWhenMedicDies = BooleanOptionItem.Create(Id + 24, "MedicShieldDeactivatesWhenMedicDies", true, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Medic]);
|
||||
ShieldDeactivationIsVisible = StringOptionItem.Create(Id + 25, "MedicShielDeactivationIsVisible", ShieldDeactivationIsVisibleOption, 0, TabGroup.CrewmateRoles, false)
|
||||
@@ -62,6 +63,8 @@ public static class Medic
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
GuesserIgnoreShield = BooleanOptionItem.Create(Id + 32, "MedicShieldedCanBeGuessed", true, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Medic]);
|
||||
AmountOfShields = IntegerOptionItem.Create(Id + 34, "MedicAmountOfShields", new(1, 14, 1), 1, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Medic]);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -69,7 +72,7 @@ public static class Medic
|
||||
ProtectList = [];
|
||||
ProtectLimit = [];
|
||||
TempMarkProtected = byte.MaxValue;
|
||||
SkillLimit = 1;
|
||||
SkillLimit = AmountOfShields.GetInt();
|
||||
}
|
||||
public static void Add(byte playerId)
|
||||
{
|
||||
@@ -129,7 +132,6 @@ public static class Medic
|
||||
if (ProtectList.Contains(target.PlayerId)) return;
|
||||
|
||||
ProtectLimit[killer.PlayerId]--;
|
||||
SkillLimit--;
|
||||
|
||||
SendRPC(killer.PlayerId);
|
||||
ProtectList.Add(target.PlayerId);
|
||||
@@ -186,7 +188,6 @@ public static class Medic
|
||||
Main.AllPlayerControls.Where(x => ProtectList.Contains(x.PlayerId)).Do(x => x.Notify(Translator.GetString("MedicKillerTryBrokenShieldTargetForTarget")));
|
||||
break;
|
||||
default:
|
||||
Utils.NotifyRoles(); // What is this?? Why is this here??
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -200,13 +201,12 @@ public static class Medic
|
||||
if (ShieldDeactivationIsVisible.GetInt() == 1)
|
||||
{
|
||||
TempMarkProtected = byte.MaxValue;
|
||||
foreach (byte pc in playerIdList.ToArray())
|
||||
foreach (byte id in playerIdList.ToArray())
|
||||
{
|
||||
Utils.NotifyRoles(SpecifySeer: Utils.GetPlayerById(pc));
|
||||
}
|
||||
foreach (byte pc in ProtectList.ToArray())
|
||||
{
|
||||
Utils.NotifyRoles(SpecifySeer: Utils.GetPlayerById(pc));
|
||||
foreach (byte id2 in ProtectList.ToArray())
|
||||
{
|
||||
Utils.NotifyRoles(SpecifySeer: Utils.GetPlayerById(id), SpecifyTarget: Utils.GetPlayerById(id2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -215,9 +215,11 @@ public static class Medic
|
||||
if (!target.Is(CustomRoles.Medic)) return;
|
||||
if (!ShieldDeactivatesWhenMedicDies.GetBool()) return;
|
||||
|
||||
if (!playerIdList.All(x => !Utils.GetPlayerById(x).IsAlive())) return; // If not all Medic-s are dead, return
|
||||
|
||||
foreach (byte pc in ProtectList.ToArray())
|
||||
{
|
||||
Utils.NotifyRoles(SpecifySeer: Utils.GetPlayerById(pc));
|
||||
Utils.NotifyRoles(SpecifySeer: Utils.GetPlayerById(pc), SpecifyTarget: target);
|
||||
}
|
||||
Utils.NotifyRoles(SpecifySeer: target);
|
||||
|
||||
|
||||
@@ -15,6 +15,10 @@ namespace TOHE.Roles.Crewmate
|
||||
var vents = UnityEngine.Object.FindObjectsOfType<Vent>();
|
||||
var vent = vents[IRandom.Instance.Next(0, vents.Count)];
|
||||
physics.RpcBootFromVent(vent.Id);
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
pc.TPtoRndVent();
|
||||
}, 0.55f, "Mole TP");
|
||||
}, 0.5f, "Mole BootFromVent");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ public static class ParityCop
|
||||
|
||||
if (((target1.Is(Team.Impostor) || target1.GetCustomSubRoles().Any(role => role.IsImpostorTeamV3())) && (target2.Is(Team.Impostor) || target2.GetCustomSubRoles().Any(role => role.IsImpostorTeamV3()))) ||
|
||||
((target1.Is(Team.Neutral) || target1.GetCustomSubRoles().Any(role => role.IsNeutralTeamV2())) && (target2.Is(Team.Neutral) || target2.GetCustomSubRoles().Any(role => role.IsNeutralTeamV2()))) ||
|
||||
(target1.Is(Team.Crewmate) && (target1.GetCustomSubRoles().Any(role => role.IsCrewmateTeamV2()) || (!target1.GetCustomSubRoles().Any())) && target2.Is(Team.Crewmate) && (target2.GetCustomSubRoles().Any(role => role.IsCrewmateTeamV2()) || !target2.GetCustomSubRoles().Any())))
|
||||
(target1.Is(Team.Crewmate) && (target1.GetCustomSubRoles().Any(role => role.IsCrewmateTeamV2()) || (target1.GetCustomSubRoles().Count == 0)) && target2.Is(Team.Crewmate) && (target2.GetCustomSubRoles().Any(role => role.IsCrewmateTeamV2()) || target2.GetCustomSubRoles().Count == 0)))
|
||||
{
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
@@ -210,11 +210,11 @@ public static class ParityCop
|
||||
string roleT1 = string.Empty, roleT2 = string.Empty;
|
||||
if (target1.Is(Team.Impostor) || target1.GetCustomSubRoles().Any(role => role.IsImpostorTeamV3())) roleT1 = "Impostor";
|
||||
else if (target1.Is(Team.Neutral) || target1.GetCustomSubRoles().Any(role => role.IsNeutralTeamV2())) roleT1 = "Neutral";
|
||||
else if (target1.Is(Team.Crewmate) && (target1.GetCustomSubRoles().Any(role => role.IsCrewmateTeamV2()) || (!target1.GetCustomSubRoles().Any())))
|
||||
else if (target1.Is(Team.Crewmate) && (target1.GetCustomSubRoles().Any(role => role.IsCrewmateTeamV2()) || (target1.GetCustomSubRoles().Count == 0)))
|
||||
|
||||
if (target2.Is(Team.Impostor) || target2.GetCustomSubRoles().Any(role => role.IsImpostorTeamV3())) roleT2 = "Impostor";
|
||||
else if (target2.Is(Team.Neutral) || target2.GetCustomSubRoles().Any(role => role.IsNeutralTeamV2())) roleT2 = "Neutral";
|
||||
else if (target2.Is(Team.Crewmate) && (target2.GetCustomSubRoles().Any(role => role.IsCrewmateTeamV2()) || !target2.GetCustomSubRoles().Any())) roleT2 = "Crewmate";
|
||||
else if (target2.Is(Team.Crewmate) && (target2.GetCustomSubRoles().Any(role => role.IsCrewmateTeamV2()) || target2.GetCustomSubRoles().Count == 0)) roleT2 = "Crewmate";
|
||||
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ public static class Psychic
|
||||
{
|
||||
playerIdList.Add(playerId);
|
||||
}
|
||||
public static bool IsEnable => playerIdList.Any();
|
||||
public static bool IsEnable => playerIdList.Count > 0;
|
||||
private static void SendRPC()
|
||||
{
|
||||
if (!IsEnable || !Utils.DoRPC) return;
|
||||
@@ -67,7 +67,7 @@ public static class Psychic
|
||||
}
|
||||
public static void OnReportDeadBody()
|
||||
{
|
||||
if (Fresh.GetBool() || RedPlayer == null || !RedPlayer.Any())
|
||||
if (Fresh.GetBool() || RedPlayer == null || RedPlayer.Count == 0)
|
||||
GetRedName();
|
||||
}
|
||||
public static void GetRedName()
|
||||
@@ -96,14 +96,14 @@ public static class Psychic
|
||||
if (ENum < 1) goto EndOfSelect;
|
||||
|
||||
RedPlayer = [];
|
||||
for (int i = 0; i < ENum && BadList.Any(); i++)
|
||||
for (int i = 0; i < ENum && BadList.Count > 0; i++)
|
||||
{
|
||||
RedPlayer.Add(BadList[IRandom.Instance.Next(0, BadList.Count)]);
|
||||
BadList.RemoveAll(RedPlayer.Contains);
|
||||
}
|
||||
|
||||
AllList.RemoveAll(RedPlayer.Contains);
|
||||
for (int i = 0; i < BNum && AllList.Any(); i++)
|
||||
for (int i = 0; i < BNum && AllList.Count > 0; i++)
|
||||
{
|
||||
RedPlayer.Add(AllList[IRandom.Instance.Next(0, AllList.Count)]);
|
||||
AllList.RemoveAll(RedPlayer.Contains);
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace TOHE.Roles.Crewmate
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
SetupSingleRoleOptions(Id, TabGroup.CrewmateRoles, CustomRoles.Sentinel, 1);
|
||||
SetupRoleOptions(Id, TabGroup.CrewmateRoles, CustomRoles.Sentinel);
|
||||
PatrolCooldown = CreateCDSetting(Id + 2, TabGroup.CrewmateRoles, CustomRoles.Sentinel);
|
||||
PatrolDuration = IntegerOptionItem.Create(Id + 3, "SentinelPatrolDuration", new(1, 90, 1), 5, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Sentinel])
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace TOHE.Roles.Crewmate
|
||||
{
|
||||
if (pc == null) return;
|
||||
if (!pc.Is(CustomRoles.Spy)) return;
|
||||
if (!SpyRedNameList.Any()) return;
|
||||
if (SpyRedNameList.Count == 0) return;
|
||||
|
||||
bool change = false;
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace TOHE.Roles.Crewmate
|
||||
}
|
||||
public static void OnFixedUpdate(PlayerControl tornadoPc)
|
||||
{
|
||||
if (!IsEnable || !GameStates.IsInTask || !Tornados.Any()) return;
|
||||
if (!IsEnable || !GameStates.IsInTask || Tornados.Count == 0) return;
|
||||
|
||||
var Random = IRandom.Instance;
|
||||
var NotifyString = GetString("TeleportedByTornado");
|
||||
|
||||
@@ -108,9 +108,9 @@ namespace TOHE.Roles.Impostor
|
||||
notify = true;
|
||||
}
|
||||
|
||||
if ((notify || chargePercent == 100) && !pc.IsModClient())
|
||||
if (notify && !pc.IsModClient())
|
||||
{
|
||||
pc.Notify(string.Format(Translator.GetString("ChronomancerPercent"), chargePercent));
|
||||
pc.Notify(string.Format(Translator.GetString("ChronomancerPercent"), chargePercent), 300f);
|
||||
}
|
||||
|
||||
if (beforeCharge != chargePercent && pc.IsModClient() && pc.PlayerId != 0)
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace TOHE.Roles.Impostor
|
||||
public static void OnFixedUpdate()
|
||||
{
|
||||
if (!IsEnable) return;
|
||||
if (!DuelPair.Any()) return;
|
||||
if (DuelPair.Count == 0) return;
|
||||
foreach (var pair in DuelPair)
|
||||
{
|
||||
var duellist = GetPlayerById(pair.Key);
|
||||
|
||||
@@ -196,7 +196,7 @@ public static class EvilTracker
|
||||
ImpostorsId[trackerId].RemoveWhere(id => Main.PlayerStates[id].IsDead);
|
||||
|
||||
var sb = new StringBuilder(80);
|
||||
if (ImpostorsId[trackerId].Any())
|
||||
if (ImpostorsId[trackerId].Count > 0)
|
||||
{
|
||||
sb.Append($"<color={Utils.GetRoleColorCode(CustomRoles.Impostor)}>");
|
||||
foreach (var impostorId in ImpostorsId[trackerId])
|
||||
|
||||
@@ -218,10 +218,7 @@ namespace TOHE.Roles.Impostor
|
||||
|
||||
public static void OnFixedUpdate(PlayerControl player)
|
||||
{
|
||||
if (!GameStates.IsInTask) return;
|
||||
if (player == null) return;
|
||||
if (!player.Is(CustomRoles.Gambler)) return;
|
||||
if (!waitingDelayedKills.Any() && !isSpeedChange.Any() && !isVisionChange.Any() && !isShielded.Any()) return;
|
||||
if (!GameStates.IsInTask || player == null || !player.Is(CustomRoles.Gambler) || (waitingDelayedKills.Count == 0 && isSpeedChange.Count == 0 && isVisionChange.Count == 0 && isShielded.Count == 0)) return;
|
||||
|
||||
bool sync = false;
|
||||
|
||||
|
||||
@@ -151,7 +151,6 @@ namespace TOHE.Roles.Impostor
|
||||
{
|
||||
NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
||||
SendRPCSyncPistolCD();
|
||||
Logger.Info($"Pistol 1 CD: {Pistol1CD}; Pistol 2 CD: {Pistol2CD}", "debug");
|
||||
}
|
||||
}
|
||||
public static bool OnCheckMurder(PlayerControl killer, PlayerControl target)
|
||||
|
||||
@@ -70,9 +70,7 @@ namespace TOHE.Roles.Impostor
|
||||
|
||||
public static void OnFixedUpdate()
|
||||
{
|
||||
if (!IsEnable) return;
|
||||
if (GameStates.IsMeeting) return;
|
||||
if (!ManipulatedPlayers.Any() && !ManipulateDelays.Any()) return;
|
||||
if (!IsEnable || GameStates.IsMeeting || ManipulatedPlayers.Count == 0 && ManipulateDelays.Count == 0) return;
|
||||
|
||||
foreach (var x in ManipulateDelays)
|
||||
{
|
||||
|
||||
@@ -62,11 +62,7 @@ namespace TOHE.Roles.Impostor
|
||||
|
||||
public static void OnFixedUpdate(PlayerControl pc)
|
||||
{
|
||||
if (pc == null) return;
|
||||
if (!Bombs.Any()) return;
|
||||
if (!GameStates.IsInTask) return;
|
||||
if (!pc.IsAlive()) return;
|
||||
if (!pc.Is(CustomRoles.Sapper)) return;
|
||||
if (pc == null || Bombs.Count == 0 || !GameStates.IsInTask || !pc.IsAlive() || !pc.Is(CustomRoles.Sapper)) return;
|
||||
|
||||
foreach (var bomb in Bombs.Where(bomb => bomb.Value + Delay.GetInt() < GetTimeStamp()))
|
||||
{
|
||||
|
||||
@@ -222,7 +222,7 @@ public static class Sniper
|
||||
|
||||
var targets = GetSnipeTargets(sniper);
|
||||
|
||||
if (targets.Any())
|
||||
if (targets.Count > 0)
|
||||
{
|
||||
//一番正確な対象がターゲット
|
||||
var snipedTarget = targets.OrderBy(c => c.Value).First().Key;
|
||||
@@ -313,7 +313,7 @@ public static class Sniper
|
||||
//エイムアシスト中のスナイパー
|
||||
if (0.5f < AimTime[seerId] && (!AimAssistOneshot || AimTime[seerId] < 1.0f))
|
||||
{
|
||||
if (GetSnipeTargets(Utils.GetPlayerById(seerId)).Any())
|
||||
if (GetSnipeTargets(Utils.GetPlayerById(seerId)).Count > 0)
|
||||
{
|
||||
return $"<size=200%>{Utils.ColorString(Palette.ImpostorRed, "◎")}</size>";
|
||||
}
|
||||
|
||||
@@ -40,8 +40,6 @@ public static class Wildling
|
||||
{
|
||||
playerIdList.Add(playerId);
|
||||
TimeStamp.TryAdd(playerId, 0);
|
||||
|
||||
|
||||
}
|
||||
public static bool IsEnable => playerIdList.Count > 0;
|
||||
private static void SendRPC(byte playerId)
|
||||
@@ -91,12 +89,4 @@ public static class Wildling
|
||||
}
|
||||
return str.ToString();
|
||||
}
|
||||
|
||||
public static void CanUseVent(PlayerControl player)
|
||||
{
|
||||
bool canUse = CanVent.GetBool();
|
||||
DestroyableSingleton<HudManager>.Instance.ImpostorVentButton.ToggleVisible(canUse && !player.Data.IsDead);
|
||||
player.Data.Role.CanVent = canUse;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -37,11 +37,11 @@
|
||||
// }
|
||||
// public static bool IsEnable()
|
||||
// {
|
||||
// return playerIdList.Any();
|
||||
// return playerIdList.Count > 0;
|
||||
// }
|
||||
// public static bool IsNEnable()
|
||||
// {
|
||||
// return NplayerIdList.Any();
|
||||
// return NplayerIdList.Count > 0;
|
||||
// }
|
||||
// public static bool IsNAlive()
|
||||
// {
|
||||
|
||||
@@ -93,11 +93,4 @@ public static class BloodKnight
|
||||
|
||||
public static void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
|
||||
public static void ApplyGameOptions(IGameOptions opt) => opt.SetVision(HasImpostorVision.GetBool());
|
||||
public static void CanUseVent(PlayerControl player)
|
||||
{
|
||||
bool canUse = CanVent.GetBool();
|
||||
DestroyableSingleton<HudManager>.Instance.ImpostorVentButton.ToggleVisible(canUse && !player.Data.IsDead);
|
||||
player.Data.Role.CanVent = canUse;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -69,7 +69,7 @@ namespace TOHE.Roles.Neutral
|
||||
}
|
||||
public static void OnFixedUpdate()
|
||||
{
|
||||
if (!IsEnable || !GameStates.IsInTask || !EncasedPlayers.Any()) return;
|
||||
if (!IsEnable || !GameStates.IsInTask || EncasedPlayers.Count == 0) return;
|
||||
|
||||
long now = GetTimeStamp();
|
||||
foreach (var id in EncasedPlayers.Where(item => item.Value + ExplodeDelay.GetInt() < now).Select(item => item.Key).ToArray())
|
||||
|
||||
@@ -23,7 +23,6 @@ public static class Gamer
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
//玩家只能有一人
|
||||
SetupSingleRoleOptions(Id, TabGroup.NeutralRoles, CustomRoles.Gamer, 1, zeroOne: false);
|
||||
KillCooldown = FloatOptionItem.Create(Id + 10, "GamerKillCooldown", new(1f, 180f, 1f), 2f, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Gamer])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
@@ -60,12 +59,6 @@ public static class Gamer
|
||||
public static bool IsEnable => playerIdList.Count > 0;
|
||||
public static void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
|
||||
public static void ApplyGameOptions(IGameOptions opt) => opt.SetVision(HasImpostorVision.GetBool());
|
||||
public static void CanUseVent(PlayerControl player)
|
||||
{
|
||||
bool gamer_canUse = CanVent.GetBool();
|
||||
DestroyableSingleton<HudManager>.Instance.ImpostorVentButton.ToggleVisible(gamer_canUse && !player.Data.IsDead);
|
||||
player.Data.Role.CanVent = gamer_canUse;
|
||||
}
|
||||
private static void SendRPC(byte playerId)
|
||||
{
|
||||
if (!IsEnable || !Utils.DoRPC) return;
|
||||
|
||||
@@ -201,8 +201,7 @@ public static class HexMaster
|
||||
foreach (PlayerControl pc in Main.AllAlivePlayerControls)
|
||||
{
|
||||
var dic = HexedPlayer.Where(x => x.Value.Contains(pc.PlayerId));
|
||||
if (!dic.Any())
|
||||
continue;
|
||||
if (!dic.Any()) continue;
|
||||
var whichId = dic.FirstOrDefault().Key;
|
||||
var hexmaster = Utils.GetPlayerById(whichId);
|
||||
if (hexmaster != null && hexmaster.IsAlive())
|
||||
|
||||
@@ -42,7 +42,6 @@ public static class Jackal
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
//Jackalは1人固定
|
||||
SetupSingleRoleOptions(Id, TabGroup.NeutralRoles, CustomRoles.Jackal, 1, zeroOne: false);
|
||||
KillCooldown = FloatOptionItem.Create(Id + 10, "KillCooldown", new(0f, 180f, 2.5f), 22.5f, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Jackal])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
@@ -117,12 +116,6 @@ public static class Jackal
|
||||
HudManager.Instance.KillButton.OverrideText($"{GetString("KillButtonText")}");
|
||||
}
|
||||
public static void ApplyGameOptions(IGameOptions opt) => opt.SetVision(HasImpostorVision.GetBool());
|
||||
public static void CanUseVent(PlayerControl player)
|
||||
{
|
||||
bool jackal_canUse = CanVent.GetBool();
|
||||
DestroyableSingleton<HudManager>.Instance.ImpostorVentButton.ToggleVisible(jackal_canUse && !player.Data.IsDead);
|
||||
player.Data.Role.CanVent = jackal_canUse;
|
||||
}
|
||||
public static void SetHudActive(HudManager __instance, bool isActive)
|
||||
{
|
||||
__instance.SabotageButton.ToggleVisible(isActive && CanUseSabotage.GetBool());
|
||||
|
||||
@@ -17,7 +17,6 @@ public static class Jinx
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
//Jinxは1人固定
|
||||
SetupSingleRoleOptions(Id, TabGroup.NeutralRoles, CustomRoles.Jinx, 1, zeroOne: false);
|
||||
KillCooldown = FloatOptionItem.Create(Id + 10, "KillCooldown", new(0f, 180f, 2.5f), 22.5f, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Jinx])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
@@ -43,10 +42,4 @@ public static class Jinx
|
||||
public static bool IsEnable => playerIdList.Count > 0;
|
||||
public static void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
|
||||
public static void ApplyGameOptions(IGameOptions opt) => opt.SetVision(HasImpostorVision.GetBool());
|
||||
public static void CanUseVent(PlayerControl player)
|
||||
{
|
||||
bool Jinx_canUse = CanVent.GetBool();
|
||||
DestroyableSingleton<HudManager>.Instance.ImpostorVentButton.ToggleVisible(Jinx_canUse && !player.Data.IsDead);
|
||||
player.Data.Role.CanVent = Jinx_canUse;
|
||||
}
|
||||
}
|
||||
@@ -124,7 +124,7 @@ public static class Magician
|
||||
switch (CardId)
|
||||
{
|
||||
case 1: // Slowness for everyone nearby
|
||||
if (TempSpeeds.Any()) RevertSpeedChanges(true);
|
||||
if (TempSpeeds.Count > 0) RevertSpeedChanges(true);
|
||||
var list = GetPlayersInRadius(SlownessRadius.GetFloat(), pc.Pos());
|
||||
foreach (var x in list)
|
||||
{
|
||||
@@ -170,7 +170,7 @@ public static class Magician
|
||||
|
||||
var targets = GetSnipeTargets(sniper);
|
||||
|
||||
if (targets.Any())
|
||||
if (targets.Count > 0)
|
||||
{
|
||||
var snipedTarget = targets.OrderBy(c => c.Value).First().Key;
|
||||
snipedTarget.CheckMurder(snipedTarget);
|
||||
@@ -247,7 +247,7 @@ public static class Magician
|
||||
if (!GameStates.IsInTask) return;
|
||||
if (Pelican.IsEaten(pc.PlayerId) || pc.Data.IsDead) return;
|
||||
|
||||
if (TempSpeeds.Any()) RevertSpeedChanges(false);
|
||||
if (TempSpeeds.Count > 0) RevertSpeedChanges(false);
|
||||
|
||||
if (PortalMarks.Count == 2 && lastTP + 5 < GetTimeStamp())
|
||||
{
|
||||
@@ -291,7 +291,7 @@ public static class Magician
|
||||
}
|
||||
}
|
||||
|
||||
if (BlindPPL.Any())
|
||||
if (BlindPPL.Count > 0)
|
||||
{
|
||||
foreach (var x in BlindPPL.Where(x => x.Value + BlindDur.GetInt() < GetTimeStamp()))
|
||||
{
|
||||
@@ -300,7 +300,7 @@ public static class Magician
|
||||
}
|
||||
}
|
||||
|
||||
if (Bombs.Any())
|
||||
if (Bombs.Count > 0)
|
||||
{
|
||||
foreach (var bomb in Bombs.Where(bomb => bomb.Value + BombDelay.GetInt() < GetTimeStamp()))
|
||||
{
|
||||
|
||||
+16
-14
@@ -7,40 +7,42 @@ namespace TOHE.Roles.Neutral;
|
||||
public static class Maverick
|
||||
{
|
||||
private static readonly int Id = 10000;
|
||||
public static List<byte> playerIdList = [];
|
||||
public static byte MaverickId = byte.MaxValue;
|
||||
public static int NumOfKills = 0;
|
||||
|
||||
private static OptionItem KillCooldown;
|
||||
public static OptionItem CanVent;
|
||||
private static OptionItem HasImpostorVision;
|
||||
public static OptionItem MinKillsToWin;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
//Maverickは1人固定
|
||||
SetupSingleRoleOptions(Id, TabGroup.NeutralRoles, CustomRoles.Maverick, 1, zeroOne: false);
|
||||
KillCooldown = FloatOptionItem.Create(Id + 10, "KillCooldown", new(0f, 180f, 2.5f), 35f, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Maverick])
|
||||
KillCooldown = FloatOptionItem.Create(Id + 10, "KillCooldown", new(0f, 180f, 2.5f), 35f, TabGroup.NeutralRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Maverick])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
CanVent = BooleanOptionItem.Create(Id + 11, "CanVent", true, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Maverick]);
|
||||
HasImpostorVision = BooleanOptionItem.Create(Id + 13, "ImpostorVision", true, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Maverick]);
|
||||
CanVent = BooleanOptionItem.Create(Id + 11, "CanVent", true, TabGroup.NeutralRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Maverick]);
|
||||
HasImpostorVision = BooleanOptionItem.Create(Id + 13, "ImpostorVision", true, TabGroup.NeutralRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Maverick]);
|
||||
MinKillsToWin = IntegerOptionItem.Create(Id + 12, "DQNumOfKillsNeeded", new(0, 14, 1), 2, TabGroup.NeutralRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Maverick]);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
playerIdList = [];
|
||||
MaverickId = byte.MaxValue;
|
||||
NumOfKills = 0;
|
||||
}
|
||||
public static void Add(byte playerId)
|
||||
{
|
||||
playerIdList.Add(playerId);
|
||||
MaverickId = playerId;
|
||||
NumOfKills = 0;
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
public static bool IsEnable => playerIdList.Count > 0;
|
||||
public static bool IsEnable => MaverickId != byte.MaxValue;
|
||||
public static void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
|
||||
public static void ApplyGameOptions(IGameOptions opt) => opt.SetVision(HasImpostorVision.GetBool());
|
||||
public static void CanUseVent(PlayerControl player)
|
||||
{
|
||||
bool Maverick_canUse = CanVent.GetBool();
|
||||
DestroyableSingleton<HudManager>.Instance.ImpostorVentButton.ToggleVisible(Maverick_canUse && !player.Data.IsDead);
|
||||
player.Data.Role.CanVent = Maverick_canUse;
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@ public static class Medusa
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
//Medusaは1人固定
|
||||
SetupSingleRoleOptions(Id, TabGroup.NeutralRoles, CustomRoles.Medusa, 1, zeroOne: false);
|
||||
KillCooldown = FloatOptionItem.Create(Id + 10, "KillCooldown", new(0f, 180f, 2.5f), 30f, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Medusa])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
@@ -40,10 +39,4 @@ public static class Medusa
|
||||
public static bool IsEnable => playerIdList.Count > 0;
|
||||
public static void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
|
||||
public static void ApplyGameOptions(IGameOptions opt) => opt.SetVision(HasImpostorVision.GetBool());
|
||||
public static void CanUseVent(PlayerControl player)
|
||||
{
|
||||
bool Medusa_canUse = CanVent.GetBool();
|
||||
DestroyableSingleton<HudManager>.Instance.ImpostorVentButton.ToggleVisible(Medusa_canUse && !player.Data.IsDead);
|
||||
player.Data.Role.CanVent = Medusa_canUse;
|
||||
}
|
||||
}
|
||||
@@ -177,7 +177,7 @@ public static class Pelican
|
||||
{
|
||||
if (!GameStates.IsInTask)
|
||||
{
|
||||
if (eatenList.Any())
|
||||
if (eatenList.Count > 0)
|
||||
{
|
||||
eatenList.Clear();
|
||||
SyncEatenList(byte.MaxValue);
|
||||
|
||||
@@ -16,7 +16,6 @@ public static class Pickpocket
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
//Pickpocketは1人固定
|
||||
SetupSingleRoleOptions(Id, TabGroup.NeutralRoles, CustomRoles.Pickpocket, 1, zeroOne: false);
|
||||
KillCooldown = FloatOptionItem.Create(Id + 10, "KillCooldown", new(0f, 180f, 2.5f), 22.5f, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Pickpocket])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
@@ -40,10 +39,4 @@ public static class Pickpocket
|
||||
public static bool IsEnable => playerIdList.Count > 0;
|
||||
public static void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
|
||||
public static void ApplyGameOptions(IGameOptions opt) => opt.SetVision(HasImpostorVision.GetBool());
|
||||
public static void CanUseVent(PlayerControl player)
|
||||
{
|
||||
bool Pickpocket_canUse = CanVent.GetBool();
|
||||
DestroyableSingleton<HudManager>.Instance.ImpostorVentButton.ToggleVisible(Pickpocket_canUse && !player.Data.IsDead);
|
||||
player.Data.Role.CanVent = Pickpocket_canUse;
|
||||
}
|
||||
}
|
||||
@@ -256,7 +256,7 @@ namespace TOHE.Roles.Neutral
|
||||
}
|
||||
public static void DirectInfect(PlayerControl player)
|
||||
{
|
||||
if (!playerIdList.Any() || player == null) return;
|
||||
if (playerIdList.Count == 0 || player == null) return;
|
||||
Logger.Info($"InfectRate [{player.GetNameWithRole()}]: 100%", "PlagueDoctor");
|
||||
InfectInfos[player.PlayerId] = 100;
|
||||
SendRPC(player.PlayerId, 100);
|
||||
|
||||
@@ -124,12 +124,6 @@ namespace TOHE.Roles.Neutral
|
||||
return IsWatch;
|
||||
}
|
||||
public static void ApplyGameOptions(IGameOptions opt) => opt.SetVision(HasImpostorVision.GetBool());
|
||||
public static void CanUseVent(PlayerControl player)
|
||||
{
|
||||
bool canUse = CanVent.GetBool();
|
||||
DestroyableSingleton<HudManager>.Instance.ImpostorVentButton.ToggleVisible(canUse && !player.Data.IsDead);
|
||||
player.Data.Role.CanVent = canUse;
|
||||
}
|
||||
|
||||
public static string GetRitualCount(byte playerId) => Utils.ColorString(RitualCount[playerId] > 0 ? Utils.GetRoleColor(CustomRoles.Ritualist).ShadeColor(0.25f) : Color.gray, RitualCount.TryGetValue(playerId, out var shotLimit) ? $"({shotLimit})" : "Invalid");
|
||||
}
|
||||
|
||||
@@ -26,11 +26,4 @@ public static class Sidekick
|
||||
{
|
||||
__instance.SabotageButton.ToggleVisible(isActive && Jackal.CanUseSabotageSK.GetBool());
|
||||
}
|
||||
|
||||
public static void CanUseVent(PlayerControl player)
|
||||
{
|
||||
bool Sidekick_canUse = Jackal.CanVentSK.GetBool();
|
||||
DestroyableSingleton<HudManager>.Instance.ImpostorVentButton.ToggleVisible(Sidekick_canUse && !player.Data.IsDead);
|
||||
player.Data.Role.CanVent = Sidekick_canUse;
|
||||
}
|
||||
}
|
||||
@@ -104,7 +104,7 @@ namespace TOHE.Roles.Neutral
|
||||
}
|
||||
public static void OnFixedUpdate()
|
||||
{
|
||||
if (!IsEnable || !GameStates.IsInTask || !Traps.Any()) return;
|
||||
if (!IsEnable || !GameStates.IsInTask || Traps.Count == 0) return;
|
||||
|
||||
long now = GetTimeStamp();
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ public static class Traitor
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
//Traitorは1人固定
|
||||
SetupSingleRoleOptions(Id, TabGroup.NeutralRoles, CustomRoles.Traitor, 1, zeroOne: false);
|
||||
KillCooldown = FloatOptionItem.Create(Id + 10, "KillCooldown", new(0f, 180f, 2.5f), 22.5f, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Traitor])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
@@ -44,10 +43,4 @@ public static class Traitor
|
||||
public static bool IsEnable => playerIdList.Count > 0;
|
||||
public static void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
|
||||
public static void ApplyGameOptions(IGameOptions opt) => opt.SetVision(HasImpostorVision.GetBool());
|
||||
public static void CanUseVent(PlayerControl player)
|
||||
{
|
||||
bool Traitor_canUse = CanVent.GetBool();
|
||||
DestroyableSingleton<HudManager>.Instance.ImpostorVentButton.ToggleVisible(Traitor_canUse && !player.Data.IsDead);
|
||||
player.Data.Role.CanVent = Traitor_canUse;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -34,7 +34,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2023.11.28" PrivateAssets="all" />
|
||||
<PackageReference Include="BepInEx.IL2CPP.MSBuild" Version="2.1.0-rc.1" />
|
||||
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.679" Private="false" ExcludeAssets="runtime;native" />
|
||||
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.682" Private="false" ExcludeAssets="runtime;native" />
|
||||
<PackageReference Include="Samboy063.Cpp2IL.Core" Version="2022.1.0-development.898" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -33,8 +33,8 @@ public class Main : BasePlugin
|
||||
public static ConfigEntry<string> DebugKeyInput { get; private set; }
|
||||
public static readonly string MainMenuText = " ";
|
||||
public const string PluginGuid = "com.gurge44.toheplus";
|
||||
public const string PluginVersion = "2.1.0";
|
||||
public const string PluginDisplayVersion = "2.1.0";
|
||||
public const string PluginVersion = "2.1.2";
|
||||
public const string PluginDisplayVersion = "2.1.2";
|
||||
public static readonly string SupportedAUVersion = "2023.10.24";
|
||||
public const int PluginCreate = 3;
|
||||
public const bool Canary = false;
|
||||
@@ -66,6 +66,7 @@ public class Main : BasePlugin
|
||||
public static ConfigEntry<bool> SwitchVanilla { get; private set; }
|
||||
public static ConfigEntry<bool> VersionCheat { get; private set; }
|
||||
public static ConfigEntry<bool> GodMode { get; private set; }
|
||||
public static ConfigEntry<bool> DarkTheme { get; private set; }
|
||||
|
||||
public static Dictionary<byte, PlayerVersion> playerVersion = [];
|
||||
//Preset Name Options
|
||||
@@ -264,6 +265,7 @@ public class Main : BasePlugin
|
||||
VersionCheat = Config.Bind("Client Options", "VersionCheat", false);
|
||||
GodMode = Config.Bind("Client Options", "GodMode", false);
|
||||
UseVersionProtocol = Config.Bind("Client Options", "UseVersionProtocol", true);
|
||||
DarkTheme = Config.Bind("Client Options", "DarkTheme", false);
|
||||
|
||||
Logger = BepInEx.Logging.Logger.CreateLogSource("TOHE");
|
||||
TOHE.Logger.Enable();
|
||||
@@ -344,6 +346,7 @@ public class Main : BasePlugin
|
||||
{CustomRoles.Express, "#00ffff"},
|
||||
{CustomRoles.NiceEraser, "#00a5ff"},
|
||||
{CustomRoles.TaskManager, "#00ffa5"},
|
||||
{CustomRoles.Shiftguard, "#eb34cc"},
|
||||
{CustomRoles.Mole, "#00ff80"},
|
||||
{CustomRoles.Sentinel, "#4bc8d6"},
|
||||
{CustomRoles.Electric, "#fbff00"},
|
||||
@@ -743,6 +746,7 @@ public enum CustomRoles
|
||||
Express,
|
||||
NiceEraser,
|
||||
TaskManager,
|
||||
Shiftguard,
|
||||
Mole,
|
||||
Sentinel,
|
||||
Electric,
|
||||
|
||||
Reference in new issue
Block a user