mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-25 02:46:56 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
730ea9afeb | ||
|
|
dde672ecfc | ||
|
|
badbc4e59a | ||
|
|
fe2e2b29af | ||
|
|
f2ccc0b5c7 | ||
|
|
9a4d085d88 | ||
|
|
a58997385c | ||
|
|
5062355a37 | ||
|
|
4f946a8f08 | ||
|
|
0a23a35bfb | ||
|
|
3a46be462a | ||
|
|
970281d3b1 | ||
|
|
087fe9288d | ||
|
|
817c786c2f | ||
|
|
ab3b2e517d | ||
|
|
16170126da | ||
|
|
cb8b161cac | ||
|
|
b1ef23682e |
No files matched your search
@@ -35,6 +35,7 @@ internal static class FFAManager
|
||||
public static OptionItem FFA_EnableRandomAbilities;
|
||||
public static OptionItem FFA_EnableRandomTwists;
|
||||
public static OptionItem FFA_ShieldIsOneTimeUse;
|
||||
public static OptionItem FFA_ChatDuringGame;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
@@ -80,6 +81,9 @@ internal static class FFAManager
|
||||
FFA_ShieldIsOneTimeUse = BooleanOptionItem.Create(67_223_013, "FFA_ShieldIsOneTimeUse", true, TabGroup.GameSettings, false)
|
||||
.SetGameMode(CustomGameMode.FFA)
|
||||
.SetColor(new Color32(0, 255, 165, byte.MaxValue));
|
||||
FFA_ChatDuringGame = BooleanOptionItem.Create(67_223_014, "FFA_ChatDuringGame", false, TabGroup.GameSettings, false)
|
||||
.SetGameMode(CustomGameMode.FFA)
|
||||
.SetColor(new Color32(0, 255, 165, byte.MaxValue));
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
@@ -97,10 +101,10 @@ internal static class FFAManager
|
||||
|
||||
foreach (PlayerControl pc in Main.AllAlivePlayerControls)
|
||||
{
|
||||
KillCount.TryAdd(pc.PlayerId, 0);
|
||||
KillCount[pc.PlayerId] = 0;
|
||||
}
|
||||
|
||||
_ = new LateTask(Utils.SetChatVisible, 7f, "Set Chat Visible for Everyone");
|
||||
if (FFA_ChatDuringGame.GetBool()) _ = new LateTask(Utils.SetChatVisible, 7f, "Set Chat Visible for Everyone");
|
||||
}
|
||||
private static void SendRPCSyncFFAPlayer(byte playerId)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
+104
-130
@@ -10,11 +10,12 @@ internal static class CustomRolesHelper
|
||||
{
|
||||
public static CustomRoles GetVNRole(this CustomRoles role)
|
||||
{
|
||||
bool UsePets = Options.UsePets.GetBool();
|
||||
return role.IsVanilla()
|
||||
? role
|
||||
: role switch
|
||||
{
|
||||
CustomRoles.Sniper => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Sniper => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Jester => Options.JesterCanVent.GetBool() ? CustomRoles.Engineer : CustomRoles.Crewmate,
|
||||
CustomRoles.Mayor => Options.MayorHasPortableButton.GetBool() ? CustomRoles.Engineer : CustomRoles.Crewmate,
|
||||
CustomRoles.Monitor => Monitor.CanVent.GetBool() ? CustomRoles.Engineer : CustomRoles.Crewmate,
|
||||
@@ -44,7 +45,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.EvilDiviner => CustomRoles.Impostor,
|
||||
CustomRoles.Wildling => Wildling.CanShapeshift.GetBool() ? CustomRoles.Shapeshifter : CustomRoles.Impostor,
|
||||
CustomRoles.Morphling => CustomRoles.Shapeshifter,
|
||||
CustomRoles.Warlock => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Warlock => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.SerialKiller => CustomRoles.Impostor,
|
||||
CustomRoles.FireWorks => CustomRoles.Shapeshifter,
|
||||
CustomRoles.SpeedBooster => CustomRoles.Crewmate,
|
||||
@@ -60,9 +61,9 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Nullifier => CustomRoles.Impostor,
|
||||
CustomRoles.Stealth => CustomRoles.Impostor,
|
||||
CustomRoles.Penguin => CustomRoles.Shapeshifter,
|
||||
CustomRoles.Sapper => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Sapper => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Mastermind => CustomRoles.Impostor,
|
||||
CustomRoles.RiftMaker => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.RiftMaker => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Gambler => CustomRoles.Impostor,
|
||||
CustomRoles.Hitman => CustomRoles.Shapeshifter,
|
||||
CustomRoles.Saboteur => CustomRoles.Impostor,
|
||||
@@ -77,15 +78,15 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.TimeMaster => CustomRoles.Engineer,
|
||||
CustomRoles.CrewmateTOHE => CustomRoles.Crewmate,
|
||||
CustomRoles.Cleanser => CustomRoles.Crewmate,
|
||||
CustomRoles.Miner => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Miner => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Psychic => CustomRoles.Crewmate,
|
||||
CustomRoles.Needy => CustomRoles.Crewmate,
|
||||
CustomRoles.Twister => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Twister => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.SuperStar => CustomRoles.Crewmate,
|
||||
CustomRoles.Hacker => CustomRoles.Shapeshifter,
|
||||
CustomRoles.Visionary => CustomRoles.Impostor,
|
||||
CustomRoles.Assassin => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Undertaker => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Assassin => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Undertaker => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Luckey => CustomRoles.Crewmate,
|
||||
CustomRoles.CyberStar => CustomRoles.Crewmate,
|
||||
CustomRoles.Demolitionist => CustomRoles.Crewmate,
|
||||
@@ -95,11 +96,11 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.TaskManager => CustomRoles.Crewmate,
|
||||
CustomRoles.Shiftguard => CustomRoles.Crewmate,
|
||||
CustomRoles.Mole => CustomRoles.Engineer,
|
||||
CustomRoles.Sentinel => Options.UsePets.GetBool() ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Sentinel => UsePets ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Electric => CustomRoles.Crewmate,
|
||||
CustomRoles.Philantropist => CustomRoles.Crewmate,
|
||||
CustomRoles.Tornado => CustomRoles.Crewmate,
|
||||
CustomRoles.Druid => Options.UsePets.GetBool() ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Druid => UsePets ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Insight => CustomRoles.Crewmate,
|
||||
CustomRoles.Tunneler => CustomRoles.Crewmate,
|
||||
CustomRoles.Detour => CustomRoles.Crewmate,
|
||||
@@ -110,17 +111,17 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Transmitter => CustomRoles.Crewmate,
|
||||
CustomRoles.Autocrat => CustomRoles.Crewmate,
|
||||
CustomRoles.Nightmare => CustomRoles.Crewmate,
|
||||
CustomRoles.CameraMan => Options.UsePets.GetBool() ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.CameraMan => UsePets ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Spy => CustomRoles.Crewmate,
|
||||
CustomRoles.Ricochet => CustomRoles.Crewmate,
|
||||
CustomRoles.Tether => Options.UsePets.GetBool() ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Doormaster => Options.UsePets.GetBool() ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Aid => CustomRoles.Impostor,
|
||||
CustomRoles.Escort => CustomRoles.Impostor,
|
||||
CustomRoles.DonutDelivery => CustomRoles.Impostor,
|
||||
CustomRoles.Gaulois => CustomRoles.Impostor,
|
||||
CustomRoles.Analyzer => CustomRoles.Impostor,
|
||||
CustomRoles.Escapee => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Tether => UsePets ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Doormaster => UsePets ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Aid => UsePets && Aid.UsePet.GetBool() ? CustomRoles.Crewmate : CustomRoles.Impostor,
|
||||
CustomRoles.Escort => UsePets && Escort.UsePet.GetBool() ? CustomRoles.Crewmate : CustomRoles.Impostor,
|
||||
CustomRoles.DonutDelivery => UsePets && DonutDelivery.UsePet.GetBool() ? CustomRoles.Crewmate : CustomRoles.Impostor,
|
||||
CustomRoles.Gaulois => UsePets && Gaulois.UsePet.GetBool() ? CustomRoles.Crewmate : CustomRoles.Impostor,
|
||||
CustomRoles.Analyzer => UsePets && Analyzer.UsePet.GetBool() ? CustomRoles.Crewmate : CustomRoles.Impostor,
|
||||
CustomRoles.Escapee => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.NiceGuesser => CustomRoles.Crewmate,
|
||||
CustomRoles.EvilGuesser => CustomRoles.Impostor,
|
||||
CustomRoles.Detective => CustomRoles.Crewmate,
|
||||
@@ -130,8 +131,8 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Mario => CustomRoles.Engineer,
|
||||
CustomRoles.AntiAdminer => CustomRoles.Impostor,
|
||||
CustomRoles.Sans => CustomRoles.Impostor,
|
||||
CustomRoles.Bomber => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Nuker => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Bomber => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Nuker => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.BoobyTrap => CustomRoles.Impostor,
|
||||
CustomRoles.Scavenger => CustomRoles.Impostor,
|
||||
CustomRoles.Transporter => CustomRoles.Crewmate,
|
||||
@@ -153,7 +154,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.CursedWolf => CustomRoles.Impostor,
|
||||
CustomRoles.Collector => CustomRoles.Crewmate,
|
||||
CustomRoles.ImperiusCurse => CustomRoles.Shapeshifter,
|
||||
CustomRoles.QuickShooter => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.QuickShooter => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Eraser => CustomRoles.Impostor,
|
||||
CustomRoles.OverKiller => CustomRoles.Impostor,
|
||||
CustomRoles.Hangman => CustomRoles.Shapeshifter,
|
||||
@@ -168,7 +169,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Crewpostor => CustomRoles.Engineer,
|
||||
CustomRoles.Observer => CustomRoles.Crewmate,
|
||||
CustomRoles.DovesOfNeace => CustomRoles.Engineer,
|
||||
CustomRoles.Disperser => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Disperser => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Camouflager => CustomRoles.Shapeshifter,
|
||||
CustomRoles.Dazzler => CustomRoles.Shapeshifter,
|
||||
CustomRoles.Devourer => CustomRoles.Shapeshifter,
|
||||
@@ -285,6 +286,7 @@ internal static class CustomRolesHelper
|
||||
|
||||
public static RoleTypes GetDYRole(this CustomRoles role)
|
||||
{
|
||||
bool UsePets = Options.UsePets.GetBool();
|
||||
return role switch
|
||||
{
|
||||
//SoloKombat
|
||||
@@ -294,40 +296,40 @@ internal static class CustomRolesHelper
|
||||
//Move And Stop
|
||||
CustomRoles.Tasker => RoleTypes.Crewmate,
|
||||
//Standard
|
||||
CustomRoles.Sheriff => RoleTypes.Impostor,
|
||||
CustomRoles.Crusader => RoleTypes.Impostor,
|
||||
CustomRoles.CopyCat => RoleTypes.Impostor,
|
||||
CustomRoles.Sheriff => UsePets && Sheriff.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Crusader => UsePets && Crusader.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.CopyCat => UsePets && CopyCat.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
//CustomRoles.CursedSoul => RoleTypes.Impostor,
|
||||
CustomRoles.Admirer => RoleTypes.Impostor,
|
||||
CustomRoles.Admirer => UsePets && Gaulois.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Refugee => RoleTypes.Impostor,
|
||||
CustomRoles.Amnesiac => RoleTypes.Impostor,
|
||||
CustomRoles.Agitater => RoleTypes.Impostor,
|
||||
CustomRoles.Monarch => RoleTypes.Impostor,
|
||||
CustomRoles.Deputy => RoleTypes.Impostor,
|
||||
CustomRoles.Monarch => UsePets && Monarch.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Deputy => UsePets && Deputy.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Arsonist => RoleTypes.Impostor,
|
||||
CustomRoles.Jackal => RoleTypes.Impostor,
|
||||
CustomRoles.Medusa => RoleTypes.Impostor,
|
||||
CustomRoles.Sidekick => RoleTypes.Impostor,
|
||||
CustomRoles.SwordsMan => RoleTypes.Impostor,
|
||||
CustomRoles.SwordsMan => UsePets && SwordsMan.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
//CustomRoles.Reverie => RoleTypes.Impostor,
|
||||
CustomRoles.Innocent => RoleTypes.Impostor,
|
||||
CustomRoles.Pelican => RoleTypes.Impostor,
|
||||
//CustomRoles.Counterfeiter => RoleTypes.Impostor,
|
||||
CustomRoles.Aid => RoleTypes.Impostor,
|
||||
CustomRoles.Escort => RoleTypes.Impostor,
|
||||
CustomRoles.DonutDelivery => RoleTypes.Impostor,
|
||||
CustomRoles.Gaulois => RoleTypes.Impostor,
|
||||
CustomRoles.Analyzer => RoleTypes.Impostor,
|
||||
CustomRoles.Witness => RoleTypes.Impostor,
|
||||
CustomRoles.Aid => UsePets && Aid.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Escort => UsePets && Escort.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.DonutDelivery => UsePets && DonutDelivery.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Gaulois => UsePets && Gaulois.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Analyzer => UsePets && Analyzer.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Witness => UsePets && Options.WitnessUsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Pursuer => RoleTypes.Impostor,
|
||||
CustomRoles.Revolutionist => RoleTypes.Impostor,
|
||||
CustomRoles.FFF => RoleTypes.Impostor,
|
||||
CustomRoles.Medic => RoleTypes.Impostor,
|
||||
CustomRoles.Medic => UsePets && Medic.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Gamer => RoleTypes.Impostor,
|
||||
CustomRoles.HexMaster => RoleTypes.Impostor,
|
||||
CustomRoles.Wraith => RoleTypes.Impostor,
|
||||
CustomRoles.Glitch => RoleTypes.Impostor,
|
||||
CustomRoles.Jailor => RoleTypes.Impostor,
|
||||
CustomRoles.Jailor => UsePets && Jailor.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Juggernaut => RoleTypes.Impostor,
|
||||
CustomRoles.Jinx => RoleTypes.Impostor,
|
||||
CustomRoles.DarkHide => RoleTypes.Impostor,
|
||||
@@ -362,7 +364,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Succubus => RoleTypes.Impostor,
|
||||
CustomRoles.Infectious => RoleTypes.Impostor,
|
||||
CustomRoles.Virus => RoleTypes.Impostor,
|
||||
CustomRoles.Farseer => RoleTypes.Impostor,
|
||||
CustomRoles.Farseer => UsePets && Farseer.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Ritualist => RoleTypes.Impostor,
|
||||
CustomRoles.Pickpocket => RoleTypes.Impostor,
|
||||
CustomRoles.Traitor => RoleTypes.Impostor,
|
||||
@@ -1000,86 +1002,6 @@ internal static class CustomRolesHelper
|
||||
|
||||
}
|
||||
|
||||
public static bool IsNeutralWithGuessAccess(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
//SoloKombat
|
||||
CustomRoles.KB_Normal or
|
||||
//FFA
|
||||
CustomRoles.Killer or
|
||||
//Move And Stop
|
||||
CustomRoles.Tasker or
|
||||
//Standard
|
||||
CustomRoles.Jester or
|
||||
CustomRoles.Agitater or
|
||||
CustomRoles.Doppelganger or
|
||||
CustomRoles.Opportunist or
|
||||
CustomRoles.Bandit or
|
||||
CustomRoles.Mario or
|
||||
CustomRoles.HexMaster or
|
||||
CustomRoles.Crewpostor or
|
||||
//CustomRoles.NWitch or
|
||||
CustomRoles.Wraith or
|
||||
CustomRoles.Parasite or
|
||||
CustomRoles.Terrorist or
|
||||
CustomRoles.Executioner or
|
||||
CustomRoles.Medusa or
|
||||
CustomRoles.Juggernaut or
|
||||
CustomRoles.Vulture or
|
||||
CustomRoles.Jinx or
|
||||
CustomRoles.Lawyer or
|
||||
CustomRoles.Arsonist or
|
||||
CustomRoles.Jackal or
|
||||
CustomRoles.Sidekick or
|
||||
CustomRoles.God or
|
||||
CustomRoles.Innocent or
|
||||
CustomRoles.Pursuer or
|
||||
// CustomRoles.Sidekick or
|
||||
CustomRoles.Poisoner or
|
||||
CustomRoles.NSerialKiller or
|
||||
CustomRoles.Enderman or
|
||||
CustomRoles.Mycologist or
|
||||
CustomRoles.Bubble or
|
||||
CustomRoles.Hookshot or
|
||||
CustomRoles.Sprayer or
|
||||
CustomRoles.PlagueDoctor or
|
||||
CustomRoles.Magician or
|
||||
CustomRoles.WeaponMaster or
|
||||
CustomRoles.Reckless or
|
||||
CustomRoles.Postman or
|
||||
CustomRoles.Eclipse or
|
||||
CustomRoles.Pyromaniac or
|
||||
CustomRoles.Vengeance or
|
||||
CustomRoles.HeadHunter or
|
||||
CustomRoles.Imitator or
|
||||
CustomRoles.Werewolf or
|
||||
CustomRoles.Pelican or
|
||||
CustomRoles.Revolutionist or
|
||||
CustomRoles.FFF or
|
||||
CustomRoles.Traitor or
|
||||
CustomRoles.Konan or
|
||||
CustomRoles.Gamer or
|
||||
CustomRoles.DarkHide or
|
||||
CustomRoles.Infectious or
|
||||
CustomRoles.Workaholic or
|
||||
CustomRoles.Collector or
|
||||
CustomRoles.Provocateur or
|
||||
CustomRoles.Sunnyboy or
|
||||
CustomRoles.Phantom or
|
||||
CustomRoles.BloodKnight or
|
||||
CustomRoles.Romantic or
|
||||
CustomRoles.Totocalcio or
|
||||
CustomRoles.VengefulRomantic or
|
||||
CustomRoles.RuthlessRomantic or
|
||||
CustomRoles.Virus or
|
||||
CustomRoles.Succubus or
|
||||
CustomRoles.Spiritcaller or
|
||||
CustomRoles.Doomsayer or
|
||||
CustomRoles.PlagueBearer or
|
||||
//CustomRoles.Pirate or
|
||||
CustomRoles.Pestilence;
|
||||
}
|
||||
|
||||
public static bool IsEvilAddons(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
@@ -1104,8 +1026,9 @@ internal static class CustomRolesHelper
|
||||
}
|
||||
public static bool IsTasklessCrewmate(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
return !role.UsesPetInsteadOfKill() && role is
|
||||
CustomRoles.Sheriff or
|
||||
CustomRoles.Admirer or
|
||||
CustomRoles.Medic or
|
||||
CustomRoles.CopyCat or
|
||||
//CustomRoles.Reverie or
|
||||
@@ -1125,12 +1048,14 @@ internal static class CustomRolesHelper
|
||||
}
|
||||
public static bool PetActivatedAbility(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
return Options.UsePets.GetBool() && role switch
|
||||
{
|
||||
CustomRoles.Doormaster or
|
||||
CustomRoles.Tether or
|
||||
CustomRoles.Mayor or
|
||||
CustomRoles.Paranoia or
|
||||
CustomRoles.Grenadier or
|
||||
CustomRoles.Veteran or
|
||||
CustomRoles.Lighter or
|
||||
CustomRoles.SecurityGuard or
|
||||
CustomRoles.DovesOfNeace or
|
||||
@@ -1139,6 +1064,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
|
||||
@@ -1154,11 +1084,59 @@ 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
|
||||
=> true,
|
||||
|
||||
CustomRoles.Gaulois when Gaulois.UsePet.GetBool() => true,
|
||||
CustomRoles.Aid when Aid.UsePet.GetBool() => true,
|
||||
CustomRoles.Escort when Escort.UsePet.GetBool() => true,
|
||||
CustomRoles.DonutDelivery when DonutDelivery.UsePet.GetBool() => true,
|
||||
CustomRoles.Analyzer when Analyzer.UsePet.GetBool() => true,
|
||||
CustomRoles.Jailor when Jailor.UsePet.GetBool() => true,
|
||||
CustomRoles.Sheriff when Sheriff.UsePet.GetBool() => true,
|
||||
CustomRoles.SwordsMan when SwordsMan.UsePet.GetBool() => true,
|
||||
CustomRoles.Medic when Medic.UsePet.GetBool() => true,
|
||||
CustomRoles.Monarch when Monarch.UsePet.GetBool() => true,
|
||||
CustomRoles.CopyCat when CopyCat.UsePet.GetBool() => true,
|
||||
CustomRoles.Farseer when Farseer.UsePet.GetBool() => true,
|
||||
CustomRoles.Deputy when Deputy.UsePet.GetBool() => true,
|
||||
CustomRoles.Admirer when Admirer.UsePet.GetBool() => true,
|
||||
CustomRoles.Crusader when Crusader.UsePet.GetBool() => true,
|
||||
CustomRoles.Witness when Options.WitnessUsePet.GetBool() => true,
|
||||
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
public static bool UsesPetInsteadOfKill(this CustomRoles role)
|
||||
{
|
||||
return Options.UsePets.GetBool() && role switch
|
||||
{
|
||||
CustomRoles.Gaulois when Gaulois.UsePet.GetBool() => true,
|
||||
CustomRoles.Aid when Aid.UsePet.GetBool() => true,
|
||||
CustomRoles.Escort when Escort.UsePet.GetBool() => true,
|
||||
CustomRoles.DonutDelivery when DonutDelivery.UsePet.GetBool() => true,
|
||||
CustomRoles.Analyzer when Analyzer.UsePet.GetBool() => true,
|
||||
CustomRoles.Jailor when Jailor.UsePet.GetBool() => true,
|
||||
CustomRoles.Sheriff when Sheriff.UsePet.GetBool() => true,
|
||||
CustomRoles.SwordsMan when SwordsMan.UsePet.GetBool() => true,
|
||||
CustomRoles.Medic when Medic.UsePet.GetBool() => true,
|
||||
CustomRoles.Monarch when Monarch.UsePet.GetBool() => true,
|
||||
CustomRoles.CopyCat when CopyCat.UsePet.GetBool() => true,
|
||||
CustomRoles.Farseer when Farseer.UsePet.GetBool() => true,
|
||||
CustomRoles.Deputy when Deputy.UsePet.GetBool() => true,
|
||||
CustomRoles.Admirer when Admirer.UsePet.GetBool() => true,
|
||||
CustomRoles.Crusader when Crusader.UsePet.GetBool() => true,
|
||||
CustomRoles.Witness when Options.WitnessUsePet.GetBool() => true,
|
||||
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
public static bool NeedUpdateOnLights(this CustomRoles role)
|
||||
{
|
||||
return role.IsNK() || role is
|
||||
return (!role.UsesPetInsteadOfKill()) && (role.GetDYRole() != RoleTypes.GuardianAngel || role is
|
||||
CustomRoles.Sheriff or
|
||||
CustomRoles.Medic or
|
||||
CustomRoles.CopyCat or
|
||||
@@ -1242,7 +1220,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Mare or
|
||||
CustomRoles.Bandit or
|
||||
CustomRoles.Agitater or
|
||||
CustomRoles.Deputy;
|
||||
CustomRoles.Deputy);
|
||||
}
|
||||
|
||||
public static bool IsBetrayalAddon(this CustomRoles role)
|
||||
@@ -1296,11 +1274,7 @@ internal static class CustomRolesHelper
|
||||
}
|
||||
public static bool CheckAddonConflictV2(CustomRoles addon, CustomRoles mainRole)
|
||||
{
|
||||
if (!addon.IsAdditionRole()) return false;
|
||||
|
||||
if (mainRole is CustomRoles.GuardianAngelTOHE or CustomRoles.God) return false;
|
||||
if (mainRole is CustomRoles.GM || addon is CustomRoles.Lovers) return false;
|
||||
return addon switch
|
||||
return addon.IsAdditionRole() && mainRole is not CustomRoles.GuardianAngelTOHE and not CustomRoles.God and not CustomRoles.GM && addon is not CustomRoles.Lovers && addon switch
|
||||
{
|
||||
CustomRoles.Lovers when mainRole is CustomRoles.RuthlessRomantic or CustomRoles.Romantic or CustomRoles.VengefulRomantic => false,
|
||||
CustomRoles.Autopsy when mainRole is CustomRoles.Doctor or CustomRoles.Tracefinder or CustomRoles.Scientist or CustomRoles.ScientistTOHE or CustomRoles.Sunnyboy => false,
|
||||
@@ -1776,7 +1750,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
|
||||
{
|
||||
|
||||
+87
-69
@@ -1,5 +1,6 @@
|
||||
using AmongUs.GameOptions;
|
||||
using Hazel;
|
||||
using InnerNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -26,43 +27,43 @@ internal class EAC
|
||||
public static bool ReceiveRpc(PlayerControl pc, byte callId, MessageReader reader)
|
||||
{
|
||||
if (!AmongUsClient.Instance.AmHost) return false;
|
||||
if (pc == null || reader == null || pc.AmOwner) return false;
|
||||
if (pc == null || reader == null) return false;
|
||||
try
|
||||
{
|
||||
MessageReader sr = MessageReader.Get(reader);
|
||||
var rpc = (RpcCalls)callId;
|
||||
switch (rpc)
|
||||
{
|
||||
case RpcCalls.SetName:
|
||||
string name = sr.ReadString();
|
||||
if (sr.BytesRemaining > 0 && sr.ReadBoolean()) return false;
|
||||
if (
|
||||
((name.Contains("<size") || name.Contains("size>")) && name.Contains('?') && !name.Contains("color")) ||
|
||||
name.Length > 160 ||
|
||||
name.Count(f => f.Equals("\"\\n\"")) > 3 ||
|
||||
name.Count(f => f.Equals("\n")) > 3 ||
|
||||
name.Count(f => f.Equals("\r")) > 3 ||
|
||||
name.Contains('░') ||
|
||||
name.Contains('▄') ||
|
||||
name.Contains('█') ||
|
||||
name.Contains('▌') ||
|
||||
name.Contains('▒') ||
|
||||
name.Contains("习近平")
|
||||
)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "非法设置游戏名称");
|
||||
Logger.Fatal($"非法修改玩家【{pc.GetClientId()}:{pc.GetRealName()}】的游戏名称,已驳回", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
//case RpcCalls.SetName:
|
||||
// string name = sr.ReadString();
|
||||
// if (sr.BytesRemaining > 0 && sr.ReadBoolean()) return false;
|
||||
// if (
|
||||
// ((name.Contains("<size") || name.Contains("size>")) && name.Contains('?') && !name.Contains("color")) ||
|
||||
// name.Length > 160 ||
|
||||
// name.Count(f => f.Equals("\"\\n\"")) > 3 ||
|
||||
// name.Count(f => f.Equals("\n")) > 3 ||
|
||||
// name.Count(f => f.Equals("\r")) > 3 ||
|
||||
// name.Contains('░') ||
|
||||
// name.Contains('▄') ||
|
||||
// name.Contains('█') ||
|
||||
// name.Contains('▌') ||
|
||||
// name.Contains('▒') ||
|
||||
// name.Contains("Xi Jinping")
|
||||
// )
|
||||
// {
|
||||
// WarnHost();
|
||||
// Report(pc, "Illegal setting of game name");
|
||||
// Logger.Fatal($"Illegal modification of the game name of player [{pc.GetClientId()}:{pc.GetRealName()}] has been rejected", "EAC");
|
||||
// return true;
|
||||
// }
|
||||
// break;
|
||||
case RpcCalls.SetRole:
|
||||
var role = (RoleTypes)sr.ReadUInt16();
|
||||
if (GameStates.IsLobby && (role is RoleTypes.CrewmateGhost or RoleTypes.ImpostorGhost))
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "非法设置状态为幽灵");
|
||||
Logger.Fatal($"非法设置玩家【{pc.GetClientId()}:{pc.GetRealName()}】的状态为幽灵,已驳回", "EAC");
|
||||
Report(pc, "Illegal setting status to ghost");
|
||||
Logger.Fatal($"Illegal setting of the status of player [{pc.GetClientId()}:{pc.GetRealName()}] to ghost, has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -75,11 +76,11 @@ internal class EAC
|
||||
text.Contains('█') ||
|
||||
text.Contains('▌') ||
|
||||
text.Contains('▒') ||
|
||||
text.Contains("习近平")
|
||||
text.Contains("Xi Jinping")
|
||||
)
|
||||
{
|
||||
Report(pc, "非法消息");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】发送非法消息,已驳回", "EAC");
|
||||
Report(pc, "Illegal message");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] sent an illegal message, which has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -88,7 +89,7 @@ internal class EAC
|
||||
WarnHost();
|
||||
Report(pc, "Bad StartMeeting");
|
||||
HandleCheat(pc, "Bad StartMeeting");
|
||||
Logger.Fatal($"非法设置玩家【{pc.GetClientId()}:{pc.GetRealName()}】的游戏名称,已驳回", "EAC");
|
||||
Logger.Fatal($"Illegal setting of the game name of the player [{pc.GetClientId()}:{pc.GetRealName()}] has been rejected", "EAC");
|
||||
return true;
|
||||
case RpcCalls.ReportDeadBody:
|
||||
if (!GameStates.IsInGame)
|
||||
@@ -96,7 +97,7 @@ internal class EAC
|
||||
WarnHost();
|
||||
Report(pc, "Report body out of game A");
|
||||
HandleCheat(pc, "Report body out of game A");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】非游戏内开会,已驳回", "EAC");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] has a non-in-game meeting and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
if (ReportTimes.TryGetValue(pc.PlayerId, out int rtimes))
|
||||
@@ -106,7 +107,7 @@ internal class EAC
|
||||
WarnHost();
|
||||
Report(pc, "Spam report bodies A");
|
||||
HandleCheat(pc, "Spam report bodies A");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】刷报告尸体满14次,已驳回", "EAC");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] reported corpses 14 times and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -119,7 +120,7 @@ internal class EAC
|
||||
WarnHost();
|
||||
Report(pc, "Set color in game");
|
||||
HandleCheat(pc, "Set color in game");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】游戏内设置颜色,已驳回", "EAC");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] sets the color in the game and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
if (pc.Data.DefaultOutfit.ColorId != -1 &&
|
||||
@@ -127,9 +128,9 @@ internal class EAC
|
||||
|| color < 0 || color > 18))
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "非法设置颜色");
|
||||
Report(pc, "Illegal color setting");
|
||||
AmongUsClient.Instance.KickPlayer(pc.GetClientId(), false);
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】非法设置颜色,已驳回", "EAC");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally set the color and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -139,7 +140,7 @@ internal class EAC
|
||||
WarnHost();
|
||||
Report(pc, "CheckMurder in Lobby");
|
||||
HandleCheat(pc, "CheckMurder in Lobby");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】非法检查击杀,已驳回", "EAC");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally checked for kill and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -147,8 +148,25 @@ internal class EAC
|
||||
//If using version protocol, client should never directly send Murder player rpc
|
||||
Report(pc, "Directly Murder Player");
|
||||
HandleCheat(pc, "Directly Murder Player");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】直接击杀,已驳回", "EAC");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] killed directly, rejected", "EAC");
|
||||
return true;
|
||||
case RpcCalls.Shapeshift:
|
||||
if (GameStates.IsLobby)
|
||||
{
|
||||
Report(pc, "ShapeShift in lobby");
|
||||
HandleCheat(pc, "ShapeShift in lobby");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] lobby is deformed and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
var target = sr.ReadNetObject<PlayerControl>();
|
||||
if (target == null)
|
||||
{
|
||||
Report(pc, "ShapeShift to null player!");
|
||||
//HandleCheat(pc, "ShapeShift to null player!");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally transformed into an empty player and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
switch (callId)
|
||||
{
|
||||
@@ -162,8 +180,8 @@ internal class EAC
|
||||
if (!GameStates.IsLobby)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "非法设置颜色");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】非法设置颜色,已驳回", "EAC");
|
||||
Report(pc, "Illegal color setting");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally set the color and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -172,8 +190,8 @@ internal class EAC
|
||||
if (GameStates.IsInGame)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "非法设置游戏名称");
|
||||
Logger.Fatal($"非法修改玩家【{pc.GetClientId()}:{pc.GetRealName()}】的游戏名称,已驳回", "EAC");
|
||||
Report(pc, "Illegal setting of game name");
|
||||
Logger.Fatal($"Illegal modification of the game name of player [{pc.GetClientId()}:{pc.GetRealName()}] has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -181,8 +199,8 @@ internal class EAC
|
||||
if (GameStates.IsLobby)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "非法击杀");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】非法击杀,已驳回", "EAC");
|
||||
Report(pc, "illegal kill");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally killed and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -190,8 +208,8 @@ internal class EAC
|
||||
if (GameStates.IsInGame)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "非法设置宠物");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】非法设置宠物,已驳回", "EAC");
|
||||
Report(pc, "Illegal pet setting");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally set a pet and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -199,8 +217,8 @@ internal class EAC
|
||||
if (GameStates.IsInGame)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "非法设置皮肤");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】非法设置皮肤,已驳回", "EAC");
|
||||
Report(pc, "Illegal skin setting");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally set the skin and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -208,8 +226,8 @@ internal class EAC
|
||||
if (GameStates.IsInGame)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "非法设置面部装扮");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】非法设置面部装扮,已驳回", "EAC");
|
||||
Report(pc, "Illegal facial decoration");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally set facial decoration and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -217,8 +235,8 @@ internal class EAC
|
||||
if (GameStates.IsInGame)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "非法设置帽子");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】非法设置帽子,已驳回", "EAC");
|
||||
Report(pc, "Illegal hat setting");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally set a hat and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -227,8 +245,8 @@ internal class EAC
|
||||
if (GameStates.IsInGame)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "非法设置游戏名称");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】非法设置名称,已驳回", "EAC");
|
||||
Report(pc, "Illegal setting of game name");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally set the name and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -271,22 +289,22 @@ internal class EAC
|
||||
WarnHost();
|
||||
Report(player, "Bad Sabotage A : Non Imp");
|
||||
HandleCheat(player, "Bad Sabotage A : Non Imp");
|
||||
Logger.Fatal($"玩家【{player.GetClientId()}:{player.GetRealName()}】Bad Sabotage A,已驳回", "EAC");
|
||||
Logger.Fatal($"Player【{player.GetClientId()}:{player.GetRealName()}】Bad Sabotage A, rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SystemTypes.LifeSupp:
|
||||
if (Mapid != 0 && Mapid != 1 && Mapid != 3) goto YesCheat;
|
||||
else if (amount != 64 && amount != 65) goto YesCheat;
|
||||
if (Mapid is not 0 and not 1 and not 3) goto YesCheat;
|
||||
else if (amount is not 64 and not 65) goto YesCheat;
|
||||
break;
|
||||
case SystemTypes.Comms:
|
||||
if (amount == 0)
|
||||
{
|
||||
if (Mapid == 1 || Mapid == 5) goto YesCheat;
|
||||
if (Mapid is 1 or 5) goto YesCheat;
|
||||
}
|
||||
else if (amount == 64 || amount == 65 || amount == 32 || amount == 33 || amount == 16 || amount == 17)
|
||||
else if (amount is 64 or 65 or 32 or 33 or 16 or 17)
|
||||
{
|
||||
if (!(Mapid == 1 || Mapid == 5)) goto YesCheat;
|
||||
if (!(Mapid is 1 or 5)) goto YesCheat;
|
||||
}
|
||||
else goto YesCheat;
|
||||
break;
|
||||
@@ -299,16 +317,16 @@ internal class EAC
|
||||
break;
|
||||
case SystemTypes.Laboratory:
|
||||
if (Mapid != 2) goto YesCheat;
|
||||
else if (!(amount == 64 || amount == 65 || amount == 32 || amount == 33)) goto YesCheat;
|
||||
else if (!(amount is 64 or 65 or 32 or 33)) goto YesCheat;
|
||||
break;
|
||||
case SystemTypes.Reactor:
|
||||
if (Mapid == 2 || Mapid == 4) goto YesCheat;
|
||||
else if (!(amount == 64 || amount == 65 || amount == 32 || amount == 33)) goto YesCheat;
|
||||
if (Mapid is 2 or 4) goto YesCheat;
|
||||
else if (!(amount is 64 or 65 or 32 or 33)) goto YesCheat;
|
||||
//Airship use heli sabotage /Other use 64,65 | 32,33
|
||||
break;
|
||||
case SystemTypes.HeliSabotage:
|
||||
if (Mapid != 4) goto YesCheat;
|
||||
else if (!(amount == 64 || amount == 65 || amount == 16 || amount == 17 || amount == 32 || amount == 33)) goto YesCheat;
|
||||
else if (!(amount is 64 or 65 or 16 or 17 or 32 or 33)) goto YesCheat;
|
||||
break;
|
||||
case SystemTypes.MushroomMixupSabotage:
|
||||
goto YesCheat;
|
||||
@@ -318,7 +336,7 @@ internal class EAC
|
||||
{
|
||||
WarnHost();
|
||||
Report(player, "Bad Sabotage D : In Meeting");
|
||||
Logger.Fatal($"玩家【{player.GetClientId()}:{player.GetRealName()}】Bad Sabotage D,已驳回", "EAC");
|
||||
Logger.Fatal($"Player【{player.GetClientId()}:{player.GetRealName()}】Bad Sabotage D, rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
//There may be cases where a player is fixing reactor and a meeting start, triggering EAC check in meeting
|
||||
@@ -330,7 +348,7 @@ internal class EAC
|
||||
WarnHost();
|
||||
Report(player, "Bad Sabotage C : Hack send RPC");
|
||||
HandleCheat(player, "Bad Sabotage C");
|
||||
Logger.Fatal($"玩家【{player.GetClientId()}:{player.GetRealName()}】Bad Sabotage C,已驳回", "EAC");
|
||||
Logger.Fatal($"Player【{player.GetClientId()}:{player.GetRealName()}】Bad Sabotage C, rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -353,7 +371,7 @@ internal class EAC
|
||||
WarnHost();
|
||||
Report(player, "Report body out of game");
|
||||
HandleCheat(player, "Report body out of game");
|
||||
Logger.Fatal($"玩家【{player.GetClientId()}:{player.GetRealName()}】非游戏内开会,已驳回", "EAC");
|
||||
Logger.Fatal($"Player [{player.GetClientId()}:{player.GetRealName()}] is not meeting in the game and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -364,13 +382,13 @@ internal class EAC
|
||||
WarnHost();
|
||||
Report(player, "Spam report bodies");
|
||||
HandleCheat(player, "Spam report bodies");
|
||||
Logger.Fatal($"玩家【{player.GetClientId()}:{player.GetRealName()}】刷报告尸体满14次,已驳回", "EAC");
|
||||
Logger.Fatal($"Player [{player.GetClientId()}:{player.GetRealName()}] reported corpses 14 times and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
if (GameStates.IsMeeting)
|
||||
{
|
||||
//Cancel rpc report body if a meeting is already held
|
||||
Logger.Info($"玩家【{player.GetClientId()}:{player.GetRealName()}】在会议期间开会,已驳回", "EAC");
|
||||
Logger.Info($"Player [{player.GetClientId()}:{player.GetRealName()}] held a meeting during the meeting and it has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -383,7 +401,7 @@ internal class EAC
|
||||
{
|
||||
string msg = $"{pc.GetClientId()}|{pc.FriendCode}|{pc.Data.PlayerName}|{pc.GetClient().GetHashedPuid()}|{reason}";
|
||||
//Cloud.SendData(msg);
|
||||
Logger.Fatal($"EAC报告:{msg}", "EAC Cloud");
|
||||
Logger.Fatal($"EAC report: {msg}", "EAC Cloud");
|
||||
Logger.SendInGame(string.Format(GetString("Message.NoticeByEAC"), $"{pc?.Data?.PlayerName} | {pc.GetClient().GetHashedPuid()}", reason));
|
||||
}
|
||||
public static bool ReceiveInvalidRpc(PlayerControl pc, byte callId)
|
||||
|
||||
@@ -202,6 +202,7 @@ static class ExtendedPlayerControl
|
||||
// player.ResetKillCooldown();
|
||||
//}
|
||||
|
||||
public static void AddKCDAsAbilityCD(this PlayerControl pc) => AddAbilityCD(pc, (int)Math.Round(Main.AllPlayerKillCooldown.TryGetValue(pc.PlayerId, out var KCD) ? KCD : Options.DefaultKillCooldown));
|
||||
public static void AddAbilityCD(this PlayerControl pc, bool includeDuration = true) => Utils.AddAbilityCD(pc.GetCustomRole(), pc.PlayerId, includeDuration);
|
||||
public static void AddAbilityCD(this PlayerControl pc, int CD) => Main.AbilityCD[pc.PlayerId] = (GetTimeStamp(), CD);
|
||||
public static bool HasAbilityCD(this PlayerControl pc) => Main.AbilityCD.ContainsKey(pc.PlayerId);
|
||||
@@ -218,6 +219,12 @@ static class ExtendedPlayerControl
|
||||
public static void SetKillCooldown(this PlayerControl player, float time = -1f, PlayerControl target = null, bool forceAnime = false)
|
||||
{
|
||||
if (player == null) return;
|
||||
if (player.GetCustomRole().PetActivatedAbility())
|
||||
{
|
||||
if (time == -1f) player.AddKCDAsAbilityCD();
|
||||
else player.AddAbilityCD((int)Math.Round(time));
|
||||
return;
|
||||
}
|
||||
if (!player.CanUseKillButton()) return;
|
||||
player.AddKillTimerToDict(CD: time);
|
||||
if (target == null) target = player;
|
||||
@@ -384,7 +391,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)
|
||||
{
|
||||
@@ -616,8 +623,8 @@ static class ExtendedPlayerControl
|
||||
CustomRoles.YinYanger => pc.IsAlive(),
|
||||
CustomRoles.Librarian => pc.IsAlive() && Librarian.CanUseKillButton(pc),
|
||||
CustomRoles.Cantankerous => pc.IsAlive() && Cantankerous.CanUseKillButton(pc.PlayerId),
|
||||
CustomRoles.Inhibitor => !IsActive(SystemTypes.Electrical) && !IsActive(SystemTypes.Laboratory) && !IsActive(SystemTypes.Comms) && !IsActive(SystemTypes.LifeSupp) && !IsActive(SystemTypes.Reactor),
|
||||
CustomRoles.Saboteur => IsActive(SystemTypes.Electrical) || IsActive(SystemTypes.Laboratory) || IsActive(SystemTypes.Comms) || IsActive(SystemTypes.LifeSupp) || IsActive(SystemTypes.Reactor),
|
||||
CustomRoles.Inhibitor => !Utils.IsActive(SystemTypes.Electrical) && !Utils.IsActive(SystemTypes.Comms) && !Utils.IsActive(SystemTypes.MushroomMixupSabotage) && !Utils.IsActive(SystemTypes.Laboratory) && !Utils.IsActive(SystemTypes.LifeSupp) && !Utils.IsActive(SystemTypes.Reactor) && !Utils.IsActive(SystemTypes.HeliSabotage),
|
||||
CustomRoles.Saboteur => Utils.IsActive(SystemTypes.Electrical) || Utils.IsActive(SystemTypes.Comms) || Utils.IsActive(SystemTypes.MushroomMixupSabotage) || Utils.IsActive(SystemTypes.Laboratory) || Utils.IsActive(SystemTypes.LifeSupp) || Utils.IsActive(SystemTypes.Reactor) || Utils.IsActive(SystemTypes.HeliSabotage),
|
||||
CustomRoles.Sniper => Sniper.CanUseKillButton(pc),
|
||||
CustomRoles.Sheriff => Sheriff.CanUseKillButton(pc.PlayerId),
|
||||
CustomRoles.Crusader => Crusader.CanUseKillButton(pc.PlayerId),
|
||||
@@ -889,14 +896,23 @@ static class ExtendedPlayerControl
|
||||
{
|
||||
if (Main.AllPlayerKillCooldown.TryGetValue(pc.PlayerId, out var kcd)) resultKCD = kcd;
|
||||
else resultKCD = 0f;
|
||||
|
||||
if (half)
|
||||
{
|
||||
resultKCD /= 2f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
resultKCD = CD;
|
||||
}
|
||||
|
||||
if (Main.KillTimers.TryGetValue(pc.PlayerId, out var timer) && timer > resultKCD) return;
|
||||
if (pc.GetCustomRole().UsesPetInsteadOfKill() && resultKCD > 0f)
|
||||
{
|
||||
pc.AddAbilityCD((int)Math.Round(resultKCD));
|
||||
}
|
||||
|
||||
if (Main.KillTimers.TryGetValue(pc.PlayerId, out var timer) && timer > resultKCD) return;
|
||||
Main.KillTimers[pc.PlayerId] = resultKCD;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)];
|
||||
|
||||
|
||||
+12
-12
@@ -39,7 +39,7 @@ static class LocateArrow
|
||||
LocateArrows.Clear();
|
||||
}
|
||||
/// <summary>
|
||||
/// 新たにターゲット矢印対象を登録
|
||||
/// Register a new target arrow object
|
||||
/// </summary>
|
||||
/// <param name="seer"></param>
|
||||
/// <param name="target"></param>
|
||||
@@ -51,7 +51,7 @@ static class LocateArrow
|
||||
LocateArrows[arrowInfo] = "・";
|
||||
}
|
||||
/// <summary>
|
||||
/// ターゲットの削除
|
||||
/// Delete target
|
||||
/// </summary>
|
||||
/// <param name="seer"></param>
|
||||
/// <param name="target"></param>
|
||||
@@ -65,7 +65,7 @@ static class LocateArrow
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// タイプの同じターゲットの全削除
|
||||
/// Delete all targets for the specified seer
|
||||
/// </summary>
|
||||
/// <param name="seer"></param>
|
||||
public static void RemoveAllTarget(byte seer)
|
||||
@@ -77,7 +77,7 @@ static class LocateArrow
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 見ることのできるすべてのターゲット矢印を取得
|
||||
/// Get all visible target arrows
|
||||
/// </summary>
|
||||
/// <param name="seer"></param>
|
||||
/// <returns></returns>
|
||||
@@ -91,8 +91,8 @@ static class LocateArrow
|
||||
return arrows;
|
||||
}
|
||||
/// <summary>
|
||||
/// FixedUpdate毎にターゲット矢印を確認
|
||||
/// 更新があったらNotifyRolesを発行
|
||||
/// Check target arrow every FixedUpdate
|
||||
/// Issue NotifyRoles when there are updates
|
||||
/// </summary>
|
||||
/// <param name="seer"></param>
|
||||
public static void OnFixedUpdate(PlayerControl seer)
|
||||
@@ -115,20 +115,20 @@ static class LocateArrow
|
||||
update = true;
|
||||
continue;
|
||||
}
|
||||
//対象の方角ベクトルを取る
|
||||
// Take the direction vector of the target
|
||||
var dir = loc - seer.transform.position;
|
||||
int index;
|
||||
if (dir.magnitude < 2)
|
||||
{
|
||||
//近い時はドット表示
|
||||
// Display a dot when close
|
||||
index = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
//-22.5~22.5度を0とするindexに変換
|
||||
// 下が0度、左側が+180まで右側が-180まで
|
||||
// 180度足すことで上が0度の時計回り
|
||||
// 45度単位のindexにするため45/2を加算
|
||||
// Convert to index with -22.5 to 22.5 degrees as 0
|
||||
// Bottom is 0 degrees, left side is +180, right side is -180
|
||||
// Adding 180 degrees clockwise with top being 0 degrees
|
||||
// Add 45/2 to make index in 45 degree units
|
||||
var angle = Vector3.SignedAngle(Vector3.down, dir, Vector3.back) + 180 + 22.5;
|
||||
index = ((int)(angle / 45)) % 8;
|
||||
}
|
||||
|
||||
+17
-2
@@ -331,6 +331,7 @@ public static class Options
|
||||
public static OptionItem BodyguardKillsKiller;
|
||||
public static OptionItem WitnessCD;
|
||||
public static OptionItem WitnessTime;
|
||||
public static OptionItem WitnessUsePet;
|
||||
public static OptionItem DQNumOfKillsNeeded;
|
||||
public static OptionItem ParanoiaNumOfUseButton;
|
||||
public static OptionItem ParanoiaVentCooldown;
|
||||
@@ -370,6 +371,8 @@ public static class Options
|
||||
public static OptionItem UnderdogCanKillWithMorePlayersAlive;
|
||||
public static OptionItem UnderdogKillCooldownWithMorePlayersAlive;
|
||||
|
||||
public static OptionItem GodfatherCancelVote;
|
||||
|
||||
public static OptionItem NimbleCD;
|
||||
public static OptionItem NimbleInVentTime;
|
||||
public static OptionItem PhysicistCD;
|
||||
@@ -1315,6 +1318,7 @@ public static class Options
|
||||
RoleLoadingText = "Impostor roles\nGodfather";
|
||||
|
||||
SetupRoleOptions(555420, TabGroup.ImpostorRoles, CustomRoles.Godfather);
|
||||
GodfatherCancelVote = CreateVoteCancellingUseSetting(555422, CustomRoles.Godfather, TabGroup.ImpostorRoles);
|
||||
RoleLoadingText = "Impostor roles\nMorphling";
|
||||
Morphling.SetupCustomOption();
|
||||
RoleLoadingText = "Impostor roles\nNemesis";
|
||||
@@ -1790,6 +1794,7 @@ public static class Options
|
||||
WitnessTime = IntegerOptionItem.Create(8553, "WitnessTime", new(0, 90, 1), 10, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Witness])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
WitnessUsePet = CreatePetUseSetting(8554, CustomRoles.Witness);
|
||||
RoleLoadingText = "Crewmate roles\nVigilante";
|
||||
SwordsMan.SetupCustomOption();
|
||||
//Reverie.SetupCustomOption();
|
||||
@@ -2737,7 +2742,7 @@ public static class Options
|
||||
RemovePetsAtDeadPlayers = BooleanOptionItem.Create(60294, "RemovePetsAtDeadPlayers", false, TabGroup.SystemSettings, false)
|
||||
.SetColor(Color.magenta);
|
||||
|
||||
CheatResponses = StringOptionItem.Create(19319, "CheatResponses", CheatResponsesName, 0, TabGroup.SystemSettings, false)
|
||||
CheatResponses = StringOptionItem.Create(19319, "CheatResponses", CheatResponsesName, 2, TabGroup.SystemSettings, false)
|
||||
.SetHeader(true);
|
||||
|
||||
//HighLevelAntiCheat = StringOptionItem.Create(19320, "HighLevelAntiCheat", CheatResponsesName, 0, TabGroup.SystemSettings, false)
|
||||
@@ -3735,6 +3740,16 @@ public static class Options
|
||||
.SetParent(CustomRoleSpawnChances[role])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
|
||||
public static OptionItem CreatePetUseSetting(int id, CustomRoles role) =>
|
||||
BooleanOptionItem.Create(id, "UsePetInsteadOfKillButton", false, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[role])
|
||||
.SetColor(Color.magenta);
|
||||
|
||||
public static OptionItem CreateVoteCancellingUseSetting(int id, CustomRoles role, TabGroup tab) =>
|
||||
BooleanOptionItem.Create(id, "UseVoteCancellingAfterVote", false, tab, false)
|
||||
.SetParent(CustomRoleSpawnChances[role])
|
||||
.SetColor(Color.yellow);
|
||||
|
||||
public class OverrideTasksData
|
||||
{
|
||||
public static Dictionary<CustomRoles, OverrideTasksData> AllData = [];
|
||||
@@ -3768,7 +3783,7 @@ public static class Options
|
||||
numShortTasks.ReplacementDictionary = replacementDic;
|
||||
|
||||
if (!AllData.ContainsKey(role)) AllData.Add(role, this);
|
||||
else Logger.Warn("重複したCustomRolesを対象とするOverrideTasksDataが作成されました", "OverrideTasksData");
|
||||
else Logger.Warn("OverrideTasksData created for duplicate CustomRoles", "OverrideTasksData");
|
||||
}
|
||||
public static OverrideTasksData Create(int idStart, TabGroup tab, CustomRoles role) => new(idStart, tab, role);
|
||||
}
|
||||
|
||||
+12
-12
@@ -40,7 +40,7 @@ static class TargetArrow
|
||||
TargetArrows.Clear();
|
||||
}
|
||||
/// <summary>
|
||||
/// 新たにターゲット矢印対象を登録
|
||||
/// Register a new target arrow object
|
||||
/// </summary>
|
||||
/// <param name="seer"></param>
|
||||
/// <param name="target"></param>
|
||||
@@ -52,7 +52,7 @@ static class TargetArrow
|
||||
TargetArrows[arrowInfo] = "・";
|
||||
}
|
||||
/// <summary>
|
||||
/// ターゲットの削除
|
||||
/// Delete target
|
||||
/// </summary>
|
||||
/// <param name="seer"></param>
|
||||
/// <param name="target"></param>
|
||||
@@ -66,7 +66,7 @@ static class TargetArrow
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// タイプの同じターゲットの全削除
|
||||
/// Delete all targets for the specified seer
|
||||
/// </summary>
|
||||
/// <param name="seer"></param>
|
||||
public static void RemoveAllTarget(byte seer)
|
||||
@@ -78,7 +78,7 @@ static class TargetArrow
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 見ることのできるすべてのターゲット矢印を取得
|
||||
/// Get all visible target arrows
|
||||
/// </summary>
|
||||
/// <param name="seer"></param>
|
||||
/// <returns></returns>
|
||||
@@ -92,8 +92,8 @@ static class TargetArrow
|
||||
return arrows;
|
||||
}
|
||||
/// <summary>
|
||||
/// FixedUpdate毎にターゲット矢印を確認
|
||||
/// 更新があったらNotifyRolesを発行
|
||||
/// Check target arrow every FixedUpdate
|
||||
/// Issue NotifyRoles when there are updates
|
||||
/// </summary>
|
||||
/// <param name="seer"></param>
|
||||
public static void OnFixedUpdate(PlayerControl seer)
|
||||
@@ -117,20 +117,20 @@ static class TargetArrow
|
||||
update = true;
|
||||
continue;
|
||||
}
|
||||
//対象の方角ベクトルを取る
|
||||
// Take the direction vector of the target
|
||||
var dir = target.transform.position - seer.transform.position;
|
||||
int index;
|
||||
if (dir.magnitude < 2)
|
||||
{
|
||||
//近い時はドット表示
|
||||
// Display a dot when close
|
||||
index = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
//-22.5~22.5度を0とするindexに変換
|
||||
// 下が0度、左側が+180まで右側が-180まで
|
||||
// 180度足すことで上が0度の時計回り
|
||||
// 45度単位のindexにするため45/2を加算
|
||||
// Convert to index with -22.5 to 22.5 degrees as 0
|
||||
// Bottom is 0 degrees, left side is +180, right side is -180
|
||||
// Adding 180 degrees clockwise with top being 0 degrees
|
||||
// Add 45/2 to make index in 45 degree units
|
||||
var angle = Vector3.SignedAngle(Vector3.down, dir, Vector3.back) + 180 + 22.5;
|
||||
index = ((int)(angle / 45)) % 8;
|
||||
}
|
||||
|
||||
+43
-20
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,7 +490,7 @@ public static class Utils
|
||||
switch (role)
|
||||
{
|
||||
case CustomRoles.GM:
|
||||
case CustomRoles.Sheriff:
|
||||
case CustomRoles.Sheriff when !Options.UsePets.GetBool() || !Sheriff.UsePet.GetBool():
|
||||
case CustomRoles.Arsonist:
|
||||
case CustomRoles.Jackal:
|
||||
case CustomRoles.Sidekick:
|
||||
@@ -514,7 +514,7 @@ public static class Utils
|
||||
case CustomRoles.Imitator:
|
||||
case CustomRoles.Werewolf:
|
||||
case CustomRoles.Bandit:
|
||||
case CustomRoles.Jailor:
|
||||
case CustomRoles.Jailor when !Options.UsePets.GetBool() || !Jailor.UsePet.GetBool():
|
||||
case CustomRoles.Traitor:
|
||||
case CustomRoles.Glitch:
|
||||
case CustomRoles.Pickpocket:
|
||||
@@ -522,7 +522,7 @@ public static class Utils
|
||||
case CustomRoles.Jinx:
|
||||
case CustomRoles.Parasite:
|
||||
case CustomRoles.Agitater:
|
||||
case CustomRoles.Crusader:
|
||||
case CustomRoles.Crusader when !Options.UsePets.GetBool() || !Crusader.UsePet.GetBool():
|
||||
case CustomRoles.Refugee:
|
||||
case CustomRoles.Jester:
|
||||
//case CustomRoles.Pirate:
|
||||
@@ -532,7 +532,7 @@ public static class Utils
|
||||
case CustomRoles.Mario:
|
||||
case CustomRoles.Vulture:
|
||||
case CustomRoles.God:
|
||||
case CustomRoles.SwordsMan:
|
||||
case CustomRoles.SwordsMan when !Options.UsePets.GetBool() || !SwordsMan.UsePet.GetBool():
|
||||
case CustomRoles.Innocent:
|
||||
case CustomRoles.Pelican:
|
||||
case CustomRoles.Medusa:
|
||||
@@ -549,7 +549,7 @@ public static class Utils
|
||||
case CustomRoles.Collector:
|
||||
case CustomRoles.ImperiusCurse:
|
||||
case CustomRoles.Provocateur:
|
||||
case CustomRoles.Medic:
|
||||
case CustomRoles.Medic when !Options.UsePets.GetBool() || !Medic.UsePet.GetBool():
|
||||
case CustomRoles.BloodKnight:
|
||||
case CustomRoles.Camouflager:
|
||||
case CustomRoles.Totocalcio:
|
||||
@@ -558,20 +558,20 @@ public static class Utils
|
||||
case CustomRoles.RuthlessRomantic:
|
||||
case CustomRoles.Succubus:
|
||||
//case CustomRoles.CursedSoul:
|
||||
case CustomRoles.Admirer:
|
||||
case CustomRoles.Admirer when !Options.UsePets.GetBool() || !Admirer.UsePet.GetBool():
|
||||
case CustomRoles.Amnesiac:
|
||||
case CustomRoles.Infectious:
|
||||
case CustomRoles.Monarch:
|
||||
case CustomRoles.Deputy:
|
||||
case CustomRoles.Monarch when !Options.UsePets.GetBool() || !Monarch.UsePet.GetBool():
|
||||
case CustomRoles.Deputy when !Options.UsePets.GetBool() || !Deputy.UsePet.GetBool():
|
||||
case CustomRoles.Virus:
|
||||
case CustomRoles.Farseer:
|
||||
case CustomRoles.Farseer when !Options.UsePets.GetBool() || !Farseer.UsePet.GetBool():
|
||||
//case CustomRoles.Counterfeiter:
|
||||
case CustomRoles.Aid:
|
||||
case CustomRoles.Escort:
|
||||
case CustomRoles.DonutDelivery:
|
||||
case CustomRoles.Gaulois:
|
||||
case CustomRoles.Analyzer:
|
||||
case CustomRoles.Witness:
|
||||
case CustomRoles.Aid when !Options.UsePets.GetBool() || !Aid.UsePet.GetBool():
|
||||
case CustomRoles.Escort when !Options.UsePets.GetBool() || !Escort.UsePet.GetBool():
|
||||
case CustomRoles.DonutDelivery when !Options.UsePets.GetBool() || !DonutDelivery.UsePet.GetBool():
|
||||
case CustomRoles.Gaulois when !Options.UsePets.GetBool() || !Gaulois.UsePet.GetBool():
|
||||
case CustomRoles.Analyzer when !Options.UsePets.GetBool() || !Analyzer.UsePet.GetBool():
|
||||
case CustomRoles.Witness when !Options.UsePets.GetBool() || !Options.WitnessUsePet.GetBool():
|
||||
case CustomRoles.Pursuer:
|
||||
case CustomRoles.Spiritcaller:
|
||||
case CustomRoles.PlagueBearer:
|
||||
@@ -623,7 +623,7 @@ public static class Utils
|
||||
}
|
||||
}
|
||||
|
||||
if (CopyCat.playerIdList.Contains(p.PlayerId) && ForRecompute) hasTasks = false;
|
||||
if (CopyCat.playerIdList.Contains(p.PlayerId) && ForRecompute && (!Options.UsePets.GetBool() || CopyCat.UsePet.GetBool())) hasTasks = false;
|
||||
|
||||
return hasTasks;
|
||||
}
|
||||
@@ -1926,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);
|
||||
@@ -2549,6 +2549,11 @@ public static class Utils
|
||||
}
|
||||
public static void AddAbilityCD(CustomRoles role, byte playerId, bool includeDuration = true)
|
||||
{
|
||||
if (role.UsesPetInsteadOfKill())
|
||||
{
|
||||
Main.AbilityCD[playerId] = (GetTimeStamp(), (int)Math.Round(Main.AllPlayerKillCooldown.TryGetValue(playerId, out var KCD) ? KCD : Options.DefaultKillCooldown));
|
||||
return;
|
||||
}
|
||||
int CD = role switch
|
||||
{
|
||||
CustomRoles.Doormaster => Doormaster.VentCooldown.GetInt(),
|
||||
@@ -2650,6 +2655,8 @@ public static class Utils
|
||||
if (Options.AirshipVariableElectrical.GetBool())
|
||||
AirshipElectricalDoors.Initialize();
|
||||
|
||||
Main.DontCancelVoteList.Clear();
|
||||
|
||||
DoorsReset.ResetDoors();
|
||||
KeepProtection.ProtectEveryone();
|
||||
|
||||
@@ -2891,7 +2898,23 @@ public static class Utils
|
||||
neutralnum++;
|
||||
}
|
||||
}
|
||||
return $"{(notify ? "<color=#777777>" : string.Empty)}There {(impnum == 1 ? "is" : "are")}{(notify ? ' ' : '\n')}{(notify ? "<#ffffff>" : "<b>")}{impnum}{(notify ? "</color>" : "</b>")} <color=#ff1919>{(impnum == 1 ? "Impostor" : "Impostors")}</color> and {(notify ? "<#ffffff>" : "<b>")}{neutralnum}{(notify ? "</color>" : "</b>")} <color=#ffab1b>{(neutralnum == 1 ? "Neutral Killer" : "Neutral Killers")}</color> left.{(notify ? "</color>" : string.Empty)}";
|
||||
return (notify ? "<#777777>" : string.Empty) +
|
||||
(impnum == 1 ? GetString("RemainingText.Prefix.SingleImp") : GetString("RemainingText.Prefix.PluralImp")) +
|
||||
(notify ? " " : "\n") +
|
||||
(notify ? "<#ffffff>" : "<b>") +
|
||||
impnum +
|
||||
(notify ? "</color>" : "</b>") +
|
||||
" " +
|
||||
$"<#ff1919>{(impnum == 1 ? GetString("RemainingText.ImpSingle") : GetString("RemainingText.ImpPlural"))}</color>" +
|
||||
" & " +
|
||||
(notify ? "<#ffffff>" : "<b>") +
|
||||
neutralnum +
|
||||
(notify ? "</color>" : "</b>") +
|
||||
" " +
|
||||
$"<#ffab1b>{(neutralnum == 1 ? GetString("RemainingText.NKSingle") : GetString("RemainingText.NKPlural"))}</color>" +
|
||||
GetString("RemainingText.Suffix") +
|
||||
"." +
|
||||
(notify ? "</color>" : string.Empty);
|
||||
}
|
||||
public static string RemoveHtmlTagsTemplate(this string str) => Regex.Replace(str, string.Empty, string.Empty);
|
||||
public static string RemoveHtmlTags(this string str) => Regex.Replace(str, "<[^>]*?>", string.Empty);
|
||||
|
||||
@@ -11,7 +11,6 @@ using TOHE.Modules;
|
||||
using TOHE.Roles.Crewmate;
|
||||
using TOHE.Roles.Impostor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using static TOHE.Translator;
|
||||
|
||||
|
||||
@@ -33,7 +32,9 @@ internal class ChatCommands
|
||||
|
||||
public static bool Prefix(ChatController __instance)
|
||||
{
|
||||
if (__instance.quickChatField.visible) return true;
|
||||
if (__instance.freeChatField.textArea.text == string.Empty) return false;
|
||||
if (!GameStates.IsModHost && !AmongUsClient.Instance.AmHost) return true;
|
||||
__instance.timeSinceLastMessage = 3f;
|
||||
|
||||
var text = __instance.freeChatField.textArea.text;
|
||||
|
||||
@@ -47,7 +47,7 @@ class ChatControllerUpdatePatch
|
||||
}
|
||||
}
|
||||
|
||||
public class ChatManager
|
||||
public static class ChatManager
|
||||
{
|
||||
public static bool cancel;
|
||||
private static readonly List<string> chatHistory = [];
|
||||
@@ -152,6 +152,7 @@ public class ChatManager
|
||||
|
||||
public static void SendPreviousMessagesToAll(bool realMessagesOnly = false)
|
||||
{
|
||||
if (!AmongUsClient.Instance.AmHost || !GameStates.IsModHost) return;
|
||||
ChatUpdatePatch.DoBlockChat = true;
|
||||
string msg = Utils.EmptyMessage();
|
||||
List<CustomRoles> roles = Enum.GetValues(typeof(CustomRoles)).Cast<CustomRoles>().Where(x => x is not CustomRoles.KB_Normal and not CustomRoles.Killer and not CustomRoles.Tasker).ToList();
|
||||
|
||||
@@ -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);
|
||||
@@ -40,7 +40,9 @@ class GameEndChecker
|
||||
//ゲーム終了時
|
||||
if (CustomWinnerHolder.WinnerTeam != CustomWinner.Default)
|
||||
{
|
||||
//カモフラージュ強制解除
|
||||
NameNotifyManager.Reset();
|
||||
NotifyRoles(ForceLoop: true);
|
||||
|
||||
Main.AllPlayerControls.Do(pc => Camouflage.RpcSetSkin(pc, ForceRevert: true, RevertToDefault: true));
|
||||
|
||||
if (reason == GameOverReason.ImpostorBySabotage && (CustomRoles.Jackal.RoleExist() || CustomRoles.Sidekick.RoleExist()) && Jackal.CanWinBySabotageWhenNoImpAlive.GetBool() && !Main.AllAlivePlayerControls.Any(x => x.GetCustomRole().IsImpostorTeam()))
|
||||
@@ -533,7 +535,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 +563,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 +620,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;
|
||||
}
|
||||
|
||||
+12
-2
@@ -101,10 +101,20 @@ internal class InnerNetClientCanBanPatch
|
||||
[HarmonyPatch(typeof(InnerNetClient), nameof(InnerNetClient.KickPlayer))]
|
||||
internal class KickPlayerPatch
|
||||
{
|
||||
public static void Prefix(InnerNetClient __instance, int clientId, bool ban)
|
||||
public static bool Prefix(InnerNetClient __instance, int clientId, bool ban)
|
||||
{
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost) return true;
|
||||
|
||||
if (AmongUsClient.Instance.ClientId == clientId)
|
||||
{
|
||||
Logger.SendInGame(string.Format("Game Attempting to {0} Host, Blocked the attempt.", ban ? "Ban" : "Kick"));
|
||||
Logger.Info("Game attempted to kick/ban host....", "KickPlayerPatch");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ban) BanManager.AddBanPlayer(AmongUsClient.Instance.GetRecentClient(clientId));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
[HarmonyPatch(typeof(ResolutionManager), nameof(ResolutionManager.SetResolution))]
|
||||
|
||||
+3
-3
@@ -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++)
|
||||
@@ -580,7 +580,7 @@ class HudManagerPatch
|
||||
LowerInfoText.enabled = false;
|
||||
}
|
||||
|
||||
if (player.CanUseKillButton())
|
||||
if (player.CanUseKillButton() && !player.GetCustomRole().UsesPetInsteadOfKill())
|
||||
{
|
||||
__instance.KillButton?.ToggleVisible(player.IsAlive() && GameStates.IsInTask);
|
||||
player.Data.Role.CanUseKillButton = true;
|
||||
|
||||
@@ -512,8 +512,12 @@ class IntroCutsceneDestroyPatch
|
||||
{
|
||||
if (Main.NormalOptions.MapId != 4)
|
||||
{
|
||||
Main.AllPlayerControls.Do(pc => pc.RpcResetAbilityCooldown());
|
||||
Main.AllPlayerControls.Do(pc => pc.AddAbilityCD());
|
||||
foreach (var pc in Main.AllAlivePlayerControls)
|
||||
{
|
||||
pc.RpcResetAbilityCooldown();
|
||||
if (pc.GetCustomRole().UsesPetInsteadOfKill()) pc.AddAbilityCD(10);
|
||||
else pc.AddAbilityCD();
|
||||
}
|
||||
if (Options.StartingKillCooldown.GetInt() != 10 && Options.StartingKillCooldown.GetInt() > 0)
|
||||
{
|
||||
_ = new LateTask(() =>
|
||||
|
||||
+93
-44
@@ -87,40 +87,36 @@ class CheckForEndVotingPatch
|
||||
{
|
||||
switch (pc.GetCustomRole())
|
||||
{
|
||||
case CustomRoles.Divinator:
|
||||
case CustomRoles.Divinator when !Divinator.CancelVote.GetBool():
|
||||
Divinator.OnVote(pc, voteTarget);
|
||||
break;
|
||||
case CustomRoles.Oracle:
|
||||
case CustomRoles.Oracle when !Oracle.CancelVote.GetBool():
|
||||
Oracle.OnVote(pc, voteTarget);
|
||||
break;
|
||||
case CustomRoles.Eraser:
|
||||
case CustomRoles.Eraser when !Eraser.CancelVote.GetBool():
|
||||
Eraser.OnVote(pc, voteTarget);
|
||||
break;
|
||||
case CustomRoles.Tether:
|
||||
case CustomRoles.Tether when !Tether.CancelVote.GetBool():
|
||||
Tether.OnVote(pc, voteTarget);
|
||||
break;
|
||||
case CustomRoles.Ricochet:
|
||||
case CustomRoles.Ricochet when !Ricochet.CancelVote.GetBool():
|
||||
Ricochet.OnVote(pc, voteTarget);
|
||||
break;
|
||||
case CustomRoles.Cleanser:
|
||||
case CustomRoles.Cleanser when !Cleanser.CancelVote.GetBool():
|
||||
Cleanser.OnVote(pc, voteTarget);
|
||||
break;
|
||||
//case CustomRoles.Jailor:
|
||||
// Jailor.OnVote(pc, voteTarget);
|
||||
// break;
|
||||
case CustomRoles.NiceEraser:
|
||||
case CustomRoles.NiceEraser when !NiceEraser.CancelVote.GetBool():
|
||||
NiceEraser.OnVote(pc, voteTarget);
|
||||
break;
|
||||
case CustomRoles.Tracker:
|
||||
case CustomRoles.Tracker when !Tracker.CancelVote.GetBool():
|
||||
Tracker.OnVote(pc, voteTarget);
|
||||
break;
|
||||
case CustomRoles.Godfather:
|
||||
if (pc == null || voteTarget == null) break;
|
||||
case CustomRoles.Godfather when !Options.GodfatherCancelVote.GetBool():
|
||||
Main.GodfatherTarget = voteTarget.PlayerId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (pc.GetCustomRole() == CustomRoles.Godfather) Main.GodfatherTarget = byte.MaxValue;
|
||||
else if (pc.Is(CustomRoles.Godfather)) Main.GodfatherTarget = byte.MaxValue;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < __instance.playerStates.Count; i++)
|
||||
@@ -408,19 +404,16 @@ class CheckForEndVotingPatch
|
||||
var role = GetString(exiledPlayer.GetCustomRole().ToString());
|
||||
var crole = exiledPlayer.GetCustomRole();
|
||||
var coloredRole = Utils.GetDisplayRoleName(exileId, true);
|
||||
if (Options.ConfirmEgoistOnEject.GetBool() && player.Is(CustomRoles.Egoist))
|
||||
coloredRole = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Egoist), GetRoleString("Temp.Blank") + coloredRole.RemoveHtmlTags());
|
||||
// if (Options.ConfirmSidekickOnEject.GetBool() && player.Is(CustomRoles.Sidekick))
|
||||
// coloredRole = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Sidekick), GetRoleString("Temp.Blank") + coloredRole.RemoveHtmlTags());
|
||||
if (Options.ConfirmLoversOnEject.GetBool() && player.Is(CustomRoles.Lovers))
|
||||
coloredRole = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Lovers), GetRoleString("Temp.Blank") + coloredRole.RemoveHtmlTags());
|
||||
if (Options.RascalAppearAsMadmate.GetBool() && player.Is(CustomRoles.Rascal))
|
||||
coloredRole = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Madmate), GetRoleString("Mad-") + coloredRole.RemoveHtmlTags());
|
||||
|
||||
if (Options.ConfirmEgoistOnEject.GetBool() && player.Is(CustomRoles.Egoist)) coloredRole = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Egoist), GetRoleString("Temp.Blank") + coloredRole.RemoveHtmlTags());
|
||||
if (Options.ConfirmLoversOnEject.GetBool() && player.Is(CustomRoles.Lovers)) coloredRole = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Lovers), GetRoleString("Temp.Blank") + coloredRole.RemoveHtmlTags());
|
||||
if (Options.RascalAppearAsMadmate.GetBool() && player.Is(CustomRoles.Rascal)) coloredRole = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Madmate), GetRoleString("Mad-") + coloredRole.RemoveHtmlTags());
|
||||
|
||||
var name = string.Empty;
|
||||
int impnum = 0;
|
||||
int neutralnum = 0;
|
||||
|
||||
if (CustomRolesHelper.RoleExist(CustomRoles.Bard))
|
||||
if (CustomRoles.Bard.RoleExist())
|
||||
{
|
||||
Main.BardCreations++;
|
||||
try { name = ModUpdater.Get("https://v1.hitokoto.cn/?encode=text"); }
|
||||
@@ -500,18 +493,18 @@ class CheckForEndVotingPatch
|
||||
case (0, 0): // Crewmates win
|
||||
name += GetString("GG");
|
||||
break;
|
||||
case ( > 0, > 0): // Both imps and neutrals remain
|
||||
case (> 0, > 0): // Both imps and neutrals remain
|
||||
name += impnum switch
|
||||
{
|
||||
1 => "1 <color=#ff1919>Impostor</color> <color=#777777>&</color> ",
|
||||
2 => "2 <color=#ff1919>Impostors</color> <color=#777777>&</color> ",
|
||||
3 => "3 <color=#ff1919>Impostors</color> <color=#777777>&</color> ",
|
||||
1 => $"1 <color=#ff1919>{GetString("RemainingText.ImpSingle")}</color> <color=#777777>&</color> ",
|
||||
2 => $"2 <color=#ff1919>{GetString("RemainingText.ImpPlural")}</color> <color=#777777>&</color> ",
|
||||
3 => $"3 <color=#ff1919>{GetString("RemainingText.ImpPlural")}</color> <color=#777777>&</color> ",
|
||||
_ => string.Empty,
|
||||
};
|
||||
if (neutralnum == 1) name += "1 <color=#ffab1b>Neutral</color> <color=#777777>remains.</color>";
|
||||
else name += $"{neutralnum} <color=#ffab1b>Neutrals</color> <color=#777777>remain.</color>";
|
||||
if (neutralnum == 1) name += $"1 <color=#ffab1b>{GetString("RemainingText.NKSingle")}</color> <color=#777777>{GetString("RemainingText.EjectionSuffix.NKSingle")}</color>";
|
||||
else name += $"{neutralnum} <color=#ffab1b>{GetString("RemainingText.NKPlural")}</color> <color=#777777>{GetString("RemainingText.EjectionSuffix.NKPlural")}</color>";
|
||||
break;
|
||||
case ( > 0, 0): // Only imps remain
|
||||
case (> 0, 0): // Only imps remain
|
||||
name += impnum switch
|
||||
{
|
||||
1 => GetString("OneImpRemain"),
|
||||
@@ -1336,11 +1329,9 @@ class MeetingHudOnDestroyPatch
|
||||
[HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.CastVote))]
|
||||
class MeetingHudCastVotePatch
|
||||
{
|
||||
public static bool Prefix()
|
||||
{
|
||||
return true; // return false to use the vote as a trigger
|
||||
}
|
||||
public static void Postfix(MeetingHud __instance, [HarmonyArgument(0)] byte srcPlayerId, [HarmonyArgument(1)] byte suspectPlayerId)
|
||||
private static readonly Dictionary<byte, (MeetingHud MEETING_HUD, PlayerVoteArea SOURCE_PLAYER_VOTE_AREA, PlayerControl SOURCE_PLAYER)> ShouldCancelVoteList = [];
|
||||
|
||||
public static bool Prefix(MeetingHud __instance, [HarmonyArgument(0)] byte srcPlayerId, [HarmonyArgument(1)] byte suspectPlayerId)
|
||||
{
|
||||
PlayerVoteArea pva_src = null;
|
||||
PlayerVoteArea pva_target = null;
|
||||
@@ -1353,7 +1344,7 @@ class MeetingHudCastVotePatch
|
||||
if (pva_src == null)
|
||||
{
|
||||
Logger.Error("Src PlayerVoteArea not found", "MeetingHudCastVotePatch.Prefix");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (pva_target == null)
|
||||
{
|
||||
@@ -1365,7 +1356,7 @@ class MeetingHudCastVotePatch
|
||||
if (pc_src == null)
|
||||
{
|
||||
Logger.Error("Src PlayerControl is null", "MeetingHudCastVotePatch.Prefix");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (pc_target == null)
|
||||
{
|
||||
@@ -1373,21 +1364,79 @@ class MeetingHudCastVotePatch
|
||||
isSkip = true;
|
||||
}
|
||||
|
||||
Logger.Info($"{pc_src.GetNameWithRole().RemoveHtmlTags()} => {(isSkip ? "Skip" : pc_target.GetNameWithRole().RemoveHtmlTags())}", "Vote");
|
||||
bool isVoteCanceled = false;
|
||||
|
||||
//pva_src.UnsetVote(); // Uncomment to use the vote as a trigger
|
||||
//__instance.RpcClearVote(pc_src.GetClientId()); // Uncomment to use the vote as a trigger
|
||||
if (!Main.DontCancelVoteList.Contains(srcPlayerId))
|
||||
{
|
||||
if (!isSkip)
|
||||
{
|
||||
switch (pc_src.GetCustomRole())
|
||||
{
|
||||
case CustomRoles.Divinator when Divinator.CancelVote.GetBool():
|
||||
if (Divinator.OnVote(pc_src, pc_target)) CancelVote();
|
||||
break;
|
||||
case CustomRoles.Oracle when Oracle.CancelVote.GetBool():
|
||||
if (Oracle.OnVote(pc_src, pc_target)) CancelVote();
|
||||
break;
|
||||
case CustomRoles.Eraser when Eraser.CancelVote.GetBool():
|
||||
if (Eraser.OnVote(pc_src, pc_target)) CancelVote();
|
||||
break;
|
||||
case CustomRoles.Tether when Tether.CancelVote.GetBool():
|
||||
if (Tether.OnVote(pc_src, pc_target)) CancelVote();
|
||||
break;
|
||||
case CustomRoles.Ricochet when Ricochet.CancelVote.GetBool():
|
||||
if (Ricochet.OnVote(pc_src, pc_target)) CancelVote();
|
||||
break;
|
||||
case CustomRoles.Cleanser when Cleanser.CancelVote.GetBool():
|
||||
if (Cleanser.OnVote(pc_src, pc_target)) CancelVote();
|
||||
break;
|
||||
case CustomRoles.NiceEraser when NiceEraser.CancelVote.GetBool():
|
||||
if (NiceEraser.OnVote(pc_src, pc_target)) CancelVote();
|
||||
break;
|
||||
case CustomRoles.Tracker when Tracker.CancelVote.GetBool():
|
||||
if (Tracker.OnVote(pc_src, pc_target)) CancelVote();
|
||||
break;
|
||||
case CustomRoles.Godfather when Options.GodfatherCancelVote.GetBool():
|
||||
Main.GodfatherTarget = pc_target.PlayerId;
|
||||
CancelVote();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CancelVote()
|
||||
{
|
||||
ShouldCancelVoteList.TryAdd(srcPlayerId, (__instance, pva_src, pc_src));
|
||||
isVoteCanceled = true;
|
||||
}
|
||||
|
||||
Logger.Info($"{pc_src.GetNameWithRole().RemoveHtmlTags()} => {(isSkip ? "Skip" : pc_target.GetNameWithRole().RemoveHtmlTags())}{(isVoteCanceled ? " (Canceled)" : string.Empty)}", "Vote");
|
||||
|
||||
return isSkip || !isVoteCanceled; // return false to use the vote as a trigger; skips and invalid votes are never canceled
|
||||
}
|
||||
public static void Postfix([HarmonyArgument(0)] byte srcPlayerId)
|
||||
{
|
||||
if (!ShouldCancelVoteList.TryGetValue(srcPlayerId, out var info)) return;
|
||||
|
||||
MeetingHud __instance = info.MEETING_HUD;
|
||||
PlayerVoteArea pva_src = info.SOURCE_PLAYER_VOTE_AREA;
|
||||
PlayerControl pc_src = info.SOURCE_PLAYER;
|
||||
|
||||
try { pva_src.UnsetVote(); } catch { }
|
||||
__instance.RpcClearVote(pc_src.GetClientId());
|
||||
|
||||
ShouldCancelVoteList.Remove(srcPlayerId);
|
||||
}
|
||||
}
|
||||
[HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.CmdCastVote))]
|
||||
class MeetingHudCmdCastVotePatch
|
||||
{
|
||||
public static bool Prefix()
|
||||
public static bool Prefix(MeetingHud __instance, [HarmonyArgument(0)] byte srcPlayerId, [HarmonyArgument(1)] byte suspectPlayerId)
|
||||
{
|
||||
return MeetingHudCastVotePatch.Prefix();
|
||||
return MeetingHudCastVotePatch.Prefix(__instance, srcPlayerId, suspectPlayerId);
|
||||
}
|
||||
public static void Postfix(MeetingHud __instance, [HarmonyArgument(0)] byte srcPlayerId, [HarmonyArgument(1)] byte suspectPlayerId)
|
||||
public static void Postfix([HarmonyArgument(0)] byte srcPlayerId)
|
||||
{
|
||||
MeetingHudCastVotePatch.Postfix(__instance, srcPlayerId, suspectPlayerId);
|
||||
MeetingHudCastVotePatch.Postfix(srcPlayerId);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using AmongUs.GameOptions;
|
||||
using HarmonyLib;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -7,6 +8,7 @@ using TOHE.Modules;
|
||||
using TOHE.Roles.Crewmate;
|
||||
using TOHE.Roles.Impostor;
|
||||
using TOHE.Roles.Neutral;
|
||||
using UnityEngine;
|
||||
using static TOHE.Translator;
|
||||
|
||||
namespace TOHE;
|
||||
@@ -98,6 +100,11 @@ class ExternalRpcPetPatch
|
||||
|
||||
PlayerControl[] AllAlivePlayers = Main.AllAlivePlayerControls;
|
||||
|
||||
bool hasKillTarget = false;
|
||||
PlayerControl target = SelectKillButtonTarget(pc);
|
||||
if (target != null) hasKillTarget = true;
|
||||
if (!pc.CanUseKillButton()) hasKillTarget = false;
|
||||
|
||||
switch (pc.GetCustomRole())
|
||||
{
|
||||
// Crewmates
|
||||
@@ -304,6 +311,75 @@ class ExternalRpcPetPatch
|
||||
pc.Notify(sb.ToString());
|
||||
break;
|
||||
|
||||
case CustomRoles.Gaulois when hasKillTarget:
|
||||
Gaulois.OnCheckMurder(pc, target);
|
||||
pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.Aid when hasKillTarget:
|
||||
Aid.OnCheckMurder(pc, target);
|
||||
pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.Escort when hasKillTarget:
|
||||
Escort.OnCheckMurder(pc, target);
|
||||
pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.DonutDelivery when hasKillTarget:
|
||||
DonutDelivery.OnCheckMurder(pc, target);
|
||||
pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.Analyzer when hasKillTarget:
|
||||
Analyzer.OnCheckMurder(pc, target);
|
||||
pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.Jailor when hasKillTarget:
|
||||
Jailor.OnCheckMurder(pc, target);
|
||||
pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.Sheriff when hasKillTarget:
|
||||
if (Sheriff.OnCheckMurder(pc, target)) pc.RpcCheckAndMurder(target);
|
||||
else pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.SwordsMan when hasKillTarget:
|
||||
if (SwordsMan.OnCheckMurder(pc)) if (!pc.RpcCheckAndMurder(target)) pc.AddKCDAsAbilityCD();
|
||||
else pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.Witness when hasKillTarget:
|
||||
if (Main.AllKillers.ContainsKey(target.PlayerId))
|
||||
pc.Notify(GetString("WitnessFoundKiller"));
|
||||
else pc.Notify(GetString("WitnessFoundInnocent"));
|
||||
pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.Medic when hasKillTarget:
|
||||
Medic.OnCheckMurderFormedicaler(pc, target);
|
||||
pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.Monarch when hasKillTarget:
|
||||
Monarch.OnCheckMurder(pc, target);
|
||||
pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.CopyCat when hasKillTarget:
|
||||
if (CopyCat.OnCheckMurder(pc, target)) if (!pc.RpcCheckAndMurder(target)) pc.AddKCDAsAbilityCD();
|
||||
pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.Farseer when hasKillTarget:
|
||||
pc.AddAbilityCD(Farseer.FarseerRevealTime.GetInt());
|
||||
if (!Main.isRevealed[(pc.PlayerId, target.PlayerId)] && !Main.FarseerTimer.ContainsKey(pc.PlayerId))
|
||||
{
|
||||
Main.FarseerTimer.TryAdd(pc.PlayerId, (target, 0f));
|
||||
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: target, ForceLoop: true);
|
||||
RPC.SetCurrentRevealTarget(pc.PlayerId, target.PlayerId);
|
||||
}
|
||||
break;
|
||||
case CustomRoles.Deputy when hasKillTarget:
|
||||
Deputy.OnCheckMurder(pc, target);
|
||||
break;
|
||||
case CustomRoles.Admirer when hasKillTarget:
|
||||
Admirer.OnCheckMurder(pc, target);
|
||||
break;
|
||||
case CustomRoles.Crusader when hasKillTarget:
|
||||
Crusader.OnCheckMurder(pc, target);
|
||||
break;
|
||||
|
||||
// Impostors
|
||||
|
||||
case CustomRoles.Sniper:
|
||||
@@ -326,11 +402,11 @@ class ExternalRpcPetPatch
|
||||
if (!Options.WarlockCanKillAllies.GetBool() && p.GetCustomRole().IsImpostor()) continue;
|
||||
if (p.Is(CustomRoles.Pestilence)) continue;
|
||||
if (Pelican.IsEaten(p.PlayerId) || Medic.ProtectList.Contains(p.PlayerId)) continue;
|
||||
dis = UnityEngine.Vector2.Distance(cppos, p.Pos());
|
||||
dis = Vector2.Distance(cppos, p.Pos());
|
||||
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;
|
||||
@@ -391,7 +467,7 @@ class ExternalRpcPetPatch
|
||||
{
|
||||
if (!tg.IsModClient()) tg.KillFlash();
|
||||
var pos = pc.Pos();
|
||||
var dis = UnityEngine.Vector2.Distance(pos, tg.Pos());
|
||||
var dis = Vector2.Distance(pos, tg.Pos());
|
||||
|
||||
if (!tg.IsAlive() || Pelican.IsEaten(tg.PlayerId) || Medic.ProtectList.Contains(tg.PlayerId) || (tg.Is(CustomRoleTypes.Impostor) && Options.ImpostorsSurviveBombs.GetBool()) || tg.inVent || tg.Is(CustomRoles.Pestilence)) continue;
|
||||
if (dis > Options.BomberRadius.GetFloat()) continue;
|
||||
@@ -416,7 +492,7 @@ class ExternalRpcPetPatch
|
||||
{
|
||||
if (!tg.IsModClient()) tg.KillFlash();
|
||||
var pos = pc.Pos();
|
||||
var dis = UnityEngine.Vector2.Distance(pos, tg.Pos());
|
||||
var dis = Vector2.Distance(pos, tg.Pos());
|
||||
|
||||
if (!tg.IsAlive() || Pelican.IsEaten(tg.PlayerId) || Medic.ProtectList.Contains(tg.PlayerId) || tg.inVent || tg.Is(CustomRoles.Pestilence)) continue;
|
||||
if (dis > Options.NukeRadius.GetFloat()) continue;
|
||||
@@ -469,8 +545,15 @@ class ExternalRpcPetPatch
|
||||
break;
|
||||
}
|
||||
|
||||
if (pc.Is(CustomRoles.Sniper) && Sniper.IsAim[pc.PlayerId]) return;
|
||||
if (pc.HasAbilityCD() || (pc.Is(CustomRoles.Sniper) && Sniper.IsAim[pc.PlayerId])) return;
|
||||
|
||||
pc.AddAbilityCD();
|
||||
}
|
||||
|
||||
public static PlayerControl SelectKillButtonTarget(PlayerControl pc)
|
||||
{
|
||||
var players = pc.GetPlayersInAbilityRangeSorted();
|
||||
var target = players.Count == 0 ? null : players[0];
|
||||
return target;
|
||||
}
|
||||
}
|
||||
+156
-130
@@ -692,6 +692,7 @@ class CheckMurderPatch
|
||||
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();
|
||||
@@ -1425,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;
|
||||
@@ -1946,6 +1947,7 @@ class ReportDeadBodyPatch
|
||||
{
|
||||
Damocles.OnReport();
|
||||
}
|
||||
Damocles.OnMeetingStart();
|
||||
|
||||
if (player.Is(CustomRoles.Stressed))
|
||||
{
|
||||
@@ -2018,7 +2020,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;
|
||||
}
|
||||
@@ -2026,18 +2028,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);
|
||||
}
|
||||
@@ -2045,17 +2048,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); });
|
||||
@@ -2073,12 +2076,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);
|
||||
@@ -2088,11 +2092,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");
|
||||
}
|
||||
|
||||
@@ -2123,14 +2124,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:
|
||||
@@ -2217,13 +2218,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))
|
||||
{
|
||||
@@ -2237,22 +2238,24 @@ 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() || !player.IsAlive())
|
||||
{
|
||||
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 (!lowLoad)
|
||||
{
|
||||
YinYanger.OnFixedUpdate();
|
||||
Duellist.OnFixedUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
if (!lowLoad)
|
||||
{
|
||||
YinYanger.OnFixedUpdate();
|
||||
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())
|
||||
{
|
||||
@@ -2266,13 +2269,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);
|
||||
@@ -2285,53 +2288,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
|
||||
{
|
||||
@@ -2340,13 +2343,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");
|
||||
}
|
||||
@@ -2356,31 +2359,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);
|
||||
@@ -2396,13 +2399,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");
|
||||
}
|
||||
@@ -2411,18 +2414,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);
|
||||
@@ -2432,17 +2435,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
|
||||
@@ -2457,44 +2460,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();
|
||||
@@ -2502,33 +2505,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:
|
||||
@@ -2576,41 +2579,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);
|
||||
@@ -2619,15 +2622,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);
|
||||
}
|
||||
@@ -2678,7 +2681,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>";
|
||||
@@ -2690,11 +2693,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;
|
||||
@@ -3017,8 +3020,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
|
||||
@@ -3778,3 +3780,27 @@ class PlayerControlSetRolePatch
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.SetRole))]
|
||||
class PlayerControlLocalSetRolePatch
|
||||
{
|
||||
public static void Postfix(PlayerControl __instance, [HarmonyArgument(0)] RoleTypes role)
|
||||
{
|
||||
if (!AmongUsClient.Instance.AmHost && !GameStates.IsModHost)
|
||||
{
|
||||
var moddedRole = role switch
|
||||
{
|
||||
RoleTypes.Impostor => CustomRoles.ImpostorTOHE,
|
||||
RoleTypes.Shapeshifter => CustomRoles.ShapeshifterTOHE,
|
||||
RoleTypes.Crewmate => CustomRoles.CrewmateTOHE,
|
||||
RoleTypes.Engineer => CustomRoles.EngineerTOHE,
|
||||
RoleTypes.Scientist => CustomRoles.ScientistTOHE,
|
||||
_ => CustomRoles.NotAssigned,
|
||||
};
|
||||
if (moddedRole != CustomRoles.NotAssigned)
|
||||
{
|
||||
Main.PlayerStates[__instance.PlayerId].SetMainRole(moddedRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ using AmongUs.GameOptions;
|
||||
using HarmonyLib;
|
||||
using Hazel;
|
||||
using InnerNet;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using TOHE.Modules;
|
||||
using TOHE.Roles.Crewmate;
|
||||
@@ -147,6 +146,7 @@ class OnPlayerLeftPatch
|
||||
Main.PlayerStates[data.Character.PlayerId].deathReason = PlayerState.DeathReason.Disconnected;
|
||||
Main.PlayerStates[data.Character.PlayerId].SetDead();
|
||||
}
|
||||
NameNotifyManager.Notice.Remove(data.Character.PlayerId);
|
||||
AntiBlackout.OnDisconnect(data.Character.Data);
|
||||
PlayerGameOptionsSender.RemoveSender(data.Character);
|
||||
}
|
||||
@@ -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,5 +1,4 @@
|
||||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TOHE.Patches;
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ internal class ChangeRoleSettings
|
||||
Main.InfectedBodies = [];
|
||||
Main.VirusNotify = [];
|
||||
Main.CrewpostorTasksDone = [];
|
||||
Main.DontCancelVoteList = [];
|
||||
|
||||
Main.LastEnteredVent = [];
|
||||
Main.LastEnteredVentLocation = [];
|
||||
@@ -478,6 +479,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 +578,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)
|
||||
{
|
||||
@@ -1182,7 +1186,7 @@ internal class SelectRolesPatch
|
||||
}
|
||||
|
||||
// Added players with unclassified roles to the list of players who require ResetCam.
|
||||
Main.ResetCamPlayerList.AddRange(Main.AllPlayerControls.Where(p => p.GetCustomRole() is CustomRoles.Arsonist or CustomRoles.Revolutionist or CustomRoles.Sidekick or CustomRoles.KB_Normal or CustomRoles.Killer or CustomRoles.Tasker or CustomRoles.Witness or CustomRoles.Innocent).Select(p => p.PlayerId));
|
||||
Main.ResetCamPlayerList.AddRange(Main.AllPlayerControls.Where(p => p.GetCustomRole() is CustomRoles.Arsonist or CustomRoles.Revolutionist or CustomRoles.Sidekick or CustomRoles.KB_Normal or CustomRoles.Killer or CustomRoles.Tasker or CustomRoles.Innocent || (p.Is(CustomRoles.Witness) && (!Options.UsePets.GetBool() || Options.WitnessUsePet.GetBool()))).Select(p => p.PlayerId));
|
||||
Utils.CountAlivePlayers(true);
|
||||
Utils.SyncAllSettings();
|
||||
SetColorPatch.IsAntiGlitchDisabled = false;
|
||||
@@ -1201,7 +1205,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 +1269,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);
|
||||
|
||||
@@ -75,6 +75,8 @@ curtsyboth#4114,1f9bbee79,龙傲天》//MalumMenu
|
||||
shyfortune#7692,526f950da,B站日常无语的无语君 //AUM
|
||||
0a4f7e294,Melani //no friendcode hacker
|
||||
sprysign#5596,064c15bb6,Onion
|
||||
musksolid#9543,troutdusky#6471,a9b3569f5,c40cfe547,caf7d691c,covid20 //Spoofed MalumMenu
|
||||
errantlug#6514,79f0cbe07,Kerbpoetic //AUM
|
||||
|
||||
## Griefer
|
||||
setmolar#4374,藏族顶针
|
||||
|
||||
+23
-5
@@ -1223,6 +1223,17 @@
|
||||
"ArsonistMinPlayersToIgnite","","Minimum Doused Players required to Ignite","","",""
|
||||
"ArsonistMaxPlayersToIgnite","","Maximum Amount of Doused Players at once","","",""
|
||||
|
||||
"## Remaining Killers Text / Confirm Ejections Text"
|
||||
"RemainingText.Prefix.SingleImp","","There is","","",""
|
||||
"RemainingText.Prefix.PluralImp","","There are","","",""
|
||||
"RemainingText.ImpSingle","","Impostor","","",""
|
||||
"RemainingText.ImpPlural","","Impostors","","",""
|
||||
"RemainingText.NKSingle","","Neutral Killer","","",""
|
||||
"RemainingText.NKPlural","","Neutral Killers","","",""
|
||||
"RemainingText.Suffix","","left","","",""
|
||||
"RemainingText.EjectionSuffix.NKSingle","","remains.","","",""
|
||||
"RemainingText.EjectionSuffix.NKPlural","","remain.","","",""
|
||||
|
||||
"## 详细设定 / Advanced Settings"
|
||||
"Cooldown","冷却时间","Cooldown","Откат","冷卻時間","冷却时间"
|
||||
"KillCooldown","击杀冷却时间","Kill Cooldown","Откат убийства","殺人冷卻時間","击杀冷却时间"
|
||||
@@ -1439,9 +1450,11 @@
|
||||
"NotifyGodAlive","如果神存活则在会议上通知所有人","Inform players at meetings that God is still alive","Сообщать игрокам на встрече что Дьявол ещё жив","若神存活則在會議上通知所有人","如果神存活则在会议上通知所有人"
|
||||
"TransporterTeleportMax","传送次数上限","Max number of teleports","Максимальное колличество телепортов","傳送次數上限","传送次数上限"
|
||||
"TriggerKill","击杀","Kill","Убийство","殺死","击杀"
|
||||
"UsePetInsteadOfKillButton","","Use Pet Button As Kill Button","","",""
|
||||
"UsePets","","Use Pet button instead of Vent / Shapeshift","","",""
|
||||
"PetToAssign","","Pet to Assign to Everyone","","",""
|
||||
"UseVoteCancelling","","Use Vote Cancelling Method instead of Commands","","",""
|
||||
"UseVoteCancellingAfterVote","","Can Vote Normally After Using Ability (Vote)","","",""
|
||||
"AbilityOnCooldown","","<color=#ffff00>Ability on cooldown!</color>","","",""
|
||||
"KillCooldownOnStrangle","","Kill Cooldown after Strangling","","",""
|
||||
"CDPT","","<color=#00ffa5>CD:</color> <color=#ffffff><b>{0}</b>s</color>","","",""
|
||||
@@ -2530,7 +2543,7 @@
|
||||
"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","","",""
|
||||
@@ -2859,19 +2872,19 @@
|
||||
"EnigmaClueLevel2","","The Killer's Level is below 50!","","",""
|
||||
"EnigmaClueLevel3","","The Killer's Level is between {0} and {1}!","","",""
|
||||
"EnigmaClueLevel4","","The Killer's Level is {0}!","","",""
|
||||
"EnigmaClueFriendCode","","The Killer's Friendcode is {0}!","","",""
|
||||
"EnigmaClueFriendCode","","The Killer's Friend Code is {0}!","","",""
|
||||
"EnigmaClueHatTitle","","Enigma Hat Clue!","","",""
|
||||
"EnigmaClueVisorTitle","","Enigma Visor Clue!","","",""
|
||||
"EnigmaClueSkinTitle","","Enigma Skin Clue!","","",""
|
||||
"EnigmaCluePetTitle","","Enigma Pet Clue!","","",""
|
||||
"EnigmaClueNameTitle","","Enigma Name Clue!","","",""
|
||||
"EnigmaClueNameLengthTitle","","Enigma Name lenght Clue!","","",""
|
||||
"EnigmaClueNameLengthTitle","","Enigma Name Length Clue!","","",""
|
||||
"EnigmaClueColorTitle","","Enigma Color Clue!","","",""
|
||||
"EnigmaClueLocationTitle","","Enigma Location Clue!","","",""
|
||||
"EnigmaClueStatusTitle","","Enigma Status Clue!","","",""
|
||||
"EnigmaClueRoleTitle","","Enigma Role Clue!","","",""
|
||||
"EnigmaClueLevelTitle","","Enigma Level Clue!","","",""
|
||||
"EnigmaClueFriendCodeTitle","","Enigma Friendcode Clue!","","",""
|
||||
"EnigmaClueFriendCodeTitle","","Enigma Friend Code Clue!","","",""
|
||||
"EnigmaClueTitle","","Enigma Clue!","","",""
|
||||
|
||||
"## Plague Doctor"
|
||||
@@ -3033,6 +3046,10 @@
|
||||
"WeaponMasterInfoLong","","(Neutral):\nAs the Weapon Master, you can cycle between your weapons by petting your pet/calling a sabotage.\n\nThe Sword weapon is a normal kill method.\n\nThe Axe weapon kills everyone in a certain radius when you make a kill. You have a higher kill cooldown while using this weapon.\n\nThe Lance weapon sets your kill range to the maximum, and you don't lunge toward your kills. You can't vent while using this weapon.\n\nWhile using your Shield, you can survive an attack once. You can't kill while using your shield.","","",""
|
||||
"WMRadius","","Axe Mode Death Radius","","",""
|
||||
"WMShieldAlreadyUsed","","Your shield was already used","","",""
|
||||
"Sword","","Sword","","",""
|
||||
"Axe","","Axe","","",""
|
||||
"Lance","","Lance","","",""
|
||||
"Shield","","Shield","","",""
|
||||
|
||||
"## Eclipse"
|
||||
"Eclipse","","Eclipse","","",""
|
||||
@@ -3316,6 +3333,7 @@
|
||||
"FFA_TargetIsShielded","","<color=#ffff00>The player you tried to kill is shielded!</color>","","",""
|
||||
"FFA_ShieldIsOneTimeUse","","Shields break after 1 kill attempt","","",""
|
||||
"FFA_ShieldBroken","","<color=#ffff00>Someone tried to kill you, your shield is now broken!</color>","","",""
|
||||
"FFA_ChatDuringGame","","Chat During Game","","",""
|
||||
"FFAChatMessageNotify","","[<color=#00ffff>Chat</color>] <color=#00ffa5>{0}:</color> {1}","","",""
|
||||
"Killer","","FREE FOR ALL","","",""
|
||||
"KillerInfo","","Kill Everyone to Win","","",""
|
||||
@@ -3376,7 +3394,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)
|
||||
|
||||
@@ -54,7 +54,12 @@ namespace TOHE.Roles.AddOns.Impostor
|
||||
|
||||
public static void Update(PlayerControl pc)
|
||||
{
|
||||
if (lastUpdate >= GetTimeStamp() || !GameStates.IsInTask || !pc.IsAlive()) return;
|
||||
if (lastUpdate >= GetTimeStamp() || !GameStates.IsInTask || pc == null) return;
|
||||
if (!pc.IsAlive())
|
||||
{
|
||||
Main.PlayerStates[pc.PlayerId].RemoveSubRole(CustomRoles.Damocles);
|
||||
return;
|
||||
}
|
||||
lastUpdate = GetTimeStamp();
|
||||
|
||||
Timer--;
|
||||
@@ -65,7 +70,7 @@ namespace TOHE.Roles.AddOns.Impostor
|
||||
pc.Suicide();
|
||||
}
|
||||
|
||||
if (pc.IsModClient() && pc.PlayerId != 0) SendRPC();
|
||||
if (pc.IsNonHostModClient()) SendRPC();
|
||||
NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
||||
}
|
||||
|
||||
@@ -111,10 +116,14 @@ namespace TOHE.Roles.AddOns.Impostor
|
||||
PreviouslyEnteredVents.Clear();
|
||||
|
||||
Timer += TimeAfterMeeting;
|
||||
Timer += 9;
|
||||
countRepairSabotage = true;
|
||||
}
|
||||
|
||||
public static void OnMeetingStart()
|
||||
{
|
||||
Timer += 9;
|
||||
}
|
||||
|
||||
public static void OnCrewmateEjected()
|
||||
{
|
||||
Timer = (int)Math.Round(Timer * 1.3);
|
||||
@@ -142,4 +151,4 @@ namespace TOHE.Roles.AddOns.Impostor
|
||||
|
||||
public static string GetProgressText() => string.Format(GetString("DamoclesTimeLeft"), Timer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,14 +13,19 @@ public static class Admirer
|
||||
|
||||
public static OptionItem AdmireCooldown;
|
||||
public static OptionItem KnowTargetRole;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static int AdmireLimit;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
SetupSingleRoleOptions(Id, TabGroup.CrewmateRoles, CustomRoles.Admirer, 1);
|
||||
AdmireCooldown = FloatOptionItem.Create(Id + 10, "AdmireCooldown", new(1f, 180f, 1f), 15f, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Admirer])
|
||||
AdmireCooldown = FloatOptionItem.Create(Id + 10, "AdmireCooldown", new(1f, 180f, 1f), 15f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Admirer])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
KnowTargetRole = BooleanOptionItem.Create(Id + 13, "AdmirerKnowTargetRole", true, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Admirer]);
|
||||
KnowTargetRole = BooleanOptionItem.Create(Id + 13, "AdmirerKnowTargetRole", true, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Admirer]);
|
||||
UsePet = CreatePetUseSetting(Id + 11, CustomRoles.Admirer);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -32,7 +37,7 @@ public static class Admirer
|
||||
playerIdList.Add(playerId);
|
||||
AdmireLimit = 1;
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
+11
-9
@@ -2,7 +2,6 @@ namespace TOHE.Roles.Crewmate
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using static TOHE.Options;
|
||||
@@ -18,16 +17,21 @@ namespace TOHE.Roles.Crewmate
|
||||
public static OptionItem AidDur;
|
||||
public static OptionItem AidCD;
|
||||
public static OptionItem UseLimitOpt;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
SetupRoleOptions(Id, TabGroup.CrewmateRoles, CustomRoles.Aid);
|
||||
AidCD = FloatOptionItem.Create(Id + 10, "AidCD", new(0f, 60f, 1f), 15f, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Aid])
|
||||
AidCD = FloatOptionItem.Create(Id + 10, "AidCD", new(0f, 60f, 1f), 15f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Aid])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
AidDur = FloatOptionItem.Create(Id + 11, "AidDur", new(0f, 60f, 1f), 10f, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Aid])
|
||||
AidDur = FloatOptionItem.Create(Id + 11, "AidDur", new(0f, 60f, 1f), 10f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Aid])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
UseLimitOpt = IntegerOptionItem.Create(Id + 12, "AbilityUseLimit", new(1, 20, 1), 5, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Aid])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
UseLimitOpt = IntegerOptionItem.Create(Id + 12, "AbilityUseLimit", new(1, 20, 1), 5, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Aid])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
UsePet = CreatePetUseSetting(Id + 13, CustomRoles.Aid);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -40,7 +44,7 @@ namespace TOHE.Roles.Crewmate
|
||||
playerIdList.Add(playerId);
|
||||
UseLimit.Add(playerId, UseLimitOpt.GetInt());
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
@@ -66,9 +70,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;
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace TOHE.Roles.Crewmate
|
||||
private static OptionItem SeeKillCount;
|
||||
private static OptionItem SeeVentCount;
|
||||
private static OptionItem SeeRoleBasis;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
private static readonly Dictionary<string, string> replacementDict = new() { { "Analyze", ColorString(GetRoleColor(CustomRoles.Analyzer), "Analyze") } };
|
||||
|
||||
@@ -45,6 +46,7 @@ namespace TOHE.Roles.Crewmate
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Analyzer]);
|
||||
SeeRoleBasis = BooleanOptionItem.Create(Id + 15, "AnalyzerSeeRoleBasis", true, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Analyzer]);
|
||||
UsePet = CreatePetUseSetting(Id + 16, CustomRoles.Analyzer);
|
||||
}
|
||||
|
||||
public static bool CanUseKillButton => CurrentTarget.ID == byte.MaxValue && UseLimit > 0;
|
||||
@@ -85,7 +87,7 @@ namespace TOHE.Roles.Crewmate
|
||||
playerId = id;
|
||||
UseLimit = UseLimitOpt.GetInt();
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(id))
|
||||
Main.ResetCamPlayerList.Add(id);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
{
|
||||
using Hazel;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using static TOHE.Options;
|
||||
using static TOHE.Translator;
|
||||
@@ -163,7 +162,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())
|
||||
|
||||
@@ -16,6 +16,7 @@ public static class Cleanser
|
||||
|
||||
public static OptionItem CleanserUsesOpt;
|
||||
public static OptionItem CleansedCanGetAddon;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
@@ -23,7 +24,7 @@ public static class Cleanser
|
||||
CleanserUsesOpt = IntegerOptionItem.Create(Id + 10, "MaxCleanserUses", new(1, 14, 1), 3, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Cleanser])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
CleansedCanGetAddon = BooleanOptionItem.Create(Id + 11, "CleansedCanGetAddon", false, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Cleanser]);
|
||||
|
||||
CancelVote = CreateVoteCancellingUseSetting(Id + 12, CustomRoles.Cleanser, TabGroup.CrewmateRoles);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -73,18 +74,18 @@ public static class Cleanser
|
||||
CleanserUses.Add(CleanserId, 0);
|
||||
}
|
||||
|
||||
public static void OnVote(PlayerControl voter, PlayerControl target)
|
||||
public static bool OnVote(PlayerControl voter, PlayerControl target)
|
||||
{
|
||||
if (!voter.Is(CustomRoles.Cleanser)) return;
|
||||
if (DidVote[voter.PlayerId]) return;
|
||||
if (!voter.Is(CustomRoles.Cleanser)) return false;
|
||||
if (DidVote[voter.PlayerId] || Main.DontCancelVoteList.Contains(voter.PlayerId)) return false;
|
||||
DidVote[voter.PlayerId] = true;
|
||||
if (CleanserUses[voter.PlayerId] >= CleanserUsesOpt.GetInt()) return;
|
||||
if (CleanserUses[voter.PlayerId] >= CleanserUsesOpt.GetInt()) return false;
|
||||
if (target.PlayerId == voter.PlayerId)
|
||||
{
|
||||
Utils.SendMessage(GetString("CleanserRemoveSelf"), voter.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Cleanser), GetString("CleanserTitle")));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if (CleanserTarget[voter.PlayerId] != byte.MaxValue) return;
|
||||
if (CleanserTarget[voter.PlayerId] != byte.MaxValue) return false;
|
||||
|
||||
CleanserUses[voter.PlayerId]++;
|
||||
CleanserTarget[voter.PlayerId] = target.PlayerId;
|
||||
@@ -92,6 +93,9 @@ public static class Cleanser
|
||||
CleansedPlayers.Add(target.PlayerId);
|
||||
Utils.SendMessage(string.Format(GetString("CleanserRemovedRole"), target.GetRealName()), voter.PlayerId, title: Utils.ColorString(Utils.GetRoleColor(CustomRoles.Cleanser), GetString("CleanserTitle")));
|
||||
SendRPC(voter.PlayerId);
|
||||
|
||||
Main.DontCancelVoteList.Add(voter.PlayerId);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void AfterMeetingTasks()
|
||||
|
||||
@@ -17,6 +17,7 @@ public static class CopyCat
|
||||
public static OptionItem CanKill;
|
||||
public static OptionItem CopyCrewVar;
|
||||
public static OptionItem MiscopyLimitOpt;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
@@ -27,6 +28,7 @@ public static class CopyCat
|
||||
CopyCrewVar = BooleanOptionItem.Create(Id + 13, "CopyCrewVar", true, TabGroup.OtherRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.CopyCat]);
|
||||
MiscopyLimitOpt = IntegerOptionItem.Create(Id + 12, "CopyCatMiscopyLimit", new(0, 14, 1), 2, TabGroup.OtherRoles, false).SetParent(CanKill)
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
UsePet = CreatePetUseSetting(Id + 14, CustomRoles.CopyCat);
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
@@ -41,7 +43,8 @@ public static class CopyCat
|
||||
playerIdList.Add(playerId);
|
||||
CurrentKillCooldown.Add(playerId, KillCooldown.GetFloat());
|
||||
MiscopyLimit.TryAdd(playerId, MiscopyLimitOpt.GetInt());
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -7,10 +7,13 @@ public static class Crusader
|
||||
{
|
||||
private static readonly int Id = 20050;
|
||||
private static List<byte> playerIdList = [];
|
||||
public static Dictionary<byte, int> CrusaderLimit = [];
|
||||
|
||||
public static OptionItem SkillLimitOpt;
|
||||
public static OptionItem SkillCooldown;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static Dictionary<byte, float> CurrentKillCooldown = [];
|
||||
public static Dictionary<byte, int> CrusaderLimit = [];
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
@@ -19,6 +22,7 @@ public static class Crusader
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
SkillLimitOpt = IntegerOptionItem.Create(Id + 11, "CrusaderSkillLimit", new(1, 10, 1), 2, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Crusader])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
UsePet = Options.CreatePetUseSetting(Id + 12, CustomRoles.Crusader);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -31,8 +35,7 @@ public static class Crusader
|
||||
CrusaderLimit.TryAdd(playerId, SkillLimitOpt.GetInt());
|
||||
CurrentKillCooldown.Add(playerId, SkillCooldown.GetFloat());
|
||||
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (Options.UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ public static class Deputy
|
||||
public static OptionItem HandcuffMax;
|
||||
public static OptionItem DeputyHandcuffCDForTarget;
|
||||
private static OptionItem DeputyHandcuffDelay;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static int HandcuffLimit;
|
||||
|
||||
@@ -29,6 +30,7 @@ public static class Deputy
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
DeputyHandcuffDelay = IntegerOptionItem.Create(Id + 11, "DeputyHandcuffDelay", new(0, 20, 1), 5, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Deputy])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
UsePet = CreatePetUseSetting(Id + 13, CustomRoles.Deputy);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -40,7 +42,7 @@ public static class Deputy
|
||||
playerIdList.Add(playerId);
|
||||
HandcuffLimit = HandcuffMax.GetInt();
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ public static class Divinator
|
||||
public static OptionItem HideVote;
|
||||
public static OptionItem ShowSpecificRole;
|
||||
public static OptionItem AbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
public static List<byte> didVote = [];
|
||||
public static Dictionary<byte, float> CheckLimit = [];
|
||||
@@ -29,6 +30,7 @@ public static class Divinator
|
||||
HideVote = BooleanOptionItem.Create(Id + 14, "DivinatorHideVote", false, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Divinator]);
|
||||
AbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 15, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 1f, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Divinator])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
CancelVote = CreateVoteCancellingUseSetting(Id + 11, CustomRoles.Divinator, TabGroup.CrewmateRoles);
|
||||
OverrideTasksData.Create(Id + 21, TabGroup.CrewmateRoles, CustomRoles.Divinator);
|
||||
}
|
||||
public static void Init()
|
||||
@@ -58,16 +60,16 @@ public static class Divinator
|
||||
float uses = reader.ReadSingle();
|
||||
CheckLimit[playerId] = uses;
|
||||
}
|
||||
public static void OnVote(PlayerControl player, PlayerControl target)
|
||||
public static bool OnVote(PlayerControl player, PlayerControl target)
|
||||
{
|
||||
if (player == null || target == null) return;
|
||||
if (didVote.Contains(player.PlayerId)) return;
|
||||
if (player == null || target == null) return false;
|
||||
if (didVote.Contains(player.PlayerId) || Main.DontCancelVoteList.Contains(player.PlayerId)) return false;
|
||||
didVote.Add(player.PlayerId);
|
||||
|
||||
if (CheckLimit[player.PlayerId] < 1)
|
||||
{
|
||||
Utils.SendMessage(GetString("DivinatorCheckReachLimit"), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Divinator), GetString("DivinatorCheckMsgTitle")));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
CheckLimit[player.PlayerId] -= 1;
|
||||
@@ -76,7 +78,7 @@ public static class Divinator
|
||||
if (player.PlayerId == target.PlayerId)
|
||||
{
|
||||
Utils.SendMessage(GetString("DivinatorCheckSelfMsg") + "\n\n" + string.Format(GetString("DivinatorCheckLimit"), CheckLimit[player.PlayerId]), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Divinator), GetString("DivinatorCheckMsgTitle")));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
string msg;
|
||||
@@ -548,5 +550,8 @@ public static class Divinator
|
||||
}*/
|
||||
|
||||
Utils.SendMessage(GetString("DivinatorCheck") + "\n" + msg + "\n\n" + string.Format(GetString("DivinatorCheckLimit"), CheckLimit[player.PlayerId]), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Divinator), GetString("DivinatorCheckMsgTitle")));
|
||||
|
||||
Main.DontCancelVoteList.Add(player.PlayerId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ namespace TOHE.Roles.Crewmate
|
||||
|
||||
private static OptionItem CD;
|
||||
private static OptionItem UseLimit;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static int DeliverLimit;
|
||||
|
||||
@@ -24,6 +25,7 @@ namespace TOHE.Roles.Crewmate
|
||||
UseLimit = IntegerOptionItem.Create(Id + 12, "AbilityUseLimit", new(1, 20, 1), 5, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.DonutDelivery])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
UsePet = CreatePetUseSetting(Id + 13, CustomRoles.DonutDelivery);
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
@@ -39,7 +41,7 @@ namespace TOHE.Roles.Crewmate
|
||||
|
||||
DeliverLimit = UseLimit.GetInt();
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace TOHE.Roles.Crewmate
|
||||
|
||||
private static OptionItem CD;
|
||||
private static OptionItem UseLimit;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static int BlockLimit;
|
||||
|
||||
@@ -26,6 +27,7 @@ namespace TOHE.Roles.Crewmate
|
||||
UseLimit = IntegerOptionItem.Create(Id + 11, "AbilityUseLimit", new(1, 20, 1), 3, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Escort])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
UsePet = CreatePetUseSetting(Id + 12, CustomRoles.Escort);
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
@@ -39,7 +41,7 @@ namespace TOHE.Roles.Crewmate
|
||||
|
||||
BlockLimit = UseLimit.GetInt();
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace TOHE.Roles.Crewmate
|
||||
public static OptionItem FarseerCooldown;
|
||||
public static OptionItem FarseerRevealTime;
|
||||
public static OptionItem Vision;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
private static readonly System.Collections.Generic.List<CustomRoles> randomRolesForTrickster =
|
||||
[
|
||||
@@ -109,6 +110,7 @@ namespace TOHE.Roles.Crewmate
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
Vision = FloatOptionItem.Create(Id + 12, "FarseerVision", new(0f, 1f, 0.05f), 0.25f, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Farseer])
|
||||
.SetValueFormat(OptionFormat.Multiplier);
|
||||
UsePet = CreatePetUseSetting(Id + 13, CustomRoles.Farseer);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -117,7 +119,8 @@ namespace TOHE.Roles.Crewmate
|
||||
public static void Add(byte playerId)
|
||||
{
|
||||
isEnable = true;
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
@@ -145,7 +148,8 @@ namespace TOHE.Roles.Crewmate
|
||||
}
|
||||
else if (ar_time >= FarseerRevealTime.GetFloat())//時間以上一緒にいて塗れた時
|
||||
{
|
||||
player.SetKillCooldown();
|
||||
if (UsePets.GetBool()) player.AddKCDAsAbilityCD();
|
||||
else player.SetKillCooldown();
|
||||
Main.FarseerTimer.Remove(player.PlayerId);//塗が完了したのでDictionaryから削除
|
||||
Main.isRevealed[(player.PlayerId, ar_target.PlayerId)] = true;//塗り完了
|
||||
player.RpcSetRevealtPlayer(ar_target, true);
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace TOHE.Roles.Crewmate
|
||||
private static OptionItem CD;
|
||||
private static OptionItem AdditionalSpeed;
|
||||
private static OptionItem UseLimitOpt;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static List<byte> IncreasedSpeedPlayerList = [];
|
||||
|
||||
@@ -28,6 +29,7 @@ namespace TOHE.Roles.Crewmate
|
||||
UseLimitOpt = IntegerOptionItem.Create(Id + 7, "AbilityUseLimit", new(1, 14, 1), 3, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Gaulois])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
UsePet = CreatePetUseSetting(Id + 8, CustomRoles.Gaulois);
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
@@ -41,6 +43,10 @@ namespace TOHE.Roles.Crewmate
|
||||
{
|
||||
playerIdList.Add(playerId);
|
||||
UseLimit.Add(playerId, UseLimitOpt.GetInt());
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
public static bool IsEnable => playerIdList.Count > 0;
|
||||
@@ -91,6 +97,7 @@ namespace TOHE.Roles.Crewmate
|
||||
IncreasedSpeedPlayerList.Add(target.PlayerId);
|
||||
UseLimit[killer.PlayerId]--;
|
||||
|
||||
killer.SetKillCooldown();
|
||||
SendRPC(killer.PlayerId);
|
||||
SendRPCAddPlayerToList(target.PlayerId);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ public static class Jailor
|
||||
|
||||
public static OptionItem JailCooldown;
|
||||
public static OptionItem notifyJailedOnMeeting;
|
||||
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
@@ -24,6 +24,7 @@ public static class Jailor
|
||||
JailCooldown = FloatOptionItem.Create(Id + 10, "JailorJailCooldown", new(0f, 60f, 1f), 15f, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Jailor])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
notifyJailedOnMeeting = BooleanOptionItem.Create(Id + 18, "notifyJailedOnMeeting", true, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Jailor]);
|
||||
UsePet = CreatePetUseSetting(Id + 11, CustomRoles.Jailor);
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
@@ -41,7 +42,7 @@ public static class Jailor
|
||||
JailorHasExe.Add(playerId, false);
|
||||
JailorDidVote.Add(playerId, false);
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ public static class Medic
|
||||
private static OptionItem ResetCooldown;
|
||||
public static OptionItem GuesserIgnoreShield;
|
||||
private static OptionItem AmountOfShields;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static readonly string[] MedicWhoCanSeeProtectName =
|
||||
[
|
||||
@@ -65,6 +66,7 @@ public static class Medic
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Medic]);
|
||||
AmountOfShields = IntegerOptionItem.Create(Id + 34, "MedicAmountOfShields", new(1, 14, 1), 1, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Medic]);
|
||||
UsePet = Options.CreatePetUseSetting(Id + 36, CustomRoles.Medic);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -81,7 +83,7 @@ public static class Medic
|
||||
|
||||
Logger.Info($"{Utils.GetPlayerById(playerId)?.GetNameWithRole().RemoveHtmlTags()} : {ProtectLimit[playerId]} shields left", "Medicaler");
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (Options.UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ public static class Monarch
|
||||
|
||||
public static OptionItem KnightCooldown;
|
||||
public static OptionItem KnightMax;
|
||||
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static int KnightLimit;
|
||||
|
||||
@@ -24,6 +24,7 @@ public static class Monarch
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
KnightMax = IntegerOptionItem.Create(Id + 12, "MonarchKnightMax", new(1, 15, 1), 2, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Monarch])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
UsePet = CreatePetUseSetting(Id + 11, CustomRoles.Monarch);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -35,7 +36,7 @@ public static class Monarch
|
||||
playerIdList.Add(playerId);
|
||||
KnightLimit = KnightMax.GetInt();
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ internal static class NiceEraser
|
||||
|
||||
private static OptionItem EraseLimitOpt;
|
||||
public static OptionItem HideVote;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
private static List<byte> didVote = [];
|
||||
public static Dictionary<byte, int> EraseLimit = [];
|
||||
@@ -23,6 +24,7 @@ internal static class NiceEraser
|
||||
EraseLimitOpt = IntegerOptionItem.Create(Id + 2, "EraseLimit", new(1, 15, 1), 1, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.NiceEraser])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
HideVote = BooleanOptionItem.Create(Id + 3, "NiceEraserHideVote", false, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.NiceEraser]);
|
||||
CancelVote = Options.CreateVoteCancellingUseSetting(Id + 4, CustomRoles.NiceEraser, TabGroup.CrewmateRoles);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -55,24 +57,24 @@ internal static class NiceEraser
|
||||
}
|
||||
public static string GetProgressText(byte playerId) => Utils.ColorString(EraseLimit[playerId] > 0 ? Utils.GetRoleColor(CustomRoles.NiceEraser) : Color.gray, EraseLimit.TryGetValue(playerId, out var x) ? $"({x})" : "Invalid");
|
||||
|
||||
public static void OnVote(PlayerControl player, PlayerControl target)
|
||||
public static bool OnVote(PlayerControl player, PlayerControl target)
|
||||
{
|
||||
if (player == null || target == null) return;
|
||||
if (didVote.Contains(player.PlayerId)) return;
|
||||
if (player == null || target == null) return false;
|
||||
if (didVote.Contains(player.PlayerId) || Main.DontCancelVoteList.Contains(player.PlayerId)) return false;
|
||||
didVote.Add(player.PlayerId);
|
||||
|
||||
if (EraseLimit.ContainsKey(player.PlayerId) && EraseLimit[player.PlayerId] < 1) return;
|
||||
if (EraseLimit.ContainsKey(player.PlayerId) && EraseLimit[player.PlayerId] < 1) return false;
|
||||
|
||||
if (target.PlayerId == player.PlayerId)
|
||||
{
|
||||
Utils.SendMessage(GetString("EraserEraseSelf"), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.NiceEraser), GetString("EraserEraseMsgTitle")));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (target.GetCustomRole().IsNeutral())
|
||||
{
|
||||
Utils.SendMessage(string.Format(GetString("EraserEraseNeutralNotice"), target.GetRealName()), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.NiceEraser), GetString("EraserEraseMsgTitle")));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (EraseLimit.ContainsKey(player.PlayerId)) EraseLimit[player.PlayerId]--;
|
||||
@@ -83,7 +85,10 @@ internal static class NiceEraser
|
||||
|
||||
Utils.SendMessage(string.Format(GetString("EraserEraseNotice"), target.GetRealName()), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.NiceEraser), GetString("EraserEraseMsgTitle")));
|
||||
|
||||
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: target);
|
||||
if (GameStates.IsInTask) Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: target);
|
||||
|
||||
Main.DontCancelVoteList.Add(player.PlayerId);
|
||||
return true;
|
||||
}
|
||||
public static void OnReportDeadBody()
|
||||
{
|
||||
|
||||
+22
-18
@@ -15,6 +15,7 @@ public static class Oracle
|
||||
public static OptionItem HideVote;
|
||||
public static OptionItem FailChance;
|
||||
public static OptionItem OracleAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
public static List<byte> didVote = [];
|
||||
public static Dictionary<byte, float> CheckLimit = [];
|
||||
@@ -33,6 +34,7 @@ public static class Oracle
|
||||
OracleAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 14, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Oracle])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
CancelVote = CreateVoteCancellingUseSetting(Id + 11, CustomRoles.Oracle, TabGroup.CrewmateRoles);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -61,16 +63,16 @@ public static class Oracle
|
||||
float uses = reader.ReadSingle();
|
||||
CheckLimit[playerId] = uses;
|
||||
}
|
||||
public static void OnVote(PlayerControl player, PlayerControl target)
|
||||
public static bool OnVote(PlayerControl player, PlayerControl target)
|
||||
{
|
||||
if (player == null || target == null) return;
|
||||
if (didVote.Contains(player.PlayerId)) return;
|
||||
if (player == null || target == null) return false;
|
||||
if (didVote.Contains(player.PlayerId) || Main.DontCancelVoteList.Contains(player.PlayerId)) return false;
|
||||
didVote.Add(player.PlayerId);
|
||||
|
||||
if (CheckLimit[player.PlayerId] < 1)
|
||||
{
|
||||
Utils.SendMessage(GetString("OracleCheckReachLimit"), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Oracle), GetString("OracleCheckMsgTitle")));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
CheckLimit[player.PlayerId] -= 1;
|
||||
@@ -79,7 +81,7 @@ public static class Oracle
|
||||
if (player.PlayerId == target.PlayerId)
|
||||
{
|
||||
Utils.SendMessage(GetString("OracleCheckSelfMsg") + "\n\n" + string.Format(GetString("OracleCheckLimit"), CheckLimit[player.PlayerId]), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Oracle), GetString("OracleCheckMsgTitle")));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
string text;
|
||||
@@ -94,20 +96,20 @@ public static class Oracle
|
||||
if (random_number_1 <= FailChance.GetInt())
|
||||
{
|
||||
int random_number_2 = IRandom.Instance.Next(1, 3);
|
||||
if (text == "Crew")
|
||||
switch (text)
|
||||
{
|
||||
if (random_number_2 == 1) text = "Neut";
|
||||
if (random_number_2 == 2) text = "Imp";
|
||||
}
|
||||
if (text == "Neut")
|
||||
{
|
||||
if (random_number_2 == 1) text = "Crew";
|
||||
if (random_number_2 == 2) text = "Imp";
|
||||
}
|
||||
if (text == "Imp")
|
||||
{
|
||||
if (random_number_2 == 1) text = "Neut";
|
||||
if (random_number_2 == 2) text = "Crew";
|
||||
case "Crew":
|
||||
if (random_number_2 == 1) text = "Neut";
|
||||
else if (random_number_2 == 2) text = "Imp";
|
||||
break;
|
||||
case "Neut":
|
||||
if (random_number_2 == 1) text = "Crew";
|
||||
if (random_number_2 == 2) text = "Imp";
|
||||
break;
|
||||
case "Imp":
|
||||
if (random_number_2 == 1) text = "Neut";
|
||||
if (random_number_2 == 2) text = "Crew";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,5 +118,7 @@ public static class Oracle
|
||||
|
||||
Utils.SendMessage(GetString("OracleCheck") + "\n" + msg + "\n\n" + string.Format(GetString("OracleCheckLimit"), CheckLimit[player.PlayerId]), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Oracle), GetString("OracleCheckMsgTitle")));
|
||||
|
||||
Main.DontCancelVoteList.Add(player.PlayerId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -17,15 +17,17 @@ namespace TOHE.Roles.Crewmate
|
||||
|
||||
public static OptionItem UseLimitOpt;
|
||||
public static OptionItem RicochetAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
SetupSingleRoleOptions(Id, TabGroup.CrewmateRoles, CustomRoles.Ricochet, 1);
|
||||
UseLimitOpt = IntegerOptionItem.Create(Id + 10, "AbilityUseLimit", new(0, 20, 1), 1, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Ricochet])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
RicochetAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 11, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.5f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Ricochet])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Ricochet])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
CancelVote = CreateVoteCancellingUseSetting(Id + 12, CustomRoles.Ricochet, TabGroup.CrewmateRoles);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -82,12 +84,9 @@ namespace TOHE.Roles.Crewmate
|
||||
|
||||
return true;
|
||||
}
|
||||
public static void OnVote(PlayerControl pc, PlayerControl target)
|
||||
public static bool OnVote(PlayerControl pc, PlayerControl target)
|
||||
{
|
||||
if (target == null) return;
|
||||
if (pc == null) return;
|
||||
if (pc.PlayerId == target.PlayerId) return;
|
||||
if (!pc.Is(CustomRoles.Ricochet)) return;
|
||||
if (target == null || pc == null || pc.PlayerId == target.PlayerId || !pc.Is(CustomRoles.Ricochet) || Main.DontCancelVoteList.Contains(pc.PlayerId)) return false;
|
||||
|
||||
if (UseLimit[pc.PlayerId] >= 1)
|
||||
{
|
||||
@@ -95,7 +94,10 @@ namespace TOHE.Roles.Crewmate
|
||||
ProtectAgainst = target.PlayerId;
|
||||
SendRPC(pc.PlayerId);
|
||||
SendRPCSyncTarget(ProtectAgainst);
|
||||
Main.DontCancelVoteList.Add(pc.PlayerId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static void OnReportDeadBody()
|
||||
{
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -30,6 +30,7 @@ public static class Sheriff
|
||||
public static OptionItem NonCrewCanKillCrew;
|
||||
public static OptionItem NonCrewCanKillImp;
|
||||
public static OptionItem NonCrewCanKillNeutral;
|
||||
public static OptionItem UsePet;
|
||||
public static Dictionary<CustomRoles, OptionItem> KillTargetOptions = [];
|
||||
public static Dictionary<byte, int> ShotLimit = [];
|
||||
public static Dictionary<byte, float> CurrentKillCooldown = [];
|
||||
@@ -63,6 +64,7 @@ public static class Sheriff
|
||||
NonCrewCanKillImp = BooleanOptionItem.Create(Id + 19, "SheriffMadCanKillImp", true, TabGroup.CrewmateRoles, false).SetParent(SetNonCrewCanKill);
|
||||
NonCrewCanKillCrew = BooleanOptionItem.Create(Id + 21, "SheriffMadCanKillCrew", true, TabGroup.CrewmateRoles, false).SetParent(SetNonCrewCanKill);
|
||||
NonCrewCanKillNeutral = BooleanOptionItem.Create(Id + 20, "SheriffMadCanKillNeutral", true, TabGroup.CrewmateRoles, false).SetParent(SetNonCrewCanKill);
|
||||
UsePet = Options.CreatePetUseSetting(Id + 29, CustomRoles.Sheriff);
|
||||
}
|
||||
public static void SetUpNeutralOptions(int Id)
|
||||
{
|
||||
@@ -94,7 +96,7 @@ public static class Sheriff
|
||||
ShotLimit.TryAdd(playerId, ShotLimitOpt.GetInt());
|
||||
Logger.Info($"{Utils.GetPlayerById(playerId)?.GetNameWithRole().RemoveHtmlTags()} : Shot Limit - {ShotLimit[playerId]}", "Sheriff");
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (Options.UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ namespace TOHE.Roles.Crewmate
|
||||
using Hazel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using static TOHE.Options;
|
||||
@@ -110,7 +109,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;
|
||||
|
||||
|
||||
@@ -11,11 +11,14 @@ public static class SwordsMan
|
||||
//public static bool isKilled = false;
|
||||
public static List<byte> killed = [];
|
||||
public static OptionItem CanVent;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
Options.SetupRoleOptions(Id, TabGroup.CrewmateRoles, CustomRoles.SwordsMan);
|
||||
CanVent = BooleanOptionItem.Create(Id + 11, "CanVent", false, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.SwordsMan]);
|
||||
CanVent = BooleanOptionItem.Create(Id + 11, "CanVent", false, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.SwordsMan]);
|
||||
UsePet = Options.CreatePetUseSetting(Id + 10, CustomRoles.SwordsMan);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -32,7 +35,7 @@ public static class SwordsMan
|
||||
{
|
||||
playerIdList.Add(playerId);
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (Options.UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace TOHE.Roles.Crewmate
|
||||
public static OptionItem VentCooldown;
|
||||
public static OptionItem UseLimitOpt;
|
||||
public static OptionItem TetherAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
@@ -25,10 +26,11 @@ namespace TOHE.Roles.Crewmate
|
||||
VentCooldown = FloatOptionItem.Create(Id + 10, "VentCooldown", new(0f, 70f, 1f), 15f, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Tether])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
UseLimitOpt = IntegerOptionItem.Create(Id + 11, "AbilityUseLimit", new(0, 20, 1), 1, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Tether])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
TetherAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 12, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.4f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Tether])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Tether])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
CancelVote = CreateVoteCancellingUseSetting(Id + 13, CustomRoles.Tether, TabGroup.CrewmateRoles);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -94,12 +96,9 @@ namespace TOHE.Roles.Crewmate
|
||||
}, 0.5f, "Tether No Target Boot From Vent");
|
||||
}
|
||||
}
|
||||
public static void OnVote(PlayerControl pc, PlayerControl target)
|
||||
public static bool OnVote(PlayerControl pc, PlayerControl target)
|
||||
{
|
||||
if (pc == null) return;
|
||||
if (target == null) return;
|
||||
if (!pc.Is(CustomRoles.Tether)) return;
|
||||
if (pc.PlayerId == target.PlayerId) return;
|
||||
if (pc == null || target == null || !pc.Is(CustomRoles.Tether) || pc.PlayerId == target.PlayerId || Main.DontCancelVoteList.Contains(pc.PlayerId)) return false;
|
||||
|
||||
if (UseLimit[pc.PlayerId] >= 1)
|
||||
{
|
||||
@@ -107,7 +106,10 @@ namespace TOHE.Roles.Crewmate
|
||||
Target = target.PlayerId;
|
||||
SendRPC(pc.PlayerId);
|
||||
SendRPCSyncTarget(Target);
|
||||
Main.DontCancelVoteList.Add(pc.PlayerId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static void OnReportDeadBody()
|
||||
{
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace TOHE.Roles.Crewmate
|
||||
private static OptionItem CanGetColoredArrow;
|
||||
public static OptionItem HideVote;
|
||||
public static OptionItem TrackerAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
public static bool CanSeeLastRoomInMeeting;
|
||||
|
||||
@@ -37,6 +38,7 @@ namespace TOHE.Roles.Crewmate
|
||||
TrackerAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 9, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 1f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Tracker])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
CancelVote = CreateVoteCancellingUseSetting(Id + 4, CustomRoles.Tracker, TabGroup.CrewmateRoles);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -74,12 +76,9 @@ namespace TOHE.Roles.Crewmate
|
||||
}
|
||||
public static string GetTargetMark(PlayerControl seer, PlayerControl target) => !(seer == null || target == null) && TrackerTarget.ContainsKey(seer.PlayerId) && TrackerTarget[seer.PlayerId].Contains(target.PlayerId) ? Utils.ColorString(seer.GetRoleColor(), "◀") : string.Empty;
|
||||
|
||||
public static void OnVote(PlayerControl player, PlayerControl target)
|
||||
public static bool OnVote(PlayerControl player, PlayerControl target)
|
||||
{
|
||||
if (player == null || target == null) return;
|
||||
if (TrackLimit[player.PlayerId] < 1) return;
|
||||
if (player.PlayerId == target.PlayerId) return;
|
||||
if (TrackerTarget[player.PlayerId].Contains(target.PlayerId)) return;
|
||||
if (player == null || target == null || TrackLimit[player.PlayerId] < 1 || player.PlayerId == target.PlayerId || TrackerTarget[player.PlayerId].Contains(target.PlayerId) || Main.DontCancelVoteList.Contains(player.PlayerId)) return false;
|
||||
|
||||
TrackLimit[player.PlayerId]--;
|
||||
|
||||
@@ -87,6 +86,9 @@ namespace TOHE.Roles.Crewmate
|
||||
TargetArrow.Add(player.PlayerId, target.PlayerId);
|
||||
|
||||
SendRPC(player.PlayerId, target.PlayerId);
|
||||
|
||||
Main.DontCancelVoteList.Add(player.PlayerId);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void OnReportDeadBody()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Hazel;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using TOHE.Roles.Neutral;
|
||||
using static TOHE.Options;
|
||||
using static TOHE.Translator;
|
||||
@@ -81,7 +80,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);
|
||||
|
||||
@@ -27,6 +27,7 @@ internal static class Eraser
|
||||
private static OptionItem EraseMethod;
|
||||
private static OptionItem WhenTargetIsNeutral;
|
||||
public static OptionItem HideVote;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
private static List<byte> didVote = [];
|
||||
private static Dictionary<byte, int> EraseLimit = [];
|
||||
@@ -40,6 +41,7 @@ internal static class Eraser
|
||||
EraseLimitOpt = IntegerOptionItem.Create(Id + 12, "EraseLimit", new(1, 15, 1), 1, TabGroup.OtherRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Eraser])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
HideVote = BooleanOptionItem.Create(Id + 13, "EraserHideVote", false, TabGroup.OtherRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Eraser]);
|
||||
CancelVote = Options.CreateVoteCancellingUseSetting(Id + 14, CustomRoles.Eraser, TabGroup.OtherRoles);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -103,24 +105,24 @@ internal static class Eraser
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void OnVote(PlayerControl player, PlayerControl target)
|
||||
public static bool OnVote(PlayerControl player, PlayerControl target)
|
||||
{
|
||||
if (player == null || target == null || EraseMethod.GetInt() == 0) return;
|
||||
if (didVote.Contains(player.PlayerId)) return;
|
||||
if (player == null || target == null || EraseMethod.GetInt() == 0) return false;
|
||||
if (didVote.Contains(player.PlayerId) || Main.DontCancelVoteList.Contains(player.PlayerId)) return false;
|
||||
didVote.Add(player.PlayerId);
|
||||
|
||||
if (EraseLimit.ContainsKey(player.PlayerId) && EraseLimit[player.PlayerId] < 1) return;
|
||||
if (EraseLimit.ContainsKey(player.PlayerId) && EraseLimit[player.PlayerId] < 1) return false;
|
||||
|
||||
if (target.PlayerId == player.PlayerId)
|
||||
{
|
||||
Utils.SendMessage(GetString("EraserEraseSelf"), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Eraser), GetString("EraserEraseMsgTitle")));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (target.GetCustomRole().IsNeutral())
|
||||
{
|
||||
Utils.SendMessage(string.Format(GetString("EraserEraseNeutralNotice"), target.GetRealName()), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Eraser), GetString("EraserEraseMsgTitle")));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (EraseLimit.ContainsKey(player.PlayerId)) EraseLimit[player.PlayerId]--;
|
||||
@@ -131,7 +133,10 @@ internal static class Eraser
|
||||
|
||||
Utils.SendMessage(string.Format(GetString("EraserEraseNotice"), target.GetRealName()), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Eraser), GetString("EraserEraseMsgTitle")));
|
||||
|
||||
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: target);
|
||||
if (GameStates.IsInTask) Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: target);
|
||||
|
||||
Main.DontCancelVoteList.Add(player.PlayerId);
|
||||
return true;
|
||||
}
|
||||
public static void OnReportDeadBody()
|
||||
{
|
||||
@@ -143,8 +148,7 @@ internal static class Eraser
|
||||
foreach (byte pc in PlayerToErase.ToArray())
|
||||
{
|
||||
var player = Utils.GetPlayerById(pc);
|
||||
if (player == null)
|
||||
continue;
|
||||
if (player == null) continue;
|
||||
player.RpcSetCustomRole(CustomRolesHelper.GetErasedRole(player.GetCustomRole()));
|
||||
player.Notify(GetString("LostRoleByEraser"));
|
||||
Logger.Info($"{player.GetNameWithRole().RemoveHtmlTags()} 被擦除了", "Eraser");
|
||||
|
||||
@@ -2,7 +2,6 @@ using AmongUs.GameOptions;
|
||||
using Hazel;
|
||||
using Il2CppSystem.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using static TOHE.Options;
|
||||
using static TOHE.Translator;
|
||||
@@ -196,7 +195,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)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static TOHE.Options;
|
||||
using static TOHE.Translator;
|
||||
using static TOHE.Utils;
|
||||
@@ -70,9 +69,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)
|
||||
{
|
||||
|
||||
@@ -53,7 +53,7 @@ internal static class QuickShooter
|
||||
}
|
||||
public static void OnShapeshift(PlayerControl pc, bool shapeshifting)
|
||||
{
|
||||
if (Main.KillTimers[pc.PlayerId] == 0 && shapeshifting)
|
||||
if (Main.KillTimers[pc.PlayerId] <= 0 && shapeshifting)
|
||||
{
|
||||
ShotLimit[pc.PlayerId]++;
|
||||
SendRPC(pc.PlayerId);
|
||||
|
||||
@@ -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>";
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ namespace TOHE.Roles.Impostor
|
||||
byte playerId = reader.ReadByte();
|
||||
YinYangedPlayers.Add(playerId);
|
||||
}
|
||||
else YinYangedPlayers.Clear();
|
||||
}
|
||||
|
||||
public static bool OnCheckMurder(PlayerControl killer, PlayerControl target)
|
||||
@@ -100,8 +101,8 @@ namespace TOHE.Roles.Impostor
|
||||
public static void OnReportDeadBody()
|
||||
{
|
||||
if (!IsEnable) return;
|
||||
YinYanger_?.ResetKillCooldown();
|
||||
YinYangedPlayers.Clear();
|
||||
YinYanger_?.ResetKillCooldown();
|
||||
SendRPC(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
// {
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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()))
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using AmongUs.GameOptions;
|
||||
using System.Collections.Generic;
|
||||
using static TOHE.Options;
|
||||
|
||||
namespace TOHE.Roles.Neutral;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Hazel;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using TOHE.Roles.Crewmate;
|
||||
using UnityEngine;
|
||||
namespace TOHE.Roles.Neutral;
|
||||
@@ -177,7 +176,7 @@ public static class Pelican
|
||||
{
|
||||
if (!GameStates.IsInTask)
|
||||
{
|
||||
if (eatenList.Any())
|
||||
if (eatenList.Count > 0)
|
||||
{
|
||||
eatenList.Clear();
|
||||
SyncEatenList(byte.MaxValue);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using Hazel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using static TOHE.Options;
|
||||
using static TOHE.Utils;
|
||||
@@ -104,7 +103,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();
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ using Hazel;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using static TOHE.Options;
|
||||
using static TOHE.Translator;
|
||||
|
||||
namespace TOHE.Roles.Neutral;
|
||||
|
||||
@@ -98,7 +99,7 @@ public static class WeaponMaster
|
||||
Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
|
||||
break;
|
||||
case 3 when shieldUsed:
|
||||
WM.Notify(Translator.GetString("WMShieldAlreadyUsed"));
|
||||
WM.Notify(GetString("WMShieldAlreadyUsed"));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -119,13 +120,10 @@ public static class WeaponMaster
|
||||
{
|
||||
foreach (PlayerControl player in Main.AllAlivePlayerControls)
|
||||
{
|
||||
if (Pelican.IsEaten(player.PlayerId)) continue;
|
||||
if (player == killer) continue;
|
||||
if (player.Is(CustomRoles.Pestilence) || Main.VeteranInProtect.ContainsKey(target.PlayerId)) continue;
|
||||
if (Pelican.IsEaten(player.PlayerId) || player == killer || player.Is(CustomRoles.Pestilence) || Main.VeteranInProtect.ContainsKey(target.PlayerId)) continue;
|
||||
if (Vector2.Distance(killer.transform.position, player.transform.position) <= Radius.GetFloat())
|
||||
{
|
||||
player.SetRealKiller(killer);
|
||||
player.Kill(player);
|
||||
player.Suicide(PlayerState.DeathReason.Kill, killer);
|
||||
}
|
||||
}
|
||||
killer.SetKillCooldown(time: HighKCD.GetFloat());
|
||||
@@ -134,7 +132,7 @@ public static class WeaponMaster
|
||||
case 2:
|
||||
if (killer.RpcCheckAndMurder(target, true))
|
||||
{
|
||||
target.Kill(target);
|
||||
target.Suicide(PlayerState.DeathReason.Kill, killer);
|
||||
killer.SetKillCooldown();
|
||||
}
|
||||
return false;
|
||||
@@ -173,10 +171,10 @@ public static class WeaponMaster
|
||||
{
|
||||
return mode switch
|
||||
{
|
||||
0 => "Sword",
|
||||
1 => "Axe",
|
||||
2 => "Lance",
|
||||
3 => "Shield",
|
||||
0 => GetString("Sword"),
|
||||
1 => GetString("Axe"),
|
||||
2 => GetString("lance"),
|
||||
3 => GetString("Shield"),
|
||||
_ => string.Empty,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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.1";
|
||||
public const string PluginDisplayVersion = "2.1.1";
|
||||
public const string PluginVersion = "2.2.0";
|
||||
public const string PluginDisplayVersion = "2.2.0";
|
||||
public static readonly string SupportedAUVersion = "2023.10.24";
|
||||
public const int PluginCreate = 3;
|
||||
public const bool Canary = false;
|
||||
@@ -95,6 +95,7 @@ public class Main : BasePlugin
|
||||
public static float RefixCooldownDelay;
|
||||
public static bool ProcessShapeshifts = true;
|
||||
public static Dictionary<byte, (long START_TIMESTAMP, int TOTALCD)> AbilityCD = [];
|
||||
public static List<byte> DontCancelVoteList = [];
|
||||
private static GameData.PlayerInfo lastVotedPlayerInfo;
|
||||
public static string LastVotedPlayer;
|
||||
public static byte NimblePlayer = byte.MaxValue;
|
||||
@@ -642,13 +643,16 @@ public enum CustomRoles
|
||||
{
|
||||
//Default
|
||||
Crewmate = 0,
|
||||
//Impostor(Vanilla)
|
||||
|
||||
//Impostors (Vanilla)
|
||||
Impostor,
|
||||
Shapeshifter,
|
||||
// Vanilla Remakes
|
||||
ImpostorTOHE,
|
||||
ShapeshifterTOHE,
|
||||
//Impostor
|
||||
|
||||
//Impostors
|
||||
|
||||
BountyHunter,
|
||||
FireWorks,
|
||||
Mafia,
|
||||
@@ -727,7 +731,8 @@ public enum CustomRoles
|
||||
Refugee,
|
||||
Underdog,
|
||||
// Flashbang,
|
||||
//Crewmate(Vanilla)
|
||||
|
||||
//Crewmates (Vanilla)
|
||||
Engineer,
|
||||
GuardianAngel,
|
||||
Scientist,
|
||||
@@ -736,7 +741,9 @@ public enum CustomRoles
|
||||
EngineerTOHE,
|
||||
GuardianAngelTOHE,
|
||||
ScientistTOHE,
|
||||
//Crewmate
|
||||
|
||||
// Crewmate
|
||||
|
||||
Luckey,
|
||||
Needy,
|
||||
SuperStar,
|
||||
@@ -831,7 +838,9 @@ public enum CustomRoles
|
||||
Crusader,
|
||||
Cleanser,
|
||||
//Reverie,
|
||||
//Neutral
|
||||
|
||||
//Neutrals
|
||||
|
||||
Arsonist,
|
||||
HexMaster,
|
||||
Jester,
|
||||
|
||||
Reference in new issue
Block a user