mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-20 01:46:25 +00:00
Port to v17.0.0 (2025.9.9)
This commit is contained in:
1 parent
088c218325
commit
e3836c9d31
43 files changed
+531
-181
No files matched your search
@@ -18,7 +18,7 @@ public enum CustomRoles
|
||||
// Impostors
|
||||
|
||||
Abyssbringer,
|
||||
Hacker, // Anonymous
|
||||
Anonymous,
|
||||
AntiAdminer,
|
||||
Sans, // Arrogance
|
||||
Assumer,
|
||||
@@ -106,6 +106,7 @@ public enum CustomRoles
|
||||
Twister,
|
||||
Undertaker,
|
||||
Vampire,
|
||||
Venerer,
|
||||
Ventriloquist,
|
||||
Vindicator,
|
||||
Visionary,
|
||||
@@ -166,7 +167,6 @@ public enum CustomRoles
|
||||
Dealer,
|
||||
Demolitionist,
|
||||
Deputy,
|
||||
Detective,
|
||||
Detour,
|
||||
Dictator,
|
||||
Doctor,
|
||||
@@ -181,6 +181,7 @@ public enum CustomRoles
|
||||
Express,
|
||||
Farmer,
|
||||
Farseer,
|
||||
Forensic,
|
||||
Divinator, // Fortune Teller
|
||||
Gardener,
|
||||
Gaulois,
|
||||
@@ -189,6 +190,7 @@ public enum CustomRoles
|
||||
Grenadier,
|
||||
MeetingManager,
|
||||
Guardian,
|
||||
Hacker,
|
||||
Helper,
|
||||
Ignitor,
|
||||
Imitator,
|
||||
@@ -218,7 +220,6 @@ public enum CustomRoles
|
||||
Mortician,
|
||||
NiceEraser,
|
||||
NiceGuesser,
|
||||
NiceHacker,
|
||||
NiceSwapper,
|
||||
Nightmare,
|
||||
Negotiator,
|
||||
@@ -295,6 +296,7 @@ public enum CustomRoles
|
||||
Enderman,
|
||||
Evolver,
|
||||
Executioner,
|
||||
Explosivist,
|
||||
Totocalcio, // Follower
|
||||
Gaslighter,
|
||||
Glitch,
|
||||
@@ -366,6 +368,7 @@ public enum CustomRoles
|
||||
Technician,
|
||||
Tank,
|
||||
Terrorist,
|
||||
Thanos,
|
||||
Tiger,
|
||||
Traitor,
|
||||
Tremor,
|
||||
@@ -494,6 +497,7 @@ public enum CustomRoles
|
||||
Energetic,
|
||||
Entranced,
|
||||
EvilSpirit,
|
||||
Facilitator, // Ghost role
|
||||
Finder,
|
||||
Flashman,
|
||||
Fragile,
|
||||
|
||||
+8
-1
@@ -9,11 +9,13 @@ public enum CustomRoles
|
||||
Impostor,
|
||||
Phantom,
|
||||
Shapeshifter,
|
||||
Viper,
|
||||
|
||||
// Vanilla Remakes
|
||||
ImpostorEHR,
|
||||
PhantomEHR,
|
||||
ShapeshifterEHR,
|
||||
ViperEHR,
|
||||
|
||||
// Impostors
|
||||
|
||||
@@ -124,6 +126,7 @@ public enum CustomRoles
|
||||
Noisemaker,
|
||||
Scientist,
|
||||
Tracker,
|
||||
Detective,
|
||||
|
||||
// Vanilla Remakes
|
||||
CrewmateEHR,
|
||||
@@ -132,6 +135,7 @@ public enum CustomRoles
|
||||
NoisemakerEHR,
|
||||
ScientistEHR,
|
||||
TrackerEHR,
|
||||
DetectiveEHR,
|
||||
|
||||
// Crewmates
|
||||
|
||||
@@ -167,7 +171,6 @@ public enum CustomRoles
|
||||
Dealer,
|
||||
Demolitionist,
|
||||
Deputy,
|
||||
Detective,
|
||||
Detour,
|
||||
Dictator,
|
||||
Doctor,
|
||||
@@ -182,6 +185,7 @@ public enum CustomRoles
|
||||
Express,
|
||||
Farmer,
|
||||
Farseer,
|
||||
Forensic,
|
||||
Divinator, // Fortune Teller
|
||||
Gardener,
|
||||
Gaulois,
|
||||
@@ -296,6 +300,7 @@ public enum CustomRoles
|
||||
Enderman,
|
||||
Evolver,
|
||||
Executioner,
|
||||
Explosivist,
|
||||
Totocalcio, // Follower
|
||||
Gaslighter,
|
||||
Glitch,
|
||||
@@ -496,6 +501,7 @@ public enum CustomRoles
|
||||
Energetic,
|
||||
Entranced,
|
||||
EvilSpirit,
|
||||
Examiner,
|
||||
Facilitator, // Ghost role
|
||||
Finder,
|
||||
Flashman,
|
||||
@@ -556,6 +562,7 @@ public enum CustomRoles
|
||||
Undead,
|
||||
Underdog,
|
||||
Unlucky,
|
||||
Venom,
|
||||
Warden, // Ghost role
|
||||
Watcher,
|
||||
Workhorse,
|
||||
|
||||
+2
-2
@@ -27,11 +27,11 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2025.4.15" PrivateAssets="all" Condition="'$(Configuration)' == 'Release' Or '$(Configuration)' == 'Debug'"/>
|
||||
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2025.9.9" PrivateAssets="all" Condition="'$(Configuration)' == 'Release' Or '$(Configuration)' == 'Debug'" />
|
||||
<PackageReference Include="AmongUs.GameLibs.Android" Version="2025.6.10" PrivateAssets="all" Condition="'$(Configuration)' == 'Android'"/>
|
||||
<PackageReference Include="BepInEx.IL2CPP.MSBuild" Version="2.1.0-rc.1"/>
|
||||
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.735" Private="false" ExcludeAssets="runtime;native"/>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2025.1.0-eap1"/>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2025.2.2" />
|
||||
<PackageReference Include="Samboy063.Cpp2IL.Core" Version="2022.1.0-pre-release.19"/>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ public class Main : BasePlugin
|
||||
public const string ModColor = "#00ffff";
|
||||
public const bool AllowPublicRoom = true;
|
||||
public const string ForkId = "EHR";
|
||||
public const string SupportedAUVersion = "2025.4.15";
|
||||
public const string SupportedAUVersion = "2025.9.9";
|
||||
|
||||
public static readonly string DataPath =
|
||||
#if ANDROID
|
||||
@@ -175,7 +175,7 @@ public class Main : BasePlugin
|
||||
|
||||
private Harmony Harmony { get; } = new(PluginGuid);
|
||||
|
||||
public static NormalGameOptionsV09 NormalOptions => GameOptionsManager.Instance != null ? GameOptionsManager.Instance.currentNormalGameOptions : null;
|
||||
public static NormalGameOptionsV10 NormalOptions => GameOptionsManager.Instance != null ? GameOptionsManager.Instance.currentNormalGameOptions : null;
|
||||
|
||||
// Client Options
|
||||
public static ConfigEntry<string> HideName { get; private set; }
|
||||
@@ -356,6 +356,7 @@ public class Main : BasePlugin
|
||||
{ CustomRoles.GuardianAngel, "#77e6d1" },
|
||||
{ CustomRoles.Tracker, "#34ad50" },
|
||||
{ CustomRoles.Noisemaker, "#ff4a62" },
|
||||
{ CustomRoles.Detective, "#625EEE" },
|
||||
// Vanilla Remakes
|
||||
{ CustomRoles.CrewmateEHR, "#8cffff" },
|
||||
{ CustomRoles.EngineerEHR, "#FF6A00" },
|
||||
@@ -363,6 +364,7 @@ public class Main : BasePlugin
|
||||
{ CustomRoles.GuardianAngelEHR, "#77e6d1" },
|
||||
{ CustomRoles.TrackerEHR, "#34ad50" },
|
||||
{ CustomRoles.NoisemakerEHR, "#ff4a62" },
|
||||
{ CustomRoles.DetectiveEHR, "#625EEE" },
|
||||
// Crewmates
|
||||
{ CustomRoles.DoubleAgent, "#ff1919" },
|
||||
{ CustomRoles.Luckey, "#b8d7a3" },
|
||||
@@ -455,7 +457,7 @@ public class Main : BasePlugin
|
||||
{ CustomRoles.SpeedBooster, "#00ffff" },
|
||||
{ CustomRoles.Doctor, "#80ffdd" },
|
||||
{ CustomRoles.Dictator, "#df9b00" },
|
||||
{ CustomRoles.Detective, "#7160e8" },
|
||||
{ CustomRoles.Forensic, "#7160e8" },
|
||||
{ CustomRoles.NiceGuesser, "#f0e68c" },
|
||||
{ CustomRoles.SwordsMan, "#7a7a7a" },
|
||||
{ CustomRoles.Transporter, "#42D1FF" },
|
||||
@@ -538,6 +540,7 @@ public class Main : BasePlugin
|
||||
{ CustomRoles.Duality, "#8D6F64" },
|
||||
{ CustomRoles.Thanos, "#F9D401" },
|
||||
{ CustomRoles.SerialKiller, "#233fcc" },
|
||||
{ CustomRoles.Explosivist, "#D20103" },
|
||||
{ CustomRoles.Slenderman, "#2c2e00" },
|
||||
{ CustomRoles.Amogus, "#ff0000" },
|
||||
{ CustomRoles.Weatherman, "#347deb" },
|
||||
@@ -668,6 +671,8 @@ public class Main : BasePlugin
|
||||
{ CustomRoles.Physicist, "#87e9ff" },
|
||||
{ CustomRoles.Finder, "#32a879" },
|
||||
{ CustomRoles.Noisy, "#e34fb2" },
|
||||
{ CustomRoles.Examiner, "#625EEE" },
|
||||
{ CustomRoles.Venom, "#ff1919" },
|
||||
{ CustomRoles.Torch, "#eee5be" },
|
||||
{ CustomRoles.Seer, "#61b26c" },
|
||||
{ CustomRoles.Brakar, "#1447af" },
|
||||
@@ -793,9 +798,9 @@ public class Main : BasePlugin
|
||||
ClassInjector.RegisterTypeInIl2Cpp<VitalsPagingBehaviour>();
|
||||
#endif
|
||||
|
||||
NormalGameOptionsV09.RecommendedImpostors = NormalGameOptionsV09.MaxImpostors = Enumerable.Repeat(128, 128).ToArray();
|
||||
NormalGameOptionsV09.MinPlayers = Enumerable.Repeat(4, 128).ToArray();
|
||||
HideNSeekGameOptionsV09.MinPlayers = Enumerable.Repeat(4, 128).ToArray();
|
||||
NormalGameOptionsV10.RecommendedImpostors = NormalGameOptionsV10.MaxImpostors = Enumerable.Repeat(128, 128).ToArray();
|
||||
NormalGameOptionsV10.MinPlayers = Enumerable.Repeat(4, 128).ToArray();
|
||||
HideNSeekGameOptionsV10.MinPlayers = Enumerable.Repeat(4, 128).ToArray();
|
||||
|
||||
PrivateTagManager.LoadTagsFromFile();
|
||||
|
||||
@@ -1017,6 +1022,7 @@ public enum CustomWinner
|
||||
Necromancer = CustomRoles.Necromancer,
|
||||
Wraith = CustomRoles.Wraith,
|
||||
SerialKiller = CustomRoles.SerialKiller,
|
||||
Explosivist = CustomRoles.Explosivist,
|
||||
Thanos = CustomRoles.Thanos,
|
||||
Duality = CustomRoles.Duality,
|
||||
Slenderman = CustomRoles.Slenderman,
|
||||
|
||||
@@ -120,6 +120,18 @@ public static class AURoleOptions
|
||||
set => Opt.SetFloat(FloatOptionNames.TrackerDelay, value);
|
||||
}
|
||||
|
||||
public static float ViperDissolveTime
|
||||
{
|
||||
get => Opt.GetFloat(FloatOptionNames.ViperDissolveTime);
|
||||
set => Opt.SetFloat(FloatOptionNames.ViperDissolveTime, value);
|
||||
}
|
||||
|
||||
public static float DetectiveSuspectLimit
|
||||
{
|
||||
get => Opt.GetFloat(FloatOptionNames.DetectiveSuspectLimit);
|
||||
set => Opt.SetFloat(FloatOptionNames.DetectiveSuspectLimit, value);
|
||||
}
|
||||
|
||||
public static void SetOpt(IGameOptions opt)
|
||||
{
|
||||
Opt = opt;
|
||||
|
||||
@@ -624,6 +624,7 @@ namespace EHR
|
||||
protected override void OnFixedUpdate()
|
||||
{
|
||||
base.OnFixedUpdate();
|
||||
if (Options.CurrentGameMode != CustomGameMode.BedWars) return;
|
||||
timer -= Time.fixedDeltaTime;
|
||||
|
||||
if (timer <= 0f)
|
||||
|
||||
@@ -18,6 +18,8 @@ internal static class CustomRoleSelector
|
||||
public static int AddNoisemakerNum;
|
||||
public static int AddTrackerNum;
|
||||
public static int AddPhantomNum;
|
||||
public static int AddViperNum;
|
||||
public static int AddDetectiveNum;
|
||||
|
||||
public static readonly Dictionary<CustomGameMode, CustomRoles> GameModeRoles = new()
|
||||
{
|
||||
@@ -905,6 +907,8 @@ internal static class CustomRoleSelector
|
||||
AddNoisemakerNum = 0;
|
||||
AddTrackerNum = 0;
|
||||
AddPhantomNum = 0;
|
||||
AddViperNum = 0;
|
||||
AddDetectiveNum = 0;
|
||||
|
||||
foreach (CustomRoles role in RoleResult.Values)
|
||||
{
|
||||
@@ -930,6 +934,12 @@ internal static class CustomRoleSelector
|
||||
case CustomRoles.Phantom:
|
||||
AddPhantomNum++;
|
||||
break;
|
||||
case CustomRoles.Viper:
|
||||
AddViperNum++;
|
||||
break;
|
||||
case CustomRoles.Detective:
|
||||
AddDetectiveNum++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception e) { Utils.ThrowException(e); }
|
||||
@@ -955,7 +965,7 @@ internal static class CustomRoleSelector
|
||||
case CustomRoles.Mare or CustomRoles.Glow or CustomRoles.Sleep when Main.CurrentMap == MapNames.Fungle:
|
||||
case CustomRoles.Madmate when Options.MadmateSpawnMode.GetInt() != 0:
|
||||
case CustomRoles.Lovers or CustomRoles.LastImpostor or CustomRoles.Workhorse or CustomRoles.Undead or CustomRoles.Insane:
|
||||
case CustomRoles.Nimble or CustomRoles.Physicist or CustomRoles.Bloodlust or CustomRoles.Finder or CustomRoles.Noisy: // Assigned at a different function due to role base change
|
||||
case CustomRoles.Nimble or CustomRoles.Physicist or CustomRoles.Bloodlust or CustomRoles.Finder or CustomRoles.Noisy or CustomRoles.Examiner or CustomRoles.Venom: // Assigned at a different function due to role base change
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.PortalMaker,
|
||||
CustomRoles.Gardener,
|
||||
CustomRoles.Farmer,
|
||||
CustomRoles.Explosivist,
|
||||
|
||||
// Add-ons
|
||||
CustomRoles.Energetic,
|
||||
@@ -279,7 +280,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Escapee => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.NiceGuesser => CustomRoles.Crewmate,
|
||||
CustomRoles.EvilGuesser => CustomRoles.Impostor,
|
||||
CustomRoles.Detective => CustomRoles.Crewmate,
|
||||
CustomRoles.Forensic => CustomRoles.Crewmate,
|
||||
CustomRoles.God => CustomRoles.Crewmate,
|
||||
CustomRoles.Tank => CustomRoles.Engineer,
|
||||
CustomRoles.Technician => Technician.CanVent.GetBool() ? CustomRoles.Engineer : CustomRoles.Crewmate,
|
||||
@@ -339,7 +340,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Devourer => CustomRoles.Shapeshifter,
|
||||
CustomRoles.Deathpact => CustomRoles.Shapeshifter,
|
||||
CustomRoles.Bloodhound => CustomRoles.Crewmate,
|
||||
CustomRoles.Tracker => CustomRoles.Crewmate,
|
||||
CustomRoles.Scout => CustomRoles.Crewmate,
|
||||
CustomRoles.Merchant => CustomRoles.Crewmate,
|
||||
CustomRoles.Lookout => CustomRoles.Crewmate,
|
||||
CustomRoles.Guardian => CustomRoles.Crewmate,
|
||||
@@ -365,6 +366,8 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.ScientistEHR => CustomRoles.Scientist,
|
||||
CustomRoles.TrackerEHR => CustomRoles.Tracker,
|
||||
CustomRoles.NoisemakerEHR => CustomRoles.Noisemaker,
|
||||
CustomRoles.DetectiveEHR => CustomRoles.Detective,
|
||||
CustomRoles.ViperEHR => CustomRoles.Viper,
|
||||
|
||||
// Hide And Seek
|
||||
CustomRoles.Hider => CustomRoles.Crewmate,
|
||||
@@ -418,6 +421,8 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Impostor => CustomRoles.ImpostorEHR,
|
||||
CustomRoles.Phantom => CustomRoles.PhantomEHR,
|
||||
CustomRoles.Shapeshifter => CustomRoles.ShapeshifterEHR,
|
||||
CustomRoles.Detective => CustomRoles.DetectiveEHR,
|
||||
CustomRoles.Viper => CustomRoles.ViperEHR,
|
||||
_ => role.IsImpostor() ? CustomRoles.ImpostorEHR : CustomRoles.CrewmateEHR
|
||||
};
|
||||
}
|
||||
@@ -482,6 +487,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Poisoner => RoleTypes.Impostor,
|
||||
CustomRoles.Duality => RoleTypes.Impostor,
|
||||
CustomRoles.SerialKiller => RoleTypes.Impostor,
|
||||
CustomRoles.Explosivist => RoleTypes.Impostor,
|
||||
CustomRoles.Thanos => RoleTypes.Shapeshifter,
|
||||
CustomRoles.Slenderman => RoleTypes.Impostor,
|
||||
CustomRoles.Amogus => RoleTypes.Impostor,
|
||||
@@ -611,6 +617,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Rogue or
|
||||
CustomRoles.Parasite or
|
||||
CustomRoles.SerialKiller or
|
||||
CustomRoles.Explosivist or
|
||||
CustomRoles.Thanos or
|
||||
CustomRoles.Duality or
|
||||
CustomRoles.Slenderman or
|
||||
@@ -673,6 +680,8 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.PhantomEHR or
|
||||
CustomRoles.Shapeshifter or
|
||||
CustomRoles.ShapeshifterEHR or
|
||||
CustomRoles.Viper or
|
||||
CustomRoles.ViperEHR or
|
||||
CustomRoles.LovingImpostor or
|
||||
CustomRoles.Godfather or
|
||||
CustomRoles.EvilDiviner or
|
||||
@@ -1029,6 +1038,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Wraith or
|
||||
CustomRoles.RouleteGrandeur or
|
||||
CustomRoles.Enderman or
|
||||
CustomRoles.Explosivist or
|
||||
CustomRoles.Hookshot or
|
||||
CustomRoles.Mycologist or
|
||||
CustomRoles.Magician or
|
||||
@@ -1052,12 +1062,12 @@ internal static class CustomRolesHelper
|
||||
{
|
||||
return role.IsAdditionRole() && (!Main.NeverSpawnTogetherCombos.TryGetValue(OptionItem.CurrentPreset, out Dictionary<CustomRoles, List<CustomRoles>> neverList) || !neverList.TryGetValue(pc.GetCustomRole(), out List<CustomRoles> bannedAddonList) || !bannedAddonList.Contains(role)) && pc.GetCustomRole() is not CustomRoles.GuardianAngelEHR and not CustomRoles.God && !pc.Is(CustomRoles.Madmate) && !pc.Is(CustomRoles.GM) && role is not CustomRoles.Lovers && !pc.Is(CustomRoles.Needy) && (!pc.HasSubRole() || pc.GetCustomSubRoles().Count < Options.NoLimitAddonsNumMax.GetInt()) && (!Options.AddonCanBeSettings.TryGetValue(role, out (OptionItem Imp, OptionItem Neutral, OptionItem Crew, OptionItem Coven) o) || ((o.Imp.GetBool() || !pc.GetCustomRole().IsImpostor()) && (o.Neutral.GetBool() || !pc.GetCustomRole().IsNeutral()) && (o.Crew.GetBool() || !pc.IsCrewmate()) && (o.Coven.GetBool() || !pc.Is(Team.Coven)))) && (!role.IsImpOnlyAddon() || (pc.IsImpostor() && !pc.Is(CustomRoles.DoubleAgent)) || (pc.Is(CustomRoles.Traitor) && Traitor.CanGetImpostorOnlyAddons.GetBool())) && role switch
|
||||
{
|
||||
CustomRoles.Commited when pc.GetRoleTypes() is not (RoleTypes.Impostor or RoleTypes.Phantom or RoleTypes.Shapeshifter) => false,
|
||||
CustomRoles.Commited when pc.GetRoleTypes() is not (RoleTypes.Impostor or RoleTypes.Phantom or RoleTypes.Shapeshifter or RoleTypes.Viper) => false,
|
||||
CustomRoles.Underdog when pc.Is(CustomRoles.Mare) => false,
|
||||
CustomRoles.Shy when Options.DisableWhisperCommand.GetBool() => false,
|
||||
CustomRoles.Blocked when !pc.CanUseVent() => false,
|
||||
CustomRoles.Aide when pc.IsMadmate() || pc.Is(CustomRoles.Saboteur) => false,
|
||||
CustomRoles.Sleuth when pc.GetCustomRole() is CustomRoles.NecroGuesser or CustomRoles.Imitator or CustomRoles.Detective => false,
|
||||
CustomRoles.Sleuth when pc.GetCustomRole() is CustomRoles.NecroGuesser or CustomRoles.Imitator or CustomRoles.Forensic => false,
|
||||
CustomRoles.Introvert when pc.GetCustomRole() is CustomRoles.Leery or CustomRoles.Samurai or CustomRoles.Arsonist or CustomRoles.Revolutionist or CustomRoles.Farseer or CustomRoles.Scavenger or CustomRoles.Analyst => false,
|
||||
CustomRoles.Circumvent when pc.GetCustomRole() is CustomRoles.Swooper or CustomRoles.RiftMaker=> false,
|
||||
CustomRoles.Oblivious when pc.Is(CustomRoles.Altruist) => false,
|
||||
@@ -1070,7 +1080,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Magnet when pc.Is(Team.Impostor) => false,
|
||||
CustomRoles.Swift when pc.Is(CustomRoles.Magnet) => false,
|
||||
CustomRoles.Oblivious when pc.Is(CustomRoles.Amnesiac) && Amnesiac.RememberMode.GetValue() == 0 => false,
|
||||
CustomRoles.Rookie when pc.GetRoleTypes() is not (RoleTypes.Impostor or RoleTypes.Phantom or RoleTypes.Shapeshifter) => false,
|
||||
CustomRoles.Rookie when pc.GetRoleTypes() is not (RoleTypes.Impostor or RoleTypes.Phantom or RoleTypes.Shapeshifter or RoleTypes.Viper) => false,
|
||||
CustomRoles.Madmate when pc.Is(CustomRoles.Sidekick) => false,
|
||||
CustomRoles.Autopsy when pc.Is(CustomRoles.Doctor) || pc.Is(CustomRoles.Tracefinder) || pc.Is(CustomRoles.Scientist) || pc.Is(CustomRoles.ScientistEHR) || pc.Is(CustomRoles.Sunnyboy) => false,
|
||||
CustomRoles.Necroview when pc.Is(CustomRoles.Doctor) => false,
|
||||
@@ -1088,11 +1098,11 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Sunglasses when pc.Is(CustomRoles.Torch) || pc.Is(CustomRoles.GuardianAngelEHR) || pc.Is(CustomRoles.Bewilder) => false,
|
||||
CustomRoles.Guesser when pc.GetCustomRole() is CustomRoles.EvilGuesser or CustomRoles.NiceGuesser or CustomRoles.Doomsayer or CustomRoles.CopyCat => false,
|
||||
CustomRoles.Madmate when !pc.CanBeMadmate() || pc.Is(CustomRoles.Egoist) || pc.Is(CustomRoles.Rascal) => false,
|
||||
CustomRoles.Oblivious when pc.Is(CustomRoles.Detective) || pc.Is(CustomRoles.Cleaner) || pc.Is(CustomRoles.Medusa) || pc.Is(CustomRoles.Mortician) || pc.Is(CustomRoles.Mediumshiper) || pc.Is(CustomRoles.GuardianAngelEHR) => false,
|
||||
CustomRoles.Oblivious when pc.Is(CustomRoles.Forensic) || pc.Is(CustomRoles.Cleaner) || pc.Is(CustomRoles.Medusa) || pc.Is(CustomRoles.Mortician) || pc.Is(CustomRoles.Mediumshiper) || pc.Is(CustomRoles.GuardianAngelEHR) => false,
|
||||
CustomRoles.Youtuber when !pc.IsCrewmate() || pc.Is(CustomRoles.Madmate) || pc.Is(CustomRoles.Sheriff) || pc.Is(CustomRoles.GuardianAngelEHR) => false,
|
||||
CustomRoles.Egoist when !pc.IsImpostor() => false,
|
||||
CustomRoles.Damocles when pc.GetCustomRole() is CustomRoles.Bomber or CustomRoles.Nuker or CustomRoles.Mercenary or CustomRoles.Cantankerous => false,
|
||||
CustomRoles.Damocles when pc.GetRoleTypes() is not (RoleTypes.Impostor or RoleTypes.Phantom or RoleTypes.Shapeshifter) => false,
|
||||
CustomRoles.Damocles when pc.GetRoleTypes() is not (RoleTypes.Impostor or RoleTypes.Phantom or RoleTypes.Shapeshifter or RoleTypes.Viper) => false,
|
||||
CustomRoles.Flashman when pc.Is(CustomRoles.Swiftclaw) || pc.Is(CustomRoles.Giant) || pc.Is(CustomRoles.Spurt) || pc.GetCustomRole() is CustomRoles.Tank or CustomRoles.Zombie => false,
|
||||
CustomRoles.Giant when pc.Is(CustomRoles.Flashman) || pc.Is(CustomRoles.Spurt) || pc.Is(CustomRoles.RoomRusher) => false,
|
||||
CustomRoles.Necroview when pc.Is(CustomRoles.Visionary) => false,
|
||||
@@ -1140,9 +1150,9 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Swift when pc.Is(CustomRoles.Mafia) => false,
|
||||
CustomRoles.Reach when pc.GetCustomRole() is CustomRoles.Mafioso or CustomRoles.Evolver => false,
|
||||
CustomRoles.Trapper when pc.Is(CustomRoles.GuardianAngelEHR) => false,
|
||||
CustomRoles.Reach when pc.GetRoleTypes() is not (RoleTypes.Impostor or RoleTypes.Phantom or RoleTypes.Shapeshifter) => false,
|
||||
CustomRoles.Magnet when pc.GetRoleTypes() is not (RoleTypes.Impostor or RoleTypes.Phantom or RoleTypes.Shapeshifter) => false,
|
||||
CustomRoles.Haste when pc.GetRoleTypes() is not (RoleTypes.Impostor or RoleTypes.Phantom or RoleTypes.Shapeshifter) || !pc.CanUseImpostorVentButton() => false,
|
||||
CustomRoles.Reach when pc.GetRoleTypes() is not (RoleTypes.Impostor or RoleTypes.Phantom or RoleTypes.Shapeshifter or RoleTypes.Viper) => false,
|
||||
CustomRoles.Magnet when pc.GetRoleTypes() is not (RoleTypes.Impostor or RoleTypes.Phantom or RoleTypes.Shapeshifter or RoleTypes.Viper) => false,
|
||||
CustomRoles.Haste when pc.GetRoleTypes() is not (RoleTypes.Impostor or RoleTypes.Phantom or RoleTypes.Shapeshifter or RoleTypes.Viper) || !pc.CanUseImpostorVentButton() => false,
|
||||
CustomRoles.Diseased when pc.Is(CustomRoles.Antidote) => false,
|
||||
CustomRoles.Antidote when pc.Is(CustomRoles.Diseased) => false,
|
||||
CustomRoles.Flashman or CustomRoles.Giant when pc.GetCustomRole() is CustomRoles.Swooper or CustomRoles.Wraith or CustomRoles.Chameleon or CustomRoles.Alchemist or CustomRoles.Ankylosaurus => false,
|
||||
@@ -1153,6 +1163,8 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Physicist when !pc.IsCrewmate() || pc.GetCustomRole().IsDesyncRole() || (pc.Is(CustomRoles.TimeMaster) && !TimeMaster.TimeMasterCanUseVitals.GetBool()) => false,
|
||||
CustomRoles.Finder when !pc.IsCrewmate() || pc.GetCustomRole().IsDesyncRole() => false,
|
||||
CustomRoles.Noisy when !pc.IsCrewmate() || pc.GetCustomRole().IsDesyncRole() => false,
|
||||
CustomRoles.Examiner when !pc.IsCrewmate() || pc.GetCustomRole().IsDesyncRole() => false,
|
||||
CustomRoles.Venom when !pc.IsImpostor() => false,
|
||||
CustomRoles.Unreportable when pc.Is(CustomRoles.Bait) => false,
|
||||
CustomRoles.Oblivious when pc.Is(CustomRoles.Bloodhound) => false,
|
||||
CustomRoles.Oblivious when pc.Is(CustomRoles.Vulture) => false,
|
||||
@@ -1284,6 +1296,8 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Scientist or
|
||||
CustomRoles.GuardianAngel or
|
||||
CustomRoles.Impostor or
|
||||
CustomRoles.Detective or
|
||||
CustomRoles.Viper or
|
||||
CustomRoles.Phantom or
|
||||
CustomRoles.Shapeshifter;
|
||||
}
|
||||
@@ -1314,30 +1328,6 @@ internal static class CustomRolesHelper
|
||||
return Options.GetRoleSpawnMode(role);
|
||||
}
|
||||
|
||||
public static float GetChance(this CustomRoles role)
|
||||
{
|
||||
if (role.IsVanilla())
|
||||
{
|
||||
IRoleOptionsCollection roleOpt = Main.NormalOptions.RoleOptions;
|
||||
|
||||
return role switch
|
||||
{
|
||||
CustomRoles.Engineer => roleOpt.GetChancePerGame(RoleTypes.Engineer),
|
||||
CustomRoles.Noisemaker => roleOpt.GetChancePerGame(RoleTypes.Noisemaker),
|
||||
CustomRoles.Tracker => roleOpt.GetChancePerGame(RoleTypes.Tracker),
|
||||
CustomRoles.Scientist => roleOpt.GetChancePerGame(RoleTypes.Scientist),
|
||||
CustomRoles.Impostor => roleOpt.GetChancePerGame(RoleTypes.Impostor),
|
||||
CustomRoles.Phantom => roleOpt.GetChancePerGame(RoleTypes.Phantom),
|
||||
CustomRoles.Shapeshifter => roleOpt.GetChancePerGame(RoleTypes.Shapeshifter),
|
||||
CustomRoles.GuardianAngel => roleOpt.GetChancePerGame(RoleTypes.GuardianAngel),
|
||||
CustomRoles.Crewmate => roleOpt.GetChancePerGame(RoleTypes.Crewmate),
|
||||
_ => 0
|
||||
} / 100f;
|
||||
}
|
||||
|
||||
return Options.GetRoleChance(role);
|
||||
}
|
||||
|
||||
public static bool IsEnable(this CustomRoles role)
|
||||
{
|
||||
return role switch
|
||||
@@ -1441,7 +1431,7 @@ internal static class CustomRolesHelper
|
||||
RoleOptionType.Impostor_Concealing => Utils.GetRoleColor(CustomRoles.CopyCat),
|
||||
RoleOptionType.Impostor_Miscellaneous => Palette.ImpostorRed,
|
||||
RoleOptionType.Crewmate_Miscellaneous => Palette.CrewmateBlue,
|
||||
RoleOptionType.Crewmate_Investigate => Utils.GetRoleColor(CustomRoles.Detective),
|
||||
RoleOptionType.Crewmate_Investigate => Utils.GetRoleColor(CustomRoles.Forensic),
|
||||
RoleOptionType.Crewmate_Support => Utils.GetRoleColor(CustomRoles.NiceEraser),
|
||||
RoleOptionType.Crewmate_Killing => Utils.GetRoleColor(CustomRoles.Sheriff),
|
||||
RoleOptionType.Crewmate_Power => Utils.GetRoleColor(CustomRoles.Electric),
|
||||
@@ -1650,6 +1640,8 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.ShapeshifterEHR => RoleOptionType.Impostor_Miscellaneous,
|
||||
CustomRoles.Phantom => RoleOptionType.Impostor_Miscellaneous,
|
||||
CustomRoles.PhantomEHR => RoleOptionType.Impostor_Miscellaneous,
|
||||
CustomRoles.Viper => RoleOptionType.Impostor_Miscellaneous,
|
||||
CustomRoles.ViperEHR => RoleOptionType.Impostor_Miscellaneous,
|
||||
CustomRoles.DoubleAgent => RoleOptionType.Crewmate_Investigate,
|
||||
_ => role.IsCrewmate() ? RoleOptionType.Crewmate_Miscellaneous : RoleOptionType.Neutral_Benign
|
||||
};
|
||||
@@ -1669,6 +1661,8 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.TrackerEHR => RoleOptionType.Crewmate_Miscellaneous,
|
||||
CustomRoles.Noisemaker => RoleOptionType.Crewmate_Miscellaneous,
|
||||
CustomRoles.NoisemakerEHR => RoleOptionType.Crewmate_Miscellaneous,
|
||||
CustomRoles.Detective => RoleOptionType.Crewmate_Miscellaneous,
|
||||
CustomRoles.DetectiveEHR => RoleOptionType.Crewmate_Miscellaneous,
|
||||
CustomRoles.Addict => RoleOptionType.Crewmate_Miscellaneous,
|
||||
CustomRoles.CameraMan => RoleOptionType.Crewmate_Miscellaneous,
|
||||
CustomRoles.Demolitionist => RoleOptionType.Crewmate_Miscellaneous,
|
||||
@@ -1692,7 +1686,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Chameleon => RoleOptionType.Crewmate_Investigate,
|
||||
CustomRoles.Clairvoyant => RoleOptionType.Crewmate_Investigate,
|
||||
CustomRoles.Bloodhound => RoleOptionType.Crewmate_Investigate,
|
||||
CustomRoles.Detective => RoleOptionType.Crewmate_Investigate,
|
||||
CustomRoles.Forensic => RoleOptionType.Crewmate_Investigate,
|
||||
CustomRoles.Doctor => RoleOptionType.Crewmate_Investigate,
|
||||
CustomRoles.DoubleAgent => RoleOptionType.Crewmate_Investigate,
|
||||
CustomRoles.Druid => RoleOptionType.Crewmate_Investigate,
|
||||
@@ -1863,6 +1857,7 @@ public enum CountTypes
|
||||
HexMaster,
|
||||
Wraith,
|
||||
SerialKiller,
|
||||
Explosivist,
|
||||
Thanos,
|
||||
Duality,
|
||||
Slenderman,
|
||||
|
||||
@@ -477,6 +477,8 @@ internal static class ExtendedPlayerControl
|
||||
CustomRoles.Physicist when newRoleType == RoleTypes.Crewmate => RoleTypes.Scientist,
|
||||
CustomRoles.Finder when newRoleType is RoleTypes.Crewmate or RoleTypes.Scientist or RoleTypes.Noisemaker => RoleTypes.Tracker,
|
||||
CustomRoles.Noisy when newRoleType == RoleTypes.Crewmate => RoleTypes.Noisemaker,
|
||||
CustomRoles.Examiner when newRoleType is RoleTypes.Crewmate or RoleTypes.Scientist or RoleTypes.Noisemaker => RoleTypes.Detective,
|
||||
CustomRoles.Venom when newRoleType == RoleTypes.Impostor => RoleTypes.Viper,
|
||||
_ => newRoleType
|
||||
},
|
||||
_ => newRoleType
|
||||
@@ -1337,7 +1339,7 @@ internal static class ExtendedPlayerControl
|
||||
{
|
||||
CustomRoles role = pc.GetCustomRole();
|
||||
if (pc.Data.Role.Role == RoleTypes.GuardianAngel) return false;
|
||||
if (role.GetVNRole(true) is CustomRoles.Impostor or CustomRoles.ImpostorEHR or CustomRoles.Shapeshifter or CustomRoles.ShapeshifterEHR or CustomRoles.Phantom or CustomRoles.PhantomEHR) return true;
|
||||
if (role.GetVNRole(true) is CustomRoles.Impostor or CustomRoles.ImpostorEHR or CustomRoles.Shapeshifter or CustomRoles.ShapeshifterEHR or CustomRoles.Phantom or CustomRoles.PhantomEHR or CustomRoles.Viper or CustomRoles.ViperEHR) return true;
|
||||
if (pc.GetRoleTypes() is RoleTypes.Impostor or RoleTypes.Shapeshifter or RoleTypes.Phantom) return true;
|
||||
if (pc.Is(CustomRoles.Bloodlust)) return true;
|
||||
return !HasTasks(pc.Data, false);
|
||||
@@ -2112,6 +2114,8 @@ internal static class ExtendedPlayerControl
|
||||
{ } x when x.Contains(CustomRoles.Physicist) => RoleTypes.Scientist,
|
||||
{ } x when x.Contains(CustomRoles.Finder) => RoleTypes.Tracker,
|
||||
{ } x when x.Contains(CustomRoles.Noisy) => RoleTypes.Noisemaker,
|
||||
{ } x when x.Contains(CustomRoles.Examiner) => RoleTypes.Detective,
|
||||
{ } x when x.Contains(CustomRoles.Venom) => RoleTypes.Viper,
|
||||
_ => pc.GetCustomRole().GetRoleTypes()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,13 +9,13 @@ public static class IGameManagerEx
|
||||
opt.SetBool(name, value);
|
||||
}
|
||||
|
||||
public static void Set(this BoolOptionNames name, bool value, NormalGameOptionsV09 opt)
|
||||
public static void Set(this BoolOptionNames name, bool value, NormalGameOptionsV10 opt)
|
||||
{
|
||||
if (name is not BoolOptionNames.GhostsDoTasks and not BoolOptionNames.Roles)
|
||||
opt.SetBool(name, value);
|
||||
}
|
||||
|
||||
public static void Set(this BoolOptionNames name, bool value, HideNSeekGameOptionsV09 opt)
|
||||
public static void Set(this BoolOptionNames name, bool value, HideNSeekGameOptionsV10 opt)
|
||||
{
|
||||
opt.SetBool(name, value);
|
||||
}
|
||||
@@ -25,12 +25,12 @@ public static class IGameManagerEx
|
||||
opt.SetInt(name, value);
|
||||
}
|
||||
|
||||
public static void Set(this Int32OptionNames name, int value, NormalGameOptionsV09 opt)
|
||||
public static void Set(this Int32OptionNames name, int value, NormalGameOptionsV10 opt)
|
||||
{
|
||||
opt.SetInt(name, value);
|
||||
}
|
||||
|
||||
public static void Set(this Int32OptionNames name, int value, HideNSeekGameOptionsV09 opt)
|
||||
public static void Set(this Int32OptionNames name, int value, HideNSeekGameOptionsV10 opt)
|
||||
{
|
||||
opt.SetInt(name, value);
|
||||
}
|
||||
@@ -40,12 +40,12 @@ public static class IGameManagerEx
|
||||
opt.SetFloat(name, value);
|
||||
}
|
||||
|
||||
public static void Set(this FloatOptionNames name, float value, NormalGameOptionsV09 opt)
|
||||
public static void Set(this FloatOptionNames name, float value, NormalGameOptionsV10 opt)
|
||||
{
|
||||
opt.SetFloat(name, value);
|
||||
}
|
||||
|
||||
public static void Set(this FloatOptionNames name, float value, HideNSeekGameOptionsV09 opt)
|
||||
public static void Set(this FloatOptionNames name, float value, HideNSeekGameOptionsV10 opt)
|
||||
{
|
||||
opt.SetFloat(name, value);
|
||||
}
|
||||
@@ -55,12 +55,12 @@ public static class IGameManagerEx
|
||||
opt.SetByte(name, value);
|
||||
}
|
||||
|
||||
public static void Set(this ByteOptionNames name, byte value, NormalGameOptionsV09 opt)
|
||||
public static void Set(this ByteOptionNames name, byte value, NormalGameOptionsV10 opt)
|
||||
{
|
||||
opt.SetByte(name, value);
|
||||
}
|
||||
|
||||
public static void Set(this ByteOptionNames name, byte value, HideNSeekGameOptionsV09 opt)
|
||||
public static void Set(this ByteOptionNames name, byte value, HideNSeekGameOptionsV10 opt)
|
||||
{
|
||||
opt.SetByte(name, value);
|
||||
}
|
||||
@@ -70,12 +70,12 @@ public static class IGameManagerEx
|
||||
opt.SetUInt(name, value);
|
||||
}
|
||||
|
||||
public static void Set(this UInt32OptionNames name, uint value, NormalGameOptionsV09 opt)
|
||||
public static void Set(this UInt32OptionNames name, uint value, NormalGameOptionsV10 opt)
|
||||
{
|
||||
opt.SetUInt(name, value);
|
||||
}
|
||||
|
||||
public static void Set(this UInt32OptionNames name, uint value, HideNSeekGameOptionsV09 opt)
|
||||
public static void Set(this UInt32OptionNames name, uint value, HideNSeekGameOptionsV10 opt)
|
||||
{
|
||||
opt.SetUInt(name, value);
|
||||
}
|
||||
|
||||
@@ -24,10 +24,10 @@ public abstract class GameOptionsSender
|
||||
writer.StartMessage(0);
|
||||
writer.Write((byte)opt.GameMode);
|
||||
|
||||
if (opt.TryCast(out NormalGameOptionsV09 normalOpt))
|
||||
NormalGameOptionsV09.Serialize(writer, normalOpt);
|
||||
else if (opt.TryCast(out HideNSeekGameOptionsV09 hnsOpt))
|
||||
HideNSeekGameOptionsV09.Serialize(writer, hnsOpt);
|
||||
if (opt.TryCast(out NormalGameOptionsV10 normalOpt))
|
||||
NormalGameOptionsV10.Serialize(writer, normalOpt);
|
||||
else if (opt.TryCast(out HideNSeekGameOptionsV10 hnsOpt))
|
||||
HideNSeekGameOptionsV10.Serialize(writer, hnsOpt);
|
||||
else
|
||||
{
|
||||
writer.Recycle();
|
||||
|
||||
@@ -4,6 +4,7 @@ using AmongUs.GameOptions;
|
||||
using EHR.AddOns.Common;
|
||||
using EHR.AddOns.Crewmate;
|
||||
using EHR.AddOns.GhostRoles;
|
||||
using EHR.AddOns.Impostor;
|
||||
using EHR.Coven;
|
||||
using EHR.Crewmate;
|
||||
using EHR.Impostor;
|
||||
@@ -22,7 +23,7 @@ public sealed class PlayerGameOptionsSender(PlayerControl player) : GameOptionsS
|
||||
public PlayerControl player = player;
|
||||
|
||||
private static IGameOptions BasedGameOptions =>
|
||||
Main.RealOptionsData.Restore(new NormalGameOptionsV09(new UnityLogger().CastFast<ILogger>()).CastFast<IGameOptions>());
|
||||
Main.RealOptionsData.Restore(new NormalGameOptionsV10(new UnityLogger().CastFast<ILogger>()).CastFast<IGameOptions>());
|
||||
|
||||
protected override bool IsDirty { get; set; }
|
||||
|
||||
@@ -254,6 +255,12 @@ public sealed class PlayerGameOptionsSender(PlayerControl player) : GameOptionsS
|
||||
AURoleOptions.TrackerDuration = CrewmateVanillaRoles.TrackerDuration.GetFloat();
|
||||
AURoleOptions.TrackerDelay = CrewmateVanillaRoles.TrackerDelay.GetFloat();
|
||||
break;
|
||||
case CustomRoles.DetectiveEHR:
|
||||
AURoleOptions.DetectiveSuspectLimit = CrewmateVanillaRoles.DetectiveSuspectLimit.GetFloat();
|
||||
break;
|
||||
case CustomRoles.ViperEHR:
|
||||
AURoleOptions.ViperDissolveTime = ImpostorVanillaRoles.ViperDissolveTime.GetFloat();
|
||||
break;
|
||||
}
|
||||
|
||||
// When impostor alert is off, and the player is a desync crewmate, set impostor alert as true
|
||||
@@ -425,6 +432,12 @@ public sealed class PlayerGameOptionsSender(PlayerControl player) : GameOptionsS
|
||||
AURoleOptions.NoisemakerImpostorAlert = Noisy.NoisyImpostorAlert.GetBool();
|
||||
AURoleOptions.NoisemakerAlertDuration = Noisy.NoisyAlertDuration.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Examiner when roleTypes == RoleTypes.Detective:
|
||||
AURoleOptions.DetectiveSuspectLimit = Examiner.ExaminerSuspectLimit.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Venom when roleTypes == RoleTypes.Viper:
|
||||
AURoleOptions.ViperDissolveTime = Venom.VenomDissolveTime.GetFloat();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,6 +471,12 @@ public sealed class PlayerGameOptionsSender(PlayerControl player) : GameOptionsS
|
||||
case RoleTypes.Tracker:
|
||||
AURoleOptions.TrackerCooldown *= 0.75f;
|
||||
break;
|
||||
case RoleTypes.Viper:
|
||||
AURoleOptions.ViperDissolveTime *= 0.75f;
|
||||
break;
|
||||
case RoleTypes.Detective:
|
||||
AURoleOptions.DetectiveSuspectLimit *= 1.25f;
|
||||
goto default;
|
||||
case RoleTypes.CrewmateGhost:
|
||||
case RoleTypes.ImpostorGhost:
|
||||
break;
|
||||
|
||||
@@ -42,7 +42,7 @@ public class OptionBackupData
|
||||
// Since TryGetUInt is not implemented, get it separately
|
||||
AllValues.Add(new UIntOptionBackupValue(UInt32OptionNames.Keywords, (uint)option.Keywords));
|
||||
|
||||
RoleTypes[] array = [RoleTypes.Scientist, RoleTypes.Engineer, RoleTypes.GuardianAngel, RoleTypes.Shapeshifter, RoleTypes.Noisemaker, RoleTypes.Phantom, RoleTypes.Tracker];
|
||||
RoleTypes[] array = [RoleTypes.Scientist, RoleTypes.Engineer, RoleTypes.GuardianAngel, RoleTypes.Shapeshifter, RoleTypes.Noisemaker, RoleTypes.Phantom, RoleTypes.Tracker, RoleTypes.Viper, RoleTypes.Detective];
|
||||
foreach (RoleTypes role in array) AllValues.Add(new RoleRateBackupValue(role, option.RoleOptions.GetNumPerGame(role), option.RoleOptions.GetChancePerGame(role)));
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -839,6 +839,7 @@ public static class Utils
|
||||
case CustomRoles.Eclipse:
|
||||
case CustomRoles.Pyromaniac:
|
||||
case CustomRoles.SerialKiller:
|
||||
case CustomRoles.Explosivist:
|
||||
case CustomRoles.Thanos:
|
||||
case CustomRoles.Slenderman:
|
||||
case CustomRoles.Amogus:
|
||||
@@ -3269,6 +3270,7 @@ public static class Utils
|
||||
CustomRoles.Tiger => Tiger.EnrageCooldown.GetInt() + (includeDuration ? Tiger.EnrageDuration.GetInt() : 0),
|
||||
CustomRoles.Nonplus => Nonplus.BlindCooldown.GetInt() + (includeDuration ? Nonplus.BlindDuration.GetInt() : 0),
|
||||
CustomRoles.Amogus => Amogus.AbilityCooldown.GetInt() + (includeDuration ? Amogus.AbilityDuration.GetInt() : 0),
|
||||
CustomRoles.Explosivist => Explosivist.AbilityCooldown.GetInt() + (includeDuration ? Explosivist.ExplosionDelay.GetInt() : 0),
|
||||
CustomRoles.Cherokious => Cherokious.KillCooldown.GetInt(),
|
||||
CustomRoles.Shifter => Shifter.KillCooldown.GetInt(),
|
||||
CustomRoles.NoteKiller => NoteKiller.AbilityCooldown.GetInt(),
|
||||
@@ -4105,7 +4107,7 @@ public static class Utils
|
||||
{
|
||||
int baseColorId = deadBodyParent.Data.DefaultOutfit.ColorId;
|
||||
deadBodyParent.Data.DefaultOutfit.ColorId = colorId;
|
||||
DeadBody deadBody = Object.Instantiate(GameManager.Instance.DeadBodyPrefab);
|
||||
DeadBody deadBody = Object.Instantiate(GameManager.Instance.deadBodyPrefab[0]);
|
||||
deadBody.enabled = false;
|
||||
deadBody.ParentId = deadBodyParent.PlayerId;
|
||||
foreach (SpriteRenderer b in deadBody.bodyRenderers)
|
||||
|
||||
@@ -23,7 +23,8 @@ internal static class ChatBubbleSetNamePatch
|
||||
|
||||
if (GameStates.IsInGame && !voted && seer.PlayerId == target.PlayerId) __instance.NameText.color = seer.GetRoleColor();
|
||||
|
||||
if (seer.GetCustomRole().GetDYRole() is RoleTypes.Shapeshifter or RoleTypes.Phantom) __instance.NameText.color = Color.white;
|
||||
if (seer.GetCustomRole().GetDYRole() is RoleTypes.Shapeshifter or RoleTypes.Phantom or RoleTypes.Viper)
|
||||
__instance.NameText.color = Color.white;
|
||||
|
||||
if (Main.DarkTheme.Value)
|
||||
{
|
||||
|
||||
@@ -3238,6 +3238,30 @@ internal static class ChatCommands
|
||||
subArgs = args.Length < 3 ? "" : args[2];
|
||||
GameOptionsManager.Instance.CurrentGameOptions.SetFloat(FloatOptionNames.TrackerDelay, float.Parse(subArgs));
|
||||
break;
|
||||
case "vipercount":
|
||||
subArgs = args.Length < 3 ? "" : args[2];
|
||||
GameOptionsManager.Instance.CurrentGameOptions.RoleOptions.SetRoleRate(RoleTypes.Viper, int.Parse(subArgs), GameOptionsManager.Instance.CurrentGameOptions.RoleOptions.GetChancePerGame(RoleTypes.Viper));
|
||||
break;
|
||||
case "viperchance":
|
||||
subArgs = args.Length < 3 ? "" : args[2];
|
||||
GameOptionsManager.Instance.CurrentGameOptions.RoleOptions.SetRoleRate(RoleTypes.Viper, GameOptionsManager.Instance.CurrentGameOptions.RoleOptions.GetNumPerGame(RoleTypes.Viper), int.Parse(subArgs));
|
||||
break;
|
||||
case "viperdissolvetime":
|
||||
subArgs = args.Length < 3 ? "" : args[2];
|
||||
GameOptionsManager.Instance.CurrentGameOptions.SetFloat(FloatOptionNames.ViperDissolveTime, float.Parse(subArgs));
|
||||
break;
|
||||
case "detectivecount":
|
||||
subArgs = args.Length < 3 ? "" : args[2];
|
||||
GameOptionsManager.Instance.CurrentGameOptions.RoleOptions.SetRoleRate(RoleTypes.Detective, int.Parse(subArgs), GameOptionsManager.Instance.CurrentGameOptions.RoleOptions.GetChancePerGame(RoleTypes.Detective));
|
||||
break;
|
||||
case "detectivechance":
|
||||
subArgs = args.Length < 3 ? "" : args[2];
|
||||
GameOptionsManager.Instance.CurrentGameOptions.RoleOptions.SetRoleRate(RoleTypes.Detective, GameOptionsManager.Instance.CurrentGameOptions.RoleOptions.GetNumPerGame(RoleTypes.Detective), int.Parse(subArgs));
|
||||
break;
|
||||
case "detectivesuspectlimit":
|
||||
subArgs = args.Length < 3 ? "" : args[2];
|
||||
GameOptionsManager.Instance.CurrentGameOptions.SetFloat(FloatOptionNames.DetectiveSuspectLimit, float.Parse(subArgs));
|
||||
break;
|
||||
default:
|
||||
Utils.SendMessage(GetString("Commands.ChangeSettingHelp"), player.PlayerId);
|
||||
break;
|
||||
@@ -3328,7 +3352,7 @@ internal static class ChatCommands
|
||||
"擺爛人" or "摆烂" => GetString("Needy"),
|
||||
"獨裁者" or "独裁" or "dict" => GetString("Dictator"),
|
||||
"法醫" or "doc" => GetString("Doctor"),
|
||||
"偵探" or "det" => GetString("Detective"),
|
||||
"偵探" or "det" => GetString("Forensic"),
|
||||
"幸運兒" or "幸运" => GetString("Luckey"),
|
||||
"大明星" or "明星" or "ss" => GetString("SuperStar"),
|
||||
"demo" => GetString("Demolitionist"),
|
||||
|
||||
@@ -1101,7 +1101,7 @@ internal static class GameEndChecker
|
||||
|
||||
if ((GameData.Instance.TotalTasks == 0 && GameData.Instance.CompletedTasks == 0) || !Main.PlayerStates.Values.Any(x => x.TaskState.HasTasks)) return false;
|
||||
if (Options.DisableTaskWinIfAllCrewsAreDead.GetBool() && !Main.AllAlivePlayerControls.Any(x => x.Is(CustomRoleTypes.Crewmate))) return false;
|
||||
if (Options.DisableTaskWinIfAllCrewsAreConverted.GetBool() && Main.AllAlivePlayerControls.Where(x => x.Is(Team.Crewmate) && x.GetRoleTypes() is RoleTypes.Crewmate or RoleTypes.Engineer or RoleTypes.Scientist or RoleTypes.Noisemaker or RoleTypes.Tracker or RoleTypes.CrewmateGhost or RoleTypes.GuardianAngel).All(x => x.IsConverted())) return false;
|
||||
if (Options.DisableTaskWinIfAllCrewsAreConverted.GetBool() && Main.AllAlivePlayerControls.Where(x => x.Is(Team.Crewmate) && x.GetRoleTypes() is RoleTypes.Crewmate or RoleTypes.Engineer or RoleTypes.Scientist or RoleTypes.Noisemaker or RoleTypes.Tracker or RoleTypes.Detective or RoleTypes.CrewmateGhost or RoleTypes.GuardianAngel).All(x => x.IsConverted())) return false;
|
||||
|
||||
if (GameData.Instance.TotalTasks <= GameData.Instance.CompletedTasks)
|
||||
{
|
||||
|
||||
+2
-2
@@ -266,11 +266,11 @@ internal static class Crowded
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(NormalGameOptionsV09), nameof(NormalGameOptionsV09.AreInvalid))]
|
||||
[HarmonyPatch(typeof(NormalGameOptionsV10), nameof(NormalGameOptionsV10.AreInvalid))]
|
||||
public static class InvalidOptionsPatches
|
||||
{
|
||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||
public static bool Prefix(NormalGameOptionsV09 __instance, [HarmonyArgument(0)] int maxExpectedPlayers)
|
||||
public static bool Prefix(NormalGameOptionsV10 __instance, [HarmonyArgument(0)] int maxExpectedPlayers)
|
||||
{
|
||||
return __instance.MaxPlayers > maxExpectedPlayers ||
|
||||
__instance.NumImpostors < 1 ||
|
||||
|
||||
@@ -219,6 +219,7 @@ internal static class HudManagerPatch
|
||||
|
||||
RoleTypes roleTypes = player.GetRoleTypes();
|
||||
__instance.AbilityButton?.OverrideText(GetString($"AbilityButtonText.{roleTypes}"));
|
||||
__instance.SecondaryAbilityButton?.OverrideText(GetString($"SecondaryAbilityButtonText.{roleTypes}"));
|
||||
|
||||
PlayerState state = Main.PlayerStates[player.PlayerId];
|
||||
|
||||
|
||||
@@ -711,6 +711,14 @@ internal static class BeginCrewmatePatch
|
||||
or CustomRoles.EvilTracker
|
||||
or CustomRoles.Scout
|
||||
=> GetIntroSound(RoleTypes.Tracker),
|
||||
|
||||
CustomRoles.Viper
|
||||
or CustomRoles.ViperEHR
|
||||
=> GetIntroSound(RoleTypes.Viper),
|
||||
|
||||
CustomRoles.Detective
|
||||
or CustomRoles.DetectiveEHR
|
||||
=> GetIntroSound(RoleTypes.Detective),
|
||||
|
||||
CustomRoles.Noisemaker
|
||||
or CustomRoles.NoisemakerEHR
|
||||
@@ -921,7 +929,7 @@ internal static class BeginCrewmatePatch
|
||||
|
||||
private static AudioClip GetIntroSound(RoleTypes roleType)
|
||||
{
|
||||
return RoleManager.Instance.AllRoles.FirstOrDefault(role => role.Role == roleType)?.IntroSound;
|
||||
return RoleManager.Instance.AllRoles.Find((Il2CppSystem.Predicate<RoleBehaviour>)(role => role.Role == roleType))?.IntroSound;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -776,7 +776,7 @@ internal static class MeetingHudStartPatch
|
||||
AddMsg(string.Format(GetString("SilencerDead"), playername, pc.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Silencer), GetString("SilencerKillTitle"))));
|
||||
}
|
||||
|
||||
if (Detective.DetectiveNotify.TryGetValue(pc.PlayerId, out string value1)) AddMsg(value1, pc.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Detective), GetString("DetectiveNoticeTitle")));
|
||||
if (Forensic.ForensicNotify.TryGetValue(pc.PlayerId, out string value1)) AddMsg(value1, pc.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Forensic), GetString("ForensicNoticeTitle")));
|
||||
if (Main.SleuthMsgs.TryGetValue(pc.PlayerId, out string msg)) AddMsg(msg, pc.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Sleuth), GetString("Sleuth")));
|
||||
|
||||
if (pc.Is(CustomRoles.Mimic) && !pc.IsAlive())
|
||||
@@ -815,7 +815,7 @@ internal static class MeetingHudStartPatch
|
||||
Main.SuperStarDead.Clear();
|
||||
Express.SpeedNormal.Clear();
|
||||
Express.SpeedUp.Clear();
|
||||
Detective.DetectiveNotify.Clear();
|
||||
Forensic.ForensicNotify.Clear();
|
||||
Main.SleuthMsgs.Clear();
|
||||
Virus.VirusNotify.Clear();
|
||||
Mortician.MsgToSend.Clear();
|
||||
|
||||
@@ -170,7 +170,9 @@ internal static class ChangeRoleSettings
|
||||
RoleTypes.Shapeshifter,
|
||||
RoleTypes.Noisemaker,
|
||||
RoleTypes.Phantom,
|
||||
RoleTypes.Tracker
|
||||
RoleTypes.Tracker,
|
||||
RoleTypes.Detective,
|
||||
RoleTypes.Viper
|
||||
}.Do(x => Main.NormalOptions.roleOptions.SetRoleRate(x, 0, 0));
|
||||
|
||||
if (Main.NormalOptions.MapId > 5 && !(Main.NormalOptions.MapId == 6 && SubmergedCompatibility.Loaded))
|
||||
@@ -241,7 +243,7 @@ internal static class ChangeRoleSettings
|
||||
Mafia.MafiaRevenged = [];
|
||||
Warlock.IsCurseAndKill = [];
|
||||
Warlock.IsCursed = false;
|
||||
Detective.DetectiveNotify = [];
|
||||
Forensic.ForensicNotify = [];
|
||||
Provocateur.Provoked = [];
|
||||
Crusader.ForCrusade = [];
|
||||
Godfather.GodfatherTarget = byte.MaxValue;
|
||||
@@ -472,7 +474,7 @@ internal static class StartGameHostPatch
|
||||
|
||||
public static readonly Dictionary<byte, bool> DataDisconnected = [];
|
||||
|
||||
private static RoleOptionsCollectionV09 RoleOpt => Main.NormalOptions.roleOptions;
|
||||
private static RoleOptionsCollectionV10 RoleOpt => Main.NormalOptions.roleOptions;
|
||||
|
||||
private static void UpdateRoleTypeNums()
|
||||
{
|
||||
@@ -483,7 +485,9 @@ internal static class StartGameHostPatch
|
||||
{ RoleTypes.Shapeshifter, AddShapeshifterNum },
|
||||
{ RoleTypes.Noisemaker, AddNoisemakerNum },
|
||||
{ RoleTypes.Phantom, AddPhantomNum },
|
||||
{ RoleTypes.Tracker, AddTrackerNum }
|
||||
{ RoleTypes.Tracker, AddTrackerNum },
|
||||
{ RoleTypes.Detective, AddDetectiveNum },
|
||||
{ RoleTypes.Viper, AddViperNum }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -690,6 +694,8 @@ internal static class StartGameHostPatch
|
||||
bool nimbleSpawn = random.Next(100) < (Options.CustomAdtRoleSpawnRate.TryGetValue(CustomRoles.Nimble, out IntegerOptionItem option2) ? option2.GetFloat() : 0) && CustomRoles.Nimble.IsEnable();
|
||||
bool finderSpawn = random.Next(100) < (Options.CustomAdtRoleSpawnRate.TryGetValue(CustomRoles.Finder, out IntegerOptionItem option3) ? option3.GetFloat() : 0) && CustomRoles.Finder.IsEnable();
|
||||
bool noisySpawn = random.Next(100) < (Options.CustomAdtRoleSpawnRate.TryGetValue(CustomRoles.Noisy, out IntegerOptionItem option4) ? option4.GetFloat() : 0) && CustomRoles.Noisy.IsEnable();
|
||||
bool examinerSpawn = random.Next(100) < (Options.CustomAdtRoleSpawnRate.TryGetValue(CustomRoles.Examiner, out IntegerOptionItem option5) ? option5.GetFloat() : 0) && CustomRoles.Examiner.IsEnable();
|
||||
bool venomSpawn = random.Next(100) < (Options.CustomAdtRoleSpawnRate.TryGetValue(CustomRoles.Venom, out IntegerOptionItem option6) ? option6.GetFloat() : 0) && CustomRoles.Venom.IsEnable();
|
||||
|
||||
if (Options.EveryoneCanVent.GetBool())
|
||||
{
|
||||
@@ -697,12 +703,13 @@ internal static class StartGameHostPatch
|
||||
physicistSpawn = false;
|
||||
finderSpawn = false;
|
||||
noisySpawn = false;
|
||||
examinerSpawn = false;
|
||||
}
|
||||
|
||||
HashSet<byte> bloodlustList = [], nimbleList = [], physicistList = [], finderList = [], noisyList = [];
|
||||
HashSet<byte> bloodlustList = [], nimbleList = [], physicistList = [], finderList = [], noisyList = [], examinerList = [], venomList = [];
|
||||
bool hasBanned = Main.NeverSpawnTogetherCombos.TryGetValue(OptionItem.CurrentPreset, out Dictionary<CustomRoles, List<CustomRoles>> banned);
|
||||
|
||||
if (nimbleSpawn || physicistSpawn || finderSpawn || noisySpawn || bloodlustSpawn)
|
||||
if (nimbleSpawn || physicistSpawn || finderSpawn || noisySpawn || bloodlustSpawn || examinerSpawn || venomSpawn)
|
||||
{
|
||||
foreach (PlayerControl player in Main.AllPlayerControls)
|
||||
{
|
||||
@@ -715,6 +722,8 @@ internal static class StartGameHostPatch
|
||||
bool physicistBanned = hasBanned && banned.Any(x => x.Key == kp.Value && x.Value.Contains(CustomRoles.Physicist));
|
||||
bool finderBanned = hasBanned && banned.Any(x => x.Key == kp.Value && x.Value.Contains(CustomRoles.Finder));
|
||||
bool noisyBanned = hasBanned && banned.Any(x => x.Key == kp.Value && x.Value.Contains(CustomRoles.Noisy));
|
||||
bool examinerBanned = hasBanned && banned.Any(x => x.Key == kp.Value && x.Value.Contains(CustomRoles.Examiner));
|
||||
bool venomBanned = hasBanned && banned.Any(x => x.Key == kp.Value && x.Value.Contains(CustomRoles.Venom));
|
||||
|
||||
if (kp.Value.IsCrewmate())
|
||||
{
|
||||
@@ -726,8 +735,12 @@ internal static class StartGameHostPatch
|
||||
if (!physicistBanned) physicistList.Add(player.PlayerId);
|
||||
if (!finderBanned) finderList.Add(player.PlayerId);
|
||||
if (!noisyBanned) noisyList.Add(player.PlayerId);
|
||||
if (!examinerBanned) examinerList.Add(player.PlayerId);
|
||||
}
|
||||
}
|
||||
|
||||
if (kp.Value.IsImpostor() && kp.Value.GetRoleTypes() == RoleTypes.Impostor && !venomBanned)
|
||||
venomList.Add(player.PlayerId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -737,7 +750,9 @@ internal static class StartGameHostPatch
|
||||
{ CustomRoles.Nimble, (nimbleSpawn, nimbleList) },
|
||||
{ CustomRoles.Physicist, (physicistSpawn, physicistList) },
|
||||
{ CustomRoles.Finder, (finderSpawn, finderList) },
|
||||
{ CustomRoles.Noisy, (noisySpawn, noisyList) }
|
||||
{ CustomRoles.Noisy, (noisySpawn, noisyList) },
|
||||
{ CustomRoles.Examiner, (examinerSpawn, examinerList) },
|
||||
{ CustomRoles.Venom, (venomSpawn, venomList) }
|
||||
};
|
||||
|
||||
for (var i = 0; i < roleSpawnMapping.Count; i++)
|
||||
@@ -875,7 +890,7 @@ internal static class StartGameHostPatch
|
||||
{
|
||||
foreach (CustomRoles role in item.Value)
|
||||
{
|
||||
if (role is CustomRoles.Nimble or CustomRoles.Physicist or CustomRoles.Bloodlust or CustomRoles.Finder or CustomRoles.Noisy) continue;
|
||||
if (role is CustomRoles.Nimble or CustomRoles.Physicist or CustomRoles.Bloodlust or CustomRoles.Finder or CustomRoles.Noisy or CustomRoles.Examiner or CustomRoles.Venom) continue;
|
||||
|
||||
state.SetSubRole(role);
|
||||
if (overrideLovers && role == CustomRoles.Lovers) Main.LoversPlayers.Add(Utils.GetPlayerById(item.Key));
|
||||
@@ -1238,10 +1253,10 @@ internal static class StartGameHostPatch
|
||||
|
||||
if (Options.CurrentGameMode == CustomGameMode.Standard)
|
||||
{
|
||||
if (target.Is(Team.Crewmate) && roleType is not (RoleTypes.Crewmate or RoleTypes.Scientist or RoleTypes.Engineer or RoleTypes.Noisemaker or RoleTypes.Tracker or RoleTypes.CrewmateGhost or RoleTypes.GuardianAngel))
|
||||
if (target.Is(Team.Crewmate) && roleType is not (RoleTypes.Crewmate or RoleTypes.Scientist or RoleTypes.Engineer or RoleTypes.Noisemaker or RoleTypes.Tracker or RoleTypes.Detective or RoleTypes.CrewmateGhost or RoleTypes.GuardianAngel))
|
||||
displayRole = RoleTypes.Crewmate;
|
||||
|
||||
if (target.Is(Team.Impostor) && roleType is not (RoleTypes.Impostor or RoleTypes.Shapeshifter or RoleTypes.Phantom or RoleTypes.ImpostorGhost))
|
||||
if (target.Is(Team.Impostor) && roleType is not (RoleTypes.Impostor or RoleTypes.Shapeshifter or RoleTypes.Phantom or RoleTypes.Viper or RoleTypes.ImpostorGhost))
|
||||
displayRole = RoleTypes.Impostor;
|
||||
}
|
||||
|
||||
@@ -1399,6 +1414,8 @@ internal static class StartGameHostPatch
|
||||
CustomRoles.Physicist => RoleTypes.Scientist,
|
||||
CustomRoles.Finder => RoleTypes.Tracker,
|
||||
CustomRoles.Noisy => RoleTypes.Noisemaker,
|
||||
CustomRoles.Examiner => RoleTypes.Detective,
|
||||
CustomRoles.Venom => RoleTypes.Viper,
|
||||
_ => roleType
|
||||
};
|
||||
}
|
||||
@@ -1536,6 +1553,8 @@ internal static class StartGameHostPatch
|
||||
CustomRoles.Physicist when roleTypes == RoleTypes.Crewmate => RoleTypes.Scientist,
|
||||
CustomRoles.Finder when roleTypes is RoleTypes.Crewmate or RoleTypes.Scientist or RoleTypes.Noisemaker => RoleTypes.Tracker,
|
||||
CustomRoles.Noisy when roleTypes == RoleTypes.Crewmate => RoleTypes.Noisemaker,
|
||||
CustomRoles.Examiner when roleTypes is RoleTypes.Crewmate or RoleTypes.Scientist or RoleTypes.Noisemaker => RoleTypes.Detective,
|
||||
CustomRoles.Venom when roleTypes == RoleTypes.Impostor => RoleTypes.Viper,
|
||||
_ => roleTypes
|
||||
}
|
||||
: roleTypes;
|
||||
|
||||
@@ -326,7 +326,7 @@ public static class PhantomRoleUseAbilityPatch
|
||||
|
||||
FastDestroyableSingleton<HudManager>.Instance.AbilityButton.SetSecondImage(__instance.Ability);
|
||||
FastDestroyableSingleton<HudManager>.Instance.AbilityButton.OverrideText(FastDestroyableSingleton<TranslationController>.Instance.GetString(StringNames.PhantomAbilityUndo, new Il2CppReferenceArray<Il2CppSystem.Object>(0)));
|
||||
__instance.Player.CmdCheckVanish(GameManager.Instance.LogicOptions.GetPhantomDuration());
|
||||
__instance.Player.CmdCheckVanish(GameManager.Instance.LogicOptions.GetRoleFloat(FloatOptionNames.PhantomDuration));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1258,8 +1258,8 @@ internal static class ReportDeadBodyPatch
|
||||
|
||||
if (tpc != null && !tpc.IsAlive())
|
||||
{
|
||||
if (player.Is(CustomRoles.Detective) && player.PlayerId != target.PlayerId)
|
||||
Detective.OnReportDeadBody(player, target.Object);
|
||||
if (player.Is(CustomRoles.Forensic) && player.PlayerId != target.PlayerId)
|
||||
Forensic.OnReportDeadBody(player, target.Object);
|
||||
else if (player.Is(CustomRoles.Sleuth) && player.PlayerId != target.PlayerId)
|
||||
{
|
||||
string msg = string.Format(GetString("SleuthMsg"), tpc.GetRealName(), tpc.GetDisplayRoleName());
|
||||
@@ -2444,6 +2444,8 @@ internal static class PlayerControlLocalSetRolePatch
|
||||
RoleTypes.Noisemaker => CustomRoles.NoisemakerEHR,
|
||||
RoleTypes.Scientist => CustomRoles.ScientistEHR,
|
||||
RoleTypes.Tracker => CustomRoles.TrackerEHR,
|
||||
RoleTypes.Detective => CustomRoles.DetectiveEHR,
|
||||
RoleTypes.Viper => CustomRoles.ViperEHR,
|
||||
_ => CustomRoles.NotAssigned
|
||||
};
|
||||
|
||||
|
||||
+34
-15
@@ -165,6 +165,8 @@
|
||||
"Noisemaker": "Noisemaker",
|
||||
"Tracker": "Tracker",
|
||||
"Phantom": "Phantom",
|
||||
"Detective": "Detective",
|
||||
"Viper": "Viper",
|
||||
"EngineerEHR": "Engineer",
|
||||
"ScientistEHR": "Scientist",
|
||||
"ShapeshifterEHR": "Shapeshifter",
|
||||
@@ -174,6 +176,8 @@
|
||||
"NoisemakerEHR": "Noisemaker",
|
||||
"TrackerEHR": "Tracker",
|
||||
"PhantomEHR": "Phantom",
|
||||
"DetectiveEHR": "Detective",
|
||||
"ViperEHR": "Viper",
|
||||
"BountyHunter": "Bounty Hunter",
|
||||
"Mare": "Mare",
|
||||
"FireWorks": "Fireworker",
|
||||
@@ -249,7 +253,7 @@
|
||||
"SpeedBooster": "Speed Booster",
|
||||
"Doctor": "Doctor",
|
||||
"Dictator": "Dictator",
|
||||
"Detective": "Detective",
|
||||
"Forensic": "Forensic",
|
||||
"NiceGuesser": "Nice Guesser",
|
||||
"Transporter": "Transporter",
|
||||
"TimeManager": "Time Manager",
|
||||
@@ -528,7 +532,7 @@
|
||||
"SpeedBoosterInfo": "Boost your speed",
|
||||
"DoctorInfo": "Know how each player died",
|
||||
"DictatorInfo": "Exile a player based on your own judgment",
|
||||
"DetectiveInfo": "Gain extra info from your body reports",
|
||||
"ForensicInfo": "Gain extra info from your body reports",
|
||||
"UndercoverInfo": "Impostors see you as their partner",
|
||||
"SwordsManInfo": "You can kill 1 player",
|
||||
"NiceGuesserInfo": "Guess <color=#ff1919>evil</color> roles in meetings to kill",
|
||||
@@ -757,7 +761,7 @@
|
||||
"SpeedBoosterInfoLong": "(Crewmates):\\nSpeed Booster increases a random player's movement speed every time they complete a task.",
|
||||
"DoctorInfoLong": "(Crewmates):\\nThe Doctor can view players' cause of death and access their vitals as long as their battery is still operational.",
|
||||
"DictatorInfoLong": "(Crewmates):\\nDictator can end the meeting by voting someone out, which will also result in their death.",
|
||||
"DetectiveInfoLong": "(Crewmate):\\nAfter reporting the body, the Detective receives a clue about the victim's role. The host may reveal the murderer's role to the Detective based on the setting. Note: Detective won't be Oblivious.",
|
||||
"ForensicInfoLong": "(Crewmate):\\nAfter reporting the body, the Forensic receives a clue about the victim's role. The host may reveal the murderer's role to the Forensic based on the setting. Note: Forensic won't be Oblivious.",
|
||||
"UndercoverInfoLong": "(Crewmates):\\nThe Impostors knows who Undercover is and sees him as a teammate, but Undercover himself does not know who the Impostors are.",
|
||||
"NiceGuesserInfoLong": "(Crewmates):\\nNice Guesser can guess a player's role during the meeting. Correct guess results in killing the target, while a wrong one leads to suicide. Use the command /bt [player id] [role] to guess. You can see player IDs before their names or use the /id command.",
|
||||
"SwordsManInfoLong": "(Crewmates):\\nVigilante can kill anyone, but only once. After killing, Vigilante can do tasks. Depending on settings, Vigilante can vent.",
|
||||
@@ -854,7 +858,7 @@
|
||||
"TorchInfoLong": "(Add-ons):\\nOnly Crewmates will get Torch, who have increased vision and may not be affected by Lights Sabotage.",
|
||||
"SeerInfoLong": "(Add-ons):\\nWhen a player dies, the Seer sees a red flash (with an alarm sound like sabotage).",
|
||||
"BrakarInfoLong": "(Add-ons):\\nIn case of a tie, the target voted by the Tiebreaker has priority. However, if multiple Tiebreakers choose different targets simultaneously, their skills will not take effect.",
|
||||
"ObliviousInfoLong": "(Add-ons):\\nDetective and Cleaners won't be Oblivious. Oblivious cannot report dead bodies. Note: Bait killed by Oblivious will still be reported automatically, and Oblivious can still be used as a scapegoat for Anonymous.",
|
||||
"ObliviousInfoLong": "(Add-ons):\\nForensic and Cleaners won't be Oblivious. Oblivious cannot report dead bodies. Note: Bait killed by Oblivious will still be reported automatically, and Oblivious can still be used as a scapegoat for Anonymous.",
|
||||
"BewilderInfoLong": "(Add-ons):\\nBewilder's vision changes killer's vision on death.",
|
||||
"TruantInfoLong": "(Add-ons):\\nAfter each meeting, you freeze in place for a set amount of seconds.",
|
||||
"WorkhorseInfoLong": "(Add-ons):\\nComplete all tasks to become Workhorse and get extra tasks set by the host.",
|
||||
@@ -1524,10 +1528,10 @@
|
||||
"CrewKillingRed": "<color=#8cffff>Crewmate</color> Killings can be red",
|
||||
"PsychicCanSeeNum": "Max number of red names",
|
||||
"PsychicFresh": "New red names every meeting",
|
||||
"DetectiveCanknowKiller": "Can find the killer's role",
|
||||
"DetectiveCanknowDeathReason": "Can find the cause of death",
|
||||
"DetectiveCanknowAddons": "Can find the dead player's add-ons",
|
||||
"DetectiveCanknowKillTime": "Can find how long ago the player died",
|
||||
"ForensicCanknowKiller": "Can find the killer's role",
|
||||
"ForensicCanknowDeathReason": "Can find the cause of death",
|
||||
"ForensicCanknowAddons": "Can find the dead player's add-ons",
|
||||
"ForensicCanknowKillTime": "Can find how long ago the player died",
|
||||
"ParanoiaVentCooldown": "Vent Cooldown",
|
||||
"ParanoiaNumOfUseButton": "Max number of portable buttons",
|
||||
"EveryOneKnowSuperStar": "Everyone knows the <color=#f6f657>Super Star</color>",
|
||||
@@ -2113,12 +2117,12 @@
|
||||
"MafiaKillSucceed": "<b>{0}</b> was killed by the Nemesis!",
|
||||
"MafiaKillDisable": "Sorry, but according to Host's settings, Nemesis revenge is prohibited in this game",
|
||||
"SuperStarDead": "Shock! Super Star <b>{0}</b> has unfortunately been mercilessly killed in the recent period of time!",
|
||||
"DetectiveNoticeVictim": "According to your investigation,\\nthe victim (<b>{0}</b>) had the role [{1}]",
|
||||
"DetectiveNoticeKiller": "\\nThe killer's role is <b>{0}</b>",
|
||||
"DetectiveNoticeKillerNotFound": "The Detective couldn't find evidence leading to a murderer, this is most likely suicide.",
|
||||
"DetectiveNoticeDeathReason": "\\nThe victim's cause of death is <b>{0}</b>",
|
||||
"DetectiveNoticeAddons": "\\nThe victim's add-ons are: <b>{0}</b>",
|
||||
"DetectiveNoticeKillTime": "\\nThe victim died <b>{0}</b> seconds ago",
|
||||
"ForensicNoticeVictim": "According to your investigation,\\nthe victim (<b>{0}</b>) had the role [{1}]",
|
||||
"ForensicNoticeKiller": "\\nThe killer's role is <b>{0}</b>",
|
||||
"ForensicNoticeKillerNotFound": "The Forensic couldn't find evidence leading to a murderer, this is most likely suicide.",
|
||||
"ForensicNoticeDeathReason": "\\nThe victim's cause of death is <b>{0}</b>",
|
||||
"ForensicNoticeAddons": "\\nThe victim's add-ons are: <b>{0}</b>",
|
||||
"ForensicNoticeKillTime": "\\nThe victim died <b>{0}</b> seconds ago",
|
||||
"SleuthMsg": "{0}'s role is: {1}",
|
||||
"GodNoticeAlive": "During the meeting, each player felt a revelation from heaven, and it turned out that God is still alive!",
|
||||
"WorkaholicAdviceAlive": "It's not recommended to kill or vote <b>{0}</b> out. Doing so will help them finish their tasks quicker.",
|
||||
@@ -2934,7 +2938,7 @@
|
||||
"MessageFromTheHost": "★ Host message ★",
|
||||
"SayTitle": "★ Moderator message ★",
|
||||
"MessageFromEAC": "★ EAC ★",
|
||||
"DetectiveNoticeTitle": "★ Message for the Detective ★",
|
||||
"ForensicNoticeTitle": "★ Message for the Forensic ★",
|
||||
"GuessKillTitle": "★ Message about Guessing ★",
|
||||
"SuperStarNewsTitle": "★ Urgent news ★",
|
||||
"GodAliveTitle": "★ Message about God ★",
|
||||
@@ -3022,6 +3026,8 @@
|
||||
"EnterVentWinCountDown": "Enter vent within <b>{0}</b> seconds to win!",
|
||||
"InvalidArgs": "Invalid Args",
|
||||
"InvalidArguments": "Invalid Arguments",
|
||||
"DetectiveSuspectLimit": "Suspects Per Case",
|
||||
"ViperDissolveTime": "Body Dissolve Time",
|
||||
"On": "Always",
|
||||
"Off": "OFF",
|
||||
"ColoredOn": "<color=#00fefe><b>✓</b></color>",
|
||||
@@ -3123,6 +3129,9 @@
|
||||
"AbilityButtonText.Impostor": "Haunt",
|
||||
"AbilityButtonText.Shapeshifter": "Shift",
|
||||
"AbilityButtonText.Phantom": "Vanish",
|
||||
"AbilityButtonText.Viper": "Acid",
|
||||
"AbilityButtonText.Detective": "Notes",
|
||||
"SecondaryAbilityButtonText.Detective": "Interrogate",
|
||||
"GauloisKillButtonText": "Speed Up",
|
||||
"SniperSnipeButtonText": "Snipe",
|
||||
"FireWorksExplosionButtonText": "Detonate",
|
||||
@@ -9100,6 +9109,16 @@
|
||||
"AntidoteCDOpt": "Decrease the cooldown by",
|
||||
"AntidoteCDReset": "Cooldown returns to normal after a meeting",
|
||||
"HackButtonText": "Mimic",
|
||||
"DetectiveEHRInfo": "Gather Info, Solve Murders",
|
||||
"DetectiveEHRInfoLong": "(Crewmates):\\nAs the Detective, you can write down notes about each crime scene and interrogate suspects.",
|
||||
"ViperEHRInfo": "Kill to Dissolve Bodies",
|
||||
"ViperEHRInfoLong": "(Impostors):\\nAs the Viper, the bodies you leave behind slowly dissolve due to your acid, making them disappear and unreportable.",
|
||||
"Explosivist": "Explosivist",
|
||||
"ExplosivistInfo": "Explode Time Bombs",
|
||||
"ExplosivistInfoLong": "(Neutrals):\\nAs the Explosivist, you cannot kill normally. Instead, you can pet/vanish to develop a bomb and start carrying it. Others will only see the bomb itself, and you standing in place where you've started to use your ability. After a few seconds, the bomb explodes, killing everyone nearby, and you teleport back to where you started carrying the bomb.\\nKill everyone to win!",
|
||||
"Explosivist.ExplosionDelay": "Explosion Delay",
|
||||
"Explosivist.ExplosionRadius": "Explosion Radius",
|
||||
"ExplosivistSuffix": "<size=80%>Carrying the bomb</size>\\n<#ffff00>Explodes in </color>{0}s",
|
||||
"BomberCooldownsResetEachOther": "Kill Cooldown & Bomb Cooldown Reset Each Other When Used",
|
||||
"BomberDiesInExplosion": "<color=#ff1919>Bomber</color> dies in their explosion",
|
||||
"ImpostorsSurviveBombs": "<color=#ff1919>Impostors</color> survive bombs",
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace EHR.AddOns.Crewmate;
|
||||
|
||||
public class Examiner : IAddon
|
||||
{
|
||||
public AddonTypes Type => AddonTypes.Helpful;
|
||||
|
||||
public static OptionItem ExaminerSuspectLimit;
|
||||
|
||||
public void SetupCustomOption()
|
||||
{
|
||||
Options.SetupAdtRoleOptions(654400, CustomRoles.Examiner, canSetNum: true);
|
||||
|
||||
ExaminerSuspectLimit = new FloatOptionItem(654410, "DetectiveSuspectLimit", new(1f, 30f, 1f), 4f, TabGroup.Addons)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.DetectiveEHR])
|
||||
.SetValueFormat(OptionFormat.Players);
|
||||
}
|
||||
}
|
||||
@@ -68,7 +68,7 @@ public class Workhorse : IAddon
|
||||
{
|
||||
if (!pc.IsAlive() || IsThisRole(pc.PlayerId)) return false;
|
||||
if (pc.Is(CustomRoles.Needy) || pc.Is(CustomRoles.Lazy) || pc.Is(CustomRoles.Bloodlust)) return false;
|
||||
if (pc.GetCustomRole().GetVNRole(true) is CustomRoles.Impostor or CustomRoles.ImpostorEHR or CustomRoles.Shapeshifter or CustomRoles.ShapeshifterEHR or CustomRoles.Phantom or CustomRoles.PhantomEHR) return false;
|
||||
if (pc.GetCustomRole().GetVNRole(true) is CustomRoles.Impostor or CustomRoles.ImpostorEHR or CustomRoles.Shapeshifter or CustomRoles.ShapeshifterEHR or CustomRoles.Phantom or CustomRoles.PhantomEHR or CustomRoles.Viper or CustomRoles.ViperEHR) return false;
|
||||
|
||||
TaskState taskState = pc.GetTaskState();
|
||||
if (taskState.CompletedTasksCount + 1 < taskState.AllTasksCount) return false;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace EHR.AddOns.Impostor;
|
||||
|
||||
public class Venom : IAddon
|
||||
{
|
||||
public AddonTypes Type => AddonTypes.Helpful;
|
||||
|
||||
public static OptionItem VenomDissolveTime;
|
||||
|
||||
public void SetupCustomOption()
|
||||
{
|
||||
Options.SetupAdtRoleOptions(654500, CustomRoles.Venom, canSetNum: true);
|
||||
|
||||
VenomDissolveTime = new FloatOptionItem(654510, "ViperDissolveTime", new(0f, 60f, 0.5f), 10f, TabGroup.Addons)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.ViperEHR])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
}
|
||||
}
|
||||
@@ -76,11 +76,13 @@ internal class Analyst : RoleBase
|
||||
CustomRoles.Impostor or CustomRoles.ImpostorEHR => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Impostor), GetString("Impostor")),
|
||||
CustomRoles.Shapeshifter or CustomRoles.ShapeshifterEHR => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Speedrunner), GetString("Shapeshifter")),
|
||||
CustomRoles.Phantom or CustomRoles.PhantomEHR => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Witness), GetString("Phantom")),
|
||||
CustomRoles.Viper or CustomRoles.ViperEHR => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Poisoner), GetString("Viper")),
|
||||
CustomRoles.Crewmate or CustomRoles.CrewmateEHR => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Crewmate), GetString("Crewmate")),
|
||||
CustomRoles.Engineer or CustomRoles.EngineerEHR => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Autocrat), GetString("Engineer")),
|
||||
CustomRoles.Scientist or CustomRoles.ScientistEHR => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Doctor), GetString("Scientist")),
|
||||
CustomRoles.Noisemaker or CustomRoles.NoisemakerEHR => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Bubble), GetString("Noisemaker")),
|
||||
CustomRoles.Tracker or CustomRoles.TrackerEHR => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Scout), GetString("Tracker")),
|
||||
CustomRoles.Detective or CustomRoles.DetectiveEHR => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Forensic), GetString("Detective")),
|
||||
_ => string.Empty
|
||||
}
|
||||
: string.Empty;
|
||||
|
||||
@@ -14,6 +14,7 @@ internal class CrewmateVanillaRoles : IVanillaSettingHolder
|
||||
public static OptionItem TrackerCooldown;
|
||||
public static OptionItem TrackerDuration;
|
||||
public static OptionItem TrackerDelay;
|
||||
public static OptionItem DetectiveSuspectLimit;
|
||||
public TabGroup Tab => TabGroup.CrewmateRoles;
|
||||
|
||||
public void SetupCustomOption()
|
||||
@@ -65,5 +66,11 @@ internal class CrewmateVanillaRoles : IVanillaSettingHolder
|
||||
TrackerDelay = new FloatOptionItem(5064, "TrackerDelay", new(1f, 250f, 1f), 5f, Tab)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.TrackerEHR])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
|
||||
SetupRoleOptions(5080, Tab, CustomRoles.DetectiveEHR);
|
||||
|
||||
DetectiveSuspectLimit = new FloatOptionItem(5082, "DetectiveSuspectLimit", new(1f, 30f, 1f), 4f, Tab)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.DetectiveEHR])
|
||||
.SetValueFormat(OptionFormat.Players);
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace EHR.Crewmate;
|
||||
|
||||
internal class Detective : RoleBase
|
||||
{
|
||||
public static OptionItem DetectiveCanknowKiller;
|
||||
public static OptionItem DetectiveCanknowDeathReason;
|
||||
public static OptionItem DetectiveCanknowAddons;
|
||||
public static OptionItem DetectiveCanknowKillTime;
|
||||
|
||||
public static Dictionary<byte, string> DetectiveNotify = [];
|
||||
|
||||
public override bool IsEnable => false;
|
||||
|
||||
public override void SetupCustomOption()
|
||||
{
|
||||
Options.SetupRoleOptions(6600, TabGroup.CrewmateRoles, CustomRoles.Detective);
|
||||
|
||||
DetectiveCanknowKiller = new BooleanOptionItem(6610, "DetectiveCanknowKiller", true, TabGroup.CrewmateRoles)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Detective]);
|
||||
|
||||
DetectiveCanknowDeathReason = new BooleanOptionItem(6611, "DetectiveCanknowDeathReason", true, TabGroup.CrewmateRoles)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Detective]);
|
||||
|
||||
DetectiveCanknowAddons = new BooleanOptionItem(6612, "DetectiveCanknowAddons", true, TabGroup.CrewmateRoles)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Detective]);
|
||||
|
||||
DetectiveCanknowKillTime = new BooleanOptionItem(6613, "DetectiveCanknowKillTime", true, TabGroup.CrewmateRoles)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Detective]);
|
||||
}
|
||||
|
||||
public override void Init() { }
|
||||
|
||||
public override void Add(byte playerId) { }
|
||||
|
||||
public static void OnReportDeadBody(PlayerControl player, PlayerControl tpc)
|
||||
{
|
||||
string msg = string.Format(Translator.GetString("DetectiveNoticeVictim"), tpc.GetRealName(), tpc.GetCustomRole().ToColoredString());
|
||||
|
||||
if (DetectiveCanknowKiller.GetBool())
|
||||
{
|
||||
PlayerControl realKiller = tpc.GetRealKiller();
|
||||
|
||||
if (realKiller == null)
|
||||
msg += ";" + Translator.GetString("DetectiveNoticeKillerNotFound");
|
||||
else
|
||||
msg += ";" + string.Format(Translator.GetString("DetectiveNoticeKiller"), realKiller.GetCustomRole().ToColoredString());
|
||||
}
|
||||
|
||||
if (DetectiveCanknowDeathReason.GetBool()) msg += ";" + string.Format(Translator.GetString("DetectiveNoticeDeathReason"), Translator.GetString($"DeathReason.{Main.PlayerStates[tpc.PlayerId].deathReason}"));
|
||||
|
||||
if (DetectiveCanknowAddons.GetBool()) msg += ";" + string.Format(Translator.GetString("DetectiveNoticeAddons"), string.Join(", ", tpc.GetCustomSubRoles().Select(x => x.ToColoredString())));
|
||||
|
||||
if (DetectiveCanknowKillTime.GetBool())
|
||||
{
|
||||
DateTime deathTimeStamp = Main.PlayerStates[tpc.PlayerId].RealKiller.TimeStamp;
|
||||
DateTime now = DateTime.Now;
|
||||
double timeSpanSeconds = (now - deathTimeStamp).TotalSeconds;
|
||||
msg += ";" + string.Format(Translator.GetString("DetectiveNoticeKillTime"), (int)timeSpanSeconds);
|
||||
}
|
||||
|
||||
DetectiveNotify[player.PlayerId] = msg;
|
||||
}
|
||||
}
|
||||
@@ -128,7 +128,7 @@ public class Farseer : RoleBase
|
||||
}
|
||||
else
|
||||
{
|
||||
float range = NormalGameOptionsV09.KillDistances[Mathf.Clamp(player.Is(CustomRoles.Reach) ? 2 : Main.NormalOptions.KillDistance, 0, 2)] + 0.5f;
|
||||
float range = NormalGameOptionsV10.KillDistances[Mathf.Clamp(player.Is(CustomRoles.Reach) ? 2 : Main.NormalOptions.KillDistance, 0, 2)] + 0.5f;
|
||||
float dis = Vector2.Distance(player.Pos(), arTarget.Pos());
|
||||
|
||||
if (dis <= range)
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace EHR.Crewmate;
|
||||
|
||||
internal class Forensic : RoleBase
|
||||
{
|
||||
public static OptionItem ForensicCanknowKiller;
|
||||
public static OptionItem ForensicCanknowDeathReason;
|
||||
public static OptionItem ForensicCanknowAddons;
|
||||
public static OptionItem ForensicCanknowKillTime;
|
||||
|
||||
public static Dictionary<byte, string> ForensicNotify = [];
|
||||
|
||||
public override bool IsEnable => false;
|
||||
|
||||
public override void SetupCustomOption()
|
||||
{
|
||||
Options.SetupRoleOptions(6600, TabGroup.CrewmateRoles, CustomRoles.Forensic);
|
||||
|
||||
ForensicCanknowKiller = new BooleanOptionItem(6610, "ForensicCanknowKiller", true, TabGroup.CrewmateRoles)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Forensic]);
|
||||
|
||||
ForensicCanknowDeathReason = new BooleanOptionItem(6611, "ForensicCanknowDeathReason", true, TabGroup.CrewmateRoles)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Forensic]);
|
||||
|
||||
ForensicCanknowAddons = new BooleanOptionItem(6612, "ForensicCanknowAddons", true, TabGroup.CrewmateRoles)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Forensic]);
|
||||
|
||||
ForensicCanknowKillTime = new BooleanOptionItem(6613, "ForensicCanknowKillTime", true, TabGroup.CrewmateRoles)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Forensic]);
|
||||
}
|
||||
|
||||
public override void Init() { }
|
||||
|
||||
public override void Add(byte playerId) { }
|
||||
|
||||
public static void OnReportDeadBody(PlayerControl player, PlayerControl tpc)
|
||||
{
|
||||
string msg = string.Format(Translator.GetString("ForensicNoticeVictim"), tpc.GetRealName(), tpc.GetCustomRole().ToColoredString());
|
||||
|
||||
if (ForensicCanknowKiller.GetBool())
|
||||
{
|
||||
PlayerControl realKiller = tpc.GetRealKiller();
|
||||
|
||||
if (realKiller == null)
|
||||
msg += ";" + Translator.GetString("ForensicNoticeKillerNotFound");
|
||||
else
|
||||
msg += ";" + string.Format(Translator.GetString("ForensicNoticeKiller"), realKiller.GetCustomRole().ToColoredString());
|
||||
}
|
||||
|
||||
if (ForensicCanknowDeathReason.GetBool()) msg += ";" + string.Format(Translator.GetString("ForensicNoticeDeathReason"), Translator.GetString($"DeathReason.{Main.PlayerStates[tpc.PlayerId].deathReason}"));
|
||||
|
||||
if (ForensicCanknowAddons.GetBool()) msg += ";" + string.Format(Translator.GetString("ForensicNoticeAddons"), string.Join(", ", tpc.GetCustomSubRoles().Select(x => x.ToColoredString())));
|
||||
|
||||
if (ForensicCanknowKillTime.GetBool())
|
||||
{
|
||||
DateTime deathTimeStamp = Main.PlayerStates[tpc.PlayerId].RealKiller.TimeStamp;
|
||||
DateTime now = DateTime.Now;
|
||||
double timeSpanSeconds = (now - deathTimeStamp).TotalSeconds;
|
||||
msg += ";" + string.Format(Translator.GetString("ForensicNoticeKillTime"), (int)timeSpanSeconds);
|
||||
}
|
||||
|
||||
ForensicNotify[player.PlayerId] = msg;
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ public class Scout : RoleBase
|
||||
private static OptionItem OptionCanSeeLastRoomInMeeting;
|
||||
private static OptionItem CanGetColoredArrow;
|
||||
public static OptionItem HideVote;
|
||||
public static OptionItem TrackerAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem ScoutAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
@@ -48,7 +48,7 @@ public class Scout : RoleBase
|
||||
HideVote = new BooleanOptionItem(Id + 8, "TrackerHideVote", false, TabGroup.CrewmateRoles)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Scout]);
|
||||
|
||||
TrackerAbilityUseGainWithEachTaskCompleted = new FloatOptionItem(Id + 9, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.05f), 1f, TabGroup.CrewmateRoles)
|
||||
ScoutAbilityUseGainWithEachTaskCompleted = new FloatOptionItem(Id + 9, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.05f), 1f, TabGroup.CrewmateRoles)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Scout])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
|
||||
|
||||
@@ -191,7 +191,7 @@ public class Deathpact : RoleBase
|
||||
|
||||
foreach (PlayerControl player in dp.PlayersInDeathpact)
|
||||
{
|
||||
float range = NormalGameOptionsV09.KillDistances[Mathf.Clamp(player.Is(CustomRoles.Reach) ? 2 : Main.NormalOptions.KillDistance, 0, 2)] + 0.5f;
|
||||
float range = NormalGameOptionsV10.KillDistances[Mathf.Clamp(player.Is(CustomRoles.Reach) ? 2 : Main.NormalOptions.KillDistance, 0, 2)] + 0.5f;
|
||||
cancelDeathpact = dp.PlayersInDeathpact.Where(a => a.PlayerId != player.PlayerId).Select(otherPlayerInPact => Vector2.Distance(player.Pos(), otherPlayerInPact.Pos())).Aggregate(cancelDeathpact, (current, dis) => current && dis <= range);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ internal class ImpostorVanillaRoles : IVanillaSettingHolder
|
||||
public static OptionItem PhantomDuration;
|
||||
public static OptionItem ShapeshiftCD;
|
||||
public static OptionItem ShapeshiftDur;
|
||||
public static OptionItem ViperDissolveTime;
|
||||
public TabGroup Tab => TabGroup.ImpostorRoles;
|
||||
|
||||
public void SetupCustomOption()
|
||||
@@ -32,5 +33,11 @@ internal class ImpostorVanillaRoles : IVanillaSettingHolder
|
||||
ShapeshiftDur = new FloatOptionItem(403, "ShapeshiftDuration", new(1f, 60f, 1f), 10f, Tab)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.ShapeshifterEHR])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
|
||||
SetupRoleOptions(410, Tab, CustomRoles.ViperEHR);
|
||||
|
||||
ViperDissolveTime = new FloatOptionItem(412, "ViperDissolveTime", new(0f, 60f, 0.5f), 10f, Tab)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.ViperEHR])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ public class Psychopath : RoleBase
|
||||
{
|
||||
if (!GameStates.IsInTask || ExileController.Instance || AntiBlackout.SkipTasks || Main.KillTimers[pc.PlayerId] > 0f || Count++ < 10) return;
|
||||
var pos = pc.Pos();
|
||||
var killRange = NormalGameOptionsV09.KillDistances[Mathf.Clamp(Main.NormalOptions.KillDistance, 0, 2)];
|
||||
var killRange = NormalGameOptionsV10.KillDistances[Mathf.Clamp(Main.NormalOptions.KillDistance, 0, 2)];
|
||||
var closestPlayer = Main.AllAlivePlayerControls.Select(x => (pc: x, distance: Vector2.Distance(x.Pos(), pos))).Where(x => x.distance <= killRange).MinBy(x => x.distance).pc;
|
||||
if (closestPlayer == null) return;
|
||||
Count = 0;
|
||||
|
||||
@@ -202,7 +202,7 @@ internal class Puppeteer : RoleBase
|
||||
{
|
||||
KeyValuePair<byte, float> min = targetDistance.OrderBy(c => c.Value).FirstOrDefault();
|
||||
PlayerControl target = Utils.GetPlayerById(min.Key);
|
||||
float killRange = NormalGameOptionsV09.KillDistances[Mathf.Clamp(Main.NormalOptions.KillDistance, 0, 2)];
|
||||
float killRange = NormalGameOptionsV10.KillDistances[Mathf.Clamp(Main.NormalOptions.KillDistance, 0, 2)];
|
||||
|
||||
if (min.Value <= killRange && player.CanMove && target.CanMove)
|
||||
{
|
||||
|
||||
@@ -199,7 +199,7 @@ public class Agitater : RoleBase
|
||||
{
|
||||
KeyValuePair<byte, float> min = targetDistance.OrderBy(c => c.Value).FirstOrDefault();
|
||||
PlayerControl target = Utils.GetPlayerById(min.Key);
|
||||
float KillRange = NormalGameOptionsV09.KillDistances[Mathf.Clamp(GameOptionsManager.Instance.currentNormalGameOptions.KillDistance, 0, 2)];
|
||||
float KillRange = NormalGameOptionsV10.KillDistances[Mathf.Clamp(GameOptionsManager.Instance.currentNormalGameOptions.KillDistance, 0, 2)];
|
||||
if (min.Value <= KillRange && player.CanMove && target.CanMove) PassBomb(player, target);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ internal class Arsonist : RoleBase
|
||||
}
|
||||
else
|
||||
{
|
||||
float range = NormalGameOptionsV09.KillDistances[Mathf.Clamp(player.Is(CustomRoles.Reach) ? 2 : Main.NormalOptions.KillDistance, 0, 2)] + 0.5f;
|
||||
float range = NormalGameOptionsV10.KillDistances[Mathf.Clamp(player.Is(CustomRoles.Reach) ? 2 : Main.NormalOptions.KillDistance, 0, 2)] + 0.5f;
|
||||
float dis = Vector2.Distance(player.Pos(), arTarget.Pos());
|
||||
|
||||
if (dis <= range)
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
using System.Linq;
|
||||
using AmongUs.GameOptions;
|
||||
using Hazel;
|
||||
|
||||
namespace EHR.Neutral;
|
||||
|
||||
public class Explosivist : RoleBase
|
||||
{
|
||||
public static bool On;
|
||||
|
||||
public static OptionItem AbilityCooldown;
|
||||
private static OptionItem ImpostorVision;
|
||||
public static OptionItem ExplosionDelay;
|
||||
private static OptionItem ExplosionRadius;
|
||||
|
||||
public override bool IsEnable => On;
|
||||
|
||||
private TNT Explosive;
|
||||
private Vector2 RealPosition;
|
||||
private long ExplodeTS;
|
||||
private byte ExplosivistId;
|
||||
|
||||
public override void SetupCustomOption()
|
||||
{
|
||||
StartSetup(654300)
|
||||
.AutoSetupOption(ref AbilityCooldown, 22.5f, new FloatValueRule(0f, 180f, 0.5f), OptionFormat.Seconds)
|
||||
.AutoSetupOption(ref ImpostorVision, true)
|
||||
.AutoSetupOption(ref ExplosionDelay, 10, new IntegerValueRule(1, 60, 1), OptionFormat.Seconds)
|
||||
.AutoSetupOption(ref ExplosionRadius, 4f, new FloatValueRule(0.25f, 10f, 0.25f), OptionFormat.Multiplier);
|
||||
}
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
On = false;
|
||||
}
|
||||
|
||||
public override void Add(byte playerId)
|
||||
{
|
||||
On = true;
|
||||
Explosive = null;
|
||||
RealPosition = Vector2.zero;
|
||||
ExplodeTS = 0;
|
||||
ExplosivistId = playerId;
|
||||
}
|
||||
|
||||
public override void SetKillCooldown(byte id)
|
||||
{
|
||||
Main.AllPlayerKillCooldown[id] = AbilityCooldown.GetFloat();
|
||||
}
|
||||
|
||||
public override void ApplyGameOptions(IGameOptions opt, byte id)
|
||||
{
|
||||
opt.SetVision(ImpostorVision.GetBool());
|
||||
|
||||
if (Options.UsePhantomBasis.GetBool() && Options.UsePhantomBasisForNKs.GetBool())
|
||||
{
|
||||
AURoleOptions.PhantomCooldown = AbilityCooldown.GetFloat();
|
||||
AURoleOptions.PhantomDuration = 1f;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanUseKillButton(PlayerControl pc)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool OnVanish(PlayerControl pc)
|
||||
{
|
||||
UseAbility(pc);
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void OnPet(PlayerControl pc)
|
||||
{
|
||||
UseAbility(pc);
|
||||
}
|
||||
|
||||
void UseAbility(PlayerControl player)
|
||||
{
|
||||
if (Explosive != null) return;
|
||||
|
||||
Vector2 pos = player.Pos();
|
||||
Explosive = new TNT(pos);
|
||||
RealPosition = pos;
|
||||
|
||||
// From https://github.com/Rabek009/MoreGamemodes/blob/master/Roles/Impostor/Concealing/Droner.cs
|
||||
foreach (var pc in PlayerControl.AllPlayerControls)
|
||||
{
|
||||
if (pc == player || pc.AmOwner) continue;
|
||||
CustomRpcSender sender = CustomRpcSender.Create("Explosivist", SendOption.Reliable);
|
||||
sender.StartMessage(pc.GetClientId());
|
||||
sender.StartRpc(player.NetTransform.NetId, (byte)RpcCalls.SnapTo)
|
||||
.WriteVector2(player.transform.position)
|
||||
.Write(player.NetTransform.lastSequenceId)
|
||||
.EndRpc();
|
||||
sender.StartRpc(player.NetTransform.NetId, (byte)RpcCalls.SnapTo)
|
||||
.WriteVector2(player.transform.position)
|
||||
.Write((ushort)(player.NetTransform.lastSequenceId + 16383))
|
||||
.EndRpc();
|
||||
sender.EndMessage();
|
||||
sender.SendMessage();
|
||||
Utils.NumSnapToCallsThisRound += 2;
|
||||
}
|
||||
|
||||
if (player.AmOwner) player.Visible = false;
|
||||
|
||||
ExplodeTS = Utils.TimeStamp + ExplosionDelay.GetInt();
|
||||
}
|
||||
|
||||
public override void OnFixedUpdate(PlayerControl pc)
|
||||
{
|
||||
if (!GameStates.IsInTask || ExileController.Instance || AntiBlackout.SkipTasks) return;
|
||||
|
||||
Explosive?.TP(pc.transform.position);
|
||||
|
||||
if (Explosive != null && ExplodeTS >= Utils.TimeStamp)
|
||||
{
|
||||
Utils.GetPlayersInRadius(ExplosionRadius.GetFloat(), Explosive.Position).Without(pc).Do(x => x.Suicide(PlayerState.DeathReason.Bombed, pc));
|
||||
|
||||
RevertFreeze(pc);
|
||||
if (!Options.UsePets.GetBool()) pc.RpcResetAbilityCooldown();
|
||||
|
||||
Explosive.Despawn();
|
||||
Explosive = null;
|
||||
RealPosition = Vector2.zero;
|
||||
ExplodeTS = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnReportDeadBody()
|
||||
{
|
||||
if (Explosive != null)
|
||||
{
|
||||
PlayerControl pc = ExplosivistId.GetPlayer();
|
||||
RevertFreeze(pc);
|
||||
}
|
||||
}
|
||||
|
||||
private void RevertFreeze(PlayerControl pc)
|
||||
{
|
||||
if (pc.AmOwner) pc.Visible = true;
|
||||
pc.NetTransform.SnapTo(RealPosition, (ushort)(pc.NetTransform.lastSequenceId + 128));
|
||||
CustomRpcSender sender = CustomRpcSender.Create("Explosivist Revert", SendOption.Reliable);
|
||||
sender.StartMessage();
|
||||
sender.StartRpc(pc.NetTransform.NetId, (byte)RpcCalls.SnapTo)
|
||||
.WriteVector2(pc.transform.position)
|
||||
.Write((ushort)(pc.NetTransform.lastSequenceId + 32767))
|
||||
.EndRpc();
|
||||
sender.StartRpc(pc.NetTransform.NetId, (byte)RpcCalls.SnapTo)
|
||||
.WriteVector2(pc.transform.position)
|
||||
.Write((ushort)(pc.NetTransform.lastSequenceId + 32767 + 16383))
|
||||
.EndRpc();
|
||||
sender.StartRpc(pc.NetTransform.NetId, (byte)RpcCalls.SnapTo)
|
||||
.WriteVector2(pc.transform.position)
|
||||
.Write(pc.NetTransform.lastSequenceId)
|
||||
.EndRpc();
|
||||
sender.EndMessage();
|
||||
sender.SendMessage();
|
||||
}
|
||||
|
||||
public override string GetSuffix(PlayerControl seer, PlayerControl target, bool hud = false, bool meeting = false)
|
||||
{
|
||||
if (seer.PlayerId != ExplosivistId || seer.PlayerId != target.PlayerId || (seer.IsModdedClient() && !hud) || meeting || ExplodeTS == 0) return string.Empty;
|
||||
return string.Format(Translator.GetString("ExplosivistSuffix"), ExplodeTS - Utils.TimeStamp);
|
||||
}
|
||||
}
|
||||
@@ -176,7 +176,7 @@ internal class Revolutionist : RoleBase
|
||||
}
|
||||
else
|
||||
{
|
||||
float range = NormalGameOptionsV09.KillDistances[Mathf.Clamp(player.Is(CustomRoles.Reach) ? 2 : Main.NormalOptions.KillDistance, 0, 2)] + 0.5f;
|
||||
float range = NormalGameOptionsV10.KillDistances[Mathf.Clamp(player.Is(CustomRoles.Reach) ? 2 : Main.NormalOptions.KillDistance, 0, 2)] + 0.5f;
|
||||
float dis = Vector2.Distance(player.Pos(), rvTarget.Pos());
|
||||
|
||||
if (dis <= range)
|
||||
|
||||
@@ -114,7 +114,7 @@ internal class Samurai : RoleBase
|
||||
PlayerControl target = Utils.GetPlayerById(Target.Id);
|
||||
if (target == null) return;
|
||||
|
||||
if (Vector2.Distance(target.Pos(), pc.Pos()) > NormalGameOptionsV09.KillDistances[Mathf.Clamp(pc.Is(CustomRoles.Reach) ? 2 : Main.NormalOptions.KillDistance, 0, 2)] + 0.5f)
|
||||
if (Vector2.Distance(target.Pos(), pc.Pos()) > NormalGameOptionsV10.KillDistances[Mathf.Clamp(pc.Is(CustomRoles.Reach) ? 2 : Main.NormalOptions.KillDistance, 0, 2)] + 0.5f)
|
||||
{
|
||||
Target = (byte.MaxValue, 0);
|
||||
pc.RpcCheckAndMurder(target);
|
||||
|
||||
Reference in new issue
Block a user