Compare commits

..
18 Commits
Author SHA1 Message Date
Gurge44 730ea9afeb Fix EAC, Improve Damocles, Fix Vote Cancelling 2024-01-03 21:46:46 +01:00
Gurge44 dde672ecfc Add strings 2024-01-03 20:23:13 +01:00
Gurge44 badbc4e59a Utilize Vote Cancelling - Without any additional RPC calls 2024-01-02 21:45:36 +01:00
Gurge44 fe2e2b29af Make remaining killers text translatable 2024-01-02 20:01:10 +01:00
Gurge44 f2ccc0b5c7 Final touches 2023-12-31 19:08:01 +01:00
Gurge44 9a4d085d88 Finish 2023-12-31 17:45:56 +01:00
Gurge44 a58997385c Code Cleanup 2023-12-31 14:54:19 +01:00
Gurge44 5062355a37 Merge branch 'main' of https://github.com/Gurge44/TOHE_PLUS 2023-12-31 14:52:50 +01:00
Gurge44 4f946a8f08 Finish Pet Use as Kill Button 2023-12-31 14:52:46 +01:00
PHGaming121 0a23a35bfb Add strings to Weapon Master (#12)
* add strings

* Update WeaponMaster.cs
2023-12-31 14:51:07 +01:00
Gurge44 3a46be462a Start using pet button to kill as imp based crew roles 2023-12-30 20:17:55 +01:00
Gurge44 970281d3b1 just dont do this 2023-12-29 21:20:12 +01:00
Gurge44 087fe9288d remove debug log 2023-12-28 19:05:23 +01:00
Gurge44 817c786c2f Fix Issues & Optimize 2023-12-28 18:40:04 +01:00
Gurge44 ab3b2e517d Merge branch 'main' of https://github.com/Gurge44/TOHE_PLUS 2023-12-28 16:31:05 +01:00
Gurge44 16170126da Sync 2023-12-28 16:30:59 +01:00
Gurge44 cb8b161cac smth 2023-12-27 23:01:44 +01:00
Gurge44 b1ef23682e Final touches 2023-12-26 18:06:00 +01:00
80 changed files with 1001 additions and 650 deletions

No files matched your search

+6 -2
View File
@@ -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)
{
+34 -6
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+20 -4
View File
@@ -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());
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+2 -1
View File
@@ -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;
+2 -1
View File
@@ -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();
+7 -5
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+6 -2
View File
@@ -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
View File
@@ -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);
}
}
+88 -5
View File
@@ -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
View File
@@ -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);
}
}
}
}
+2 -2
View File
@@ -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())
{
+2 -2
View File
@@ -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
View File
@@ -1,5 +1,4 @@
using HarmonyLib;
using UnityEngine;
namespace TOHE.Patches;
+9 -5
View File
@@ -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);
+2
View File
@@ -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
View File
@@ -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.
+6 -1
View File
@@ -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)
+13 -4
View File
@@ -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);
}
}
}
+8 -3
View File
@@ -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
View File
@@ -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;
+3 -1
View File
@@ -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);
}
+1 -1
View File
@@ -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)
{
+1 -2
View File
@@ -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())
+11 -7
View File
@@ -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()
+4 -1
View File
@@ -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);
}
+6 -3
View File
@@ -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);
}
+3 -1
View File
@@ -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);
}
+10 -5
View File
@@ -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;
}
}
+3 -1
View File
@@ -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);
}
+3 -5
View File
@@ -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
{
+3 -1
View File
@@ -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);
}
+6 -2
View File
@@ -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);
+7
View File
@@ -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);
}
+3 -2
View File
@@ -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);
}
+3 -1
View File
@@ -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);
}
+4
View File
@@ -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");
}
}
+3 -2
View File
@@ -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 -7
View File
@@ -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
View File
@@ -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;
}
}
+3 -3
View File
@@ -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(() =>
{
+4 -4
View File
@@ -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);
+10 -8
View File
@@ -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()
{
+1 -1
View File
@@ -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])
+3 -1
View File
@@ -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);
}
+1 -2
View File
@@ -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;
+5 -2
View File
@@ -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);
}
+10 -8
View File
@@ -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()
{
+1 -1
View File
@@ -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");
+7 -5
View File
@@ -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()
+2 -2
View File
@@ -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 -2
View File
@@ -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);
+13 -9
View File
@@ -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");
+1 -2
View File
@@ -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])
+1 -4
View File
@@ -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;
-1
View File
@@ -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 -4
View File
@@ -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)
{
+1 -1
View File
@@ -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);
+1 -5
View File
@@ -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()))
{
+2 -2
View File
@@ -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>";
}
+2 -1
View File
@@ -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);
}
+2 -2
View File
@@ -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()
// {
+1 -1
View File
@@ -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())
+1 -2
View File
@@ -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())
+5 -5
View File
@@ -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
View File
@@ -1,5 +1,4 @@
using AmongUs.GameOptions;
using System.Collections.Generic;
using static TOHE.Options;
namespace TOHE.Roles.Neutral;
+1 -2
View File
@@ -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);
+1 -1
View File
@@ -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);
+1 -2
View File
@@ -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();
+9 -11
View File
@@ -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,
};
}
+16 -7
View File
@@ -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,