mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-21 21:43:34 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3817250793 | ||
|
|
3fdeaf6ef7 | ||
|
|
214783bbb5 | ||
|
|
ebb7367e61 | ||
|
|
c7434e5f06 | ||
|
|
3ec05fef35 | ||
|
|
2dc400be01 | ||
|
|
2ffab98391 | ||
|
|
e448341581 | ||
|
|
302b15d5d9 | ||
|
|
071b9256fd | ||
|
|
a85f9f5906 | ||
|
|
a656c4ea7f | ||
|
|
75560254ec | ||
|
|
f61226f65c | ||
|
|
f83b8f66d4 | ||
|
|
918deb5d5b |
No files matched your search
@@ -94,6 +94,14 @@ public static class Camouflage
|
||||
.Set("", 17, "hat_baseball_Black", "skin_Scientist-Darkskin", "visor_pusheenSmileVisor", "pet_Pip", "");
|
||||
break;
|
||||
}
|
||||
|
||||
if (Options.UsePets.GetBool() && CamouflageOutfit.PetId == "")
|
||||
{
|
||||
string[] pets = Options.PetToAssign;
|
||||
string pet = pets[Options.PetToAssignToEveryone.GetValue()];
|
||||
string petId = pet == "pet_RANDOM_FOR_EVERYONE" ? pets[IRandom.Instance.Next(0, pets.Length - 1)] : pet;
|
||||
CamouflageOutfit.PetId = petId;
|
||||
}
|
||||
}
|
||||
public static void CheckCamouflage()
|
||||
{
|
||||
|
||||
@@ -127,7 +127,7 @@ internal class CustomRoleSelector
|
||||
if (role.IsVanilla() || chance == 0 || role.IsAdditionRole() || (role.OnlySpawnsWithPets() && !Options.UsePets.GetBool())) continue;
|
||||
switch (role)
|
||||
{
|
||||
case CustomRoles.DarkHide when (MapNames)Main.NormalOptions.MapId == MapNames.Fungle:
|
||||
case CustomRoles.DarkHide when Main.CurrentMap == MapNames.Fungle:
|
||||
case CustomRoles.Pelican when AllRoles[RoleAssignType.Impostor].Any(x => x.Role == CustomRoles.Duellist):
|
||||
case CustomRoles.Duellist when AllRoles[RoleAssignType.NeutralKilling].Any(x => x.Role == CustomRoles.Pelican):
|
||||
case CustomRoles.VengefulRomantic:
|
||||
|
||||
@@ -70,7 +70,7 @@ public static class DevManager
|
||||
|
||||
// TOHE+ players
|
||||
DevUserList.Add(new(code: "crustzonal#9589", color: "#00FFFF", tag: "Translator PT-BR", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "artyleague01"));
|
||||
DevUserList.Add(new(code: "tinedpun#6584", color: "#0000ff", tag: "Translator PT-BR", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "Dechis")); // if you dont mind
|
||||
DevUserList.Add(new(code: "tinedpun#6584", color: "#0000ff", tag: "Translator PT-BR", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "Dechis"));
|
||||
DevUserList.Add(new(code: "swiftlord#0872", color: "null", tag: "null", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "But What About"));
|
||||
DevUserList.Add(new(code: "ovalinstep#2984", color: "null", tag: "null", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "Seleneous"));
|
||||
DevUserList.Add(new(code: "innerruler#4140", color: "null", tag: "null", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "thewhiskas27"));
|
||||
@@ -78,6 +78,9 @@ public static class DevManager
|
||||
DevUserList.Add(new(code: "crustzonal#9589", color: "null", tag: "null", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "aviiiv0102"));
|
||||
DevUserList.Add(new(code: "tubedilute#9062", color: "null", tag: "null", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "Xcl4udioX"));
|
||||
DevUserList.Add(new(code: "ponyholey#5532", color: "#0000FF", tag: "desenvolvedor", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "DrawingsZz"));
|
||||
DevUserList.Add(new(code: "akinlaptop#2206", color: "null", tag: "null", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "MR Carr"));
|
||||
DevUserList.Add(new(code: "fursilty#4676", color: "#0000ff", tag: "arthurzin", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "arthurzin"));
|
||||
DevUserList.Add(new(code: "stonefuzzy#8673", color: "#00ffe5", tag: "HyperAtillNotMe", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "HyperAtill"));
|
||||
|
||||
// Sponsor
|
||||
DevUserList.Add(new(code: "recentduct#6068", color: "#FF00FF", tag: "高冷男模法师", isUp: false, isDev: false, colorCmd: false, deBug: true, upName: null));
|
||||
|
||||
@@ -21,6 +21,8 @@ class DisableDevice
|
||||
["PolusRightAdmin"] = new(24.66f, -21.52f),
|
||||
["PolusCamera"] = new(2.96f, -12.74f),
|
||||
["PolusVital"] = new(26.70f, -15.94f),
|
||||
["DleksAdmin"] = new Vector2(-3.48f, -8.62f),
|
||||
["DleksCamera"] = new Vector2(13.06f, -2.45f),
|
||||
["AirshipCockpitAdmin"] = new(-22.32f, 0.91f),
|
||||
["AirshipRecordsAdmin"] = new(19.89f, 12.60f),
|
||||
["AirshipCamera"] = new(8.10f, -9.63f),
|
||||
@@ -35,7 +37,7 @@ class DisableDevice
|
||||
MapNames.Skeld => 1.8f,
|
||||
MapNames.Mira => 2.4f,
|
||||
MapNames.Polus => 1.8f,
|
||||
//MapNames.Dleks => 1.5f,
|
||||
MapNames.Dleks => 1.5f,
|
||||
MapNames.Airship => 1.8f,
|
||||
MapNames.Fungle => 1.8f,
|
||||
_ => 0.0f
|
||||
@@ -87,6 +89,12 @@ class DisableDevice
|
||||
if (Options.DisablePolusVital.GetBool())
|
||||
doComms |= Vector2.Distance(PlayerPos, DevicePos["PolusVital"]) <= UsableDistance();
|
||||
break;
|
||||
case 3:
|
||||
if (Options.DisableSkeldAdmin.GetBool())
|
||||
doComms |= Vector2.Distance(PlayerPos, DevicePos["DleksAdmin"]) <= UsableDistance();
|
||||
if (Options.DisableSkeldCamera.GetBool())
|
||||
doComms |= Vector2.Distance(PlayerPos, DevicePos["DleksCamera"]) <= UsableDistance();
|
||||
break;
|
||||
case 4:
|
||||
if (Options.DisableAirshipCockpitAdmin.GetBool())
|
||||
doComms |= Vector2.Distance(PlayerPos, DevicePos["AirshipCockpitAdmin"]) <= UsableDistance();
|
||||
@@ -152,6 +160,7 @@ public class RemoveDisableDevicesPatch
|
||||
if (admins == null || consoles == null) return;
|
||||
switch (Main.NormalOptions.MapId)
|
||||
{
|
||||
case 3:
|
||||
case 0:
|
||||
if (Options.DisableSkeldAdmin.GetBool())
|
||||
admins[0].gameObject.GetComponent<CircleCollider2D>().enabled = false || ignore;
|
||||
|
||||
@@ -20,9 +20,9 @@ namespace TOHE;
|
||||
|
||||
static class ExtendedPlayerControl
|
||||
{
|
||||
public static void RpcSetCustomRole(this PlayerControl player, CustomRoles role)
|
||||
public static void RpcSetCustomRole(this PlayerControl player, CustomRoles role, bool isRoleForced = false)
|
||||
{
|
||||
if (role < CustomRoles.NotAssigned)
|
||||
if (role < CustomRoles.NotAssigned || isRoleForced)
|
||||
{
|
||||
Main.PlayerStates[player.PlayerId].SetMainRole(role);
|
||||
}
|
||||
@@ -166,6 +166,7 @@ static class ExtendedPlayerControl
|
||||
|
||||
public static void RpcGuardAndKill(this PlayerControl killer, PlayerControl target = null, int colorId = 0, bool forObserver = false, bool fromSetKCD = false)
|
||||
{
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (target == null) target = killer;
|
||||
if (!forObserver && !MeetingStates.FirstMeeting) Main.AllPlayerControls.Where(x => x.Is(CustomRoles.Observer) && killer.PlayerId != x.PlayerId).Do(x => x.RpcGuardAndKill(target, colorId, true));
|
||||
// Host
|
||||
|
||||
@@ -374,7 +374,7 @@ public class TaskState
|
||||
Chameleon.SendRPCPlus(player.PlayerId);
|
||||
break;
|
||||
case CustomRoles.NiceSwapper:
|
||||
NiceSwapper.NiceSwappermax[player.PlayerId] += NiceSwapper.NiceSwapperAbilityUseGainWithEachTaskCompleted.GetFloat();
|
||||
NiceSwapper.UseLimit += NiceSwapper.NiceSwapperAbilityUseGainWithEachTaskCompleted.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Doormaster:
|
||||
Doormaster.UseLimit[player.PlayerId] += Doormaster.DoormasterAbilityUseGainWithEachTaskCompleted.GetFloat();
|
||||
|
||||
@@ -100,7 +100,7 @@ public static class NameColorManager
|
||||
(CustomRoles.Deathknight, CustomRoles.Necromancer) => Main.roleColors[CustomRoles.Necromancer],
|
||||
(CustomRoles.Necromancer, CustomRoles.Necromancer) => Main.roleColors[CustomRoles.Necromancer],
|
||||
(CustomRoles.Deathknight, CustomRoles.Deathknight) => Main.roleColors[CustomRoles.Deathknight],
|
||||
_ => "",
|
||||
_ => color,
|
||||
};
|
||||
|
||||
color = seer.GetCustomRole() switch
|
||||
@@ -122,7 +122,7 @@ public static class NameColorManager
|
||||
CustomRoles.Hookshot when Hookshot.MarkedPlayerId == target.PlayerId => Main.roleColors[CustomRoles.Hookshot],
|
||||
CustomRoles.SoulHunter when SoulHunter.CurrentTarget.ID == target.PlayerId => Main.roleColors[CustomRoles.SoulHunter],
|
||||
CustomRoles.Kamikaze when Kamikaze.MarkedPlayers.TryGetValue(seer.PlayerId, out var targets) && targets.Contains(target.PlayerId) => Main.roleColors[CustomRoles.Electric],
|
||||
_ => "",
|
||||
_ => color,
|
||||
};
|
||||
|
||||
if (SoulHunter.CurrentTarget.ID == seer.PlayerId && target.Is(CustomRoles.SoulHunter)) color = Main.roleColors[CustomRoles.SoulHunter];
|
||||
|
||||
+38
-1
@@ -213,6 +213,7 @@ public static class Options
|
||||
public static OptionItem CheatResponses;
|
||||
public static OptionItem LowLoadMode;
|
||||
public static OptionItem DeepLowLoad;
|
||||
public static OptionItem DisableVoteBan;
|
||||
|
||||
// Dummy Settings
|
||||
public static OptionItem SpawnSidekickAlone;
|
||||
@@ -363,6 +364,7 @@ public static class Options
|
||||
public static OptionItem SkeldChance;
|
||||
public static OptionItem MiraChance;
|
||||
public static OptionItem PolusChance;
|
||||
public static OptionItem DleksChance;
|
||||
public static OptionItem AirshipChance;
|
||||
public static OptionItem FungleChance;
|
||||
|
||||
@@ -706,6 +708,15 @@ public static class Options
|
||||
public static OptionItem DisableDevicesIgnoreCrewmates;
|
||||
public static OptionItem DisableDevicesIgnoreAfterAnyoneDied;
|
||||
|
||||
// Ability Use Gain every 5 seconds
|
||||
public static OptionItem VentguardAbilityChargesWhenFinishedTasks;
|
||||
public static OptionItem GrenadierAbilityChargesWhenFinishedTasks;
|
||||
public static OptionItem LighterAbilityChargesWhenFinishedTasks;
|
||||
public static OptionItem SecurityGuardAbilityChargesWhenFinishedTasks;
|
||||
public static OptionItem DovesOfNeaceAbilityChargesWhenFinishedTasks;
|
||||
public static OptionItem TimeMasterAbilityChargesWhenFinishedTasks;
|
||||
public static OptionItem VeteranAbilityChargesWhenFinishedTasks;
|
||||
|
||||
// Maps
|
||||
public static OptionItem RandomMapsMode;
|
||||
public static OptionItem AddedTheSkeld;
|
||||
@@ -1530,6 +1541,9 @@ public static class Options
|
||||
VentguardAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(5527, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 1f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Ventguard])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
VentguardAbilityChargesWhenFinishedTasks = FloatOptionItem.Create(5530, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Ventguard])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
VentguardMaxGuards = IntegerOptionItem.Create(5528, "VentguardMaxGuards", new(1, 30, 1), 3, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Ventguard]);
|
||||
VentguardBlockDoesNotAffectCrew = BooleanOptionItem.Create(5529, "VentguardBlockDoesNotAffectCrew", true, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Ventguard]);
|
||||
RoleLoadingText = "Crewmate roles\nDemolitionist";
|
||||
@@ -1684,6 +1698,9 @@ public static class Options
|
||||
GrenadierAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(6815, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.5f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Grenadier])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
GrenadierAbilityChargesWhenFinishedTasks = FloatOptionItem.Create(6816, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Grenadier])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
|
||||
LoadingPercentage = 19;
|
||||
RoleLoadingText = "Crewmate roles\nLighter";
|
||||
@@ -1707,6 +1724,9 @@ public static class Options
|
||||
LighterAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(6857, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 1.5f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Lighter])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
LighterAbilityChargesWhenFinishedTasks = FloatOptionItem.Create(6858, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Lighter])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
|
||||
RoleLoadingText = "Crewmate roles\nSecurity Guard";
|
||||
|
||||
@@ -1723,6 +1743,9 @@ public static class Options
|
||||
SecurityGuardAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(6867, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.4f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.SecurityGuard])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
SecurityGuardAbilityChargesWhenFinishedTasks = FloatOptionItem.Create(6868, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.SecurityGuard])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
|
||||
LoadingPercentage = 20;
|
||||
RoleLoadingText = "Crewmate roles\nInspector";
|
||||
@@ -1761,6 +1784,9 @@ public static class Options
|
||||
DovesOfNeaceAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(7712, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.DovesOfNeace])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
DovesOfNeaceAbilityChargesWhenFinishedTasks = FloatOptionItem.Create(7713, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.DovesOfNeace])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
RoleLoadingText = "Crewmate roles\nParanoid";
|
||||
SetupRoleOptions(7800, TabGroup.CrewmateRoles, CustomRoles.Paranoia);
|
||||
ParanoiaNumOfUseButton = IntegerOptionItem.Create(7810, "ParanoiaNumOfUseButton", new(0, 90, 1), 3, TabGroup.CrewmateRoles, false)
|
||||
@@ -1794,6 +1820,9 @@ public static class Options
|
||||
TimeMasterAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(8963, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.4f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.TimeMaster])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
TimeMasterAbilityChargesWhenFinishedTasks = FloatOptionItem.Create(8964, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.TimeMaster])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
RoleLoadingText = "Crewmate roles\nTracker";
|
||||
|
||||
Tracker.SetupCustomOption();
|
||||
@@ -1857,6 +1886,9 @@ public static class Options
|
||||
VeteranAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(8913, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.3f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Veteran])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
VeteranAbilityChargesWhenFinishedTasks = FloatOptionItem.Create(8914, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Veteran])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
RoleLoadingText = "Crewmate roles\nNice Guesser";
|
||||
SetupRoleOptions(8600, TabGroup.CrewmateRoles, CustomRoles.NiceGuesser);
|
||||
GGCanGuessTime = IntegerOptionItem.Create(8610, "GuesserCanGuessTimes", new(0, 15, 1), 15, TabGroup.CrewmateRoles, false)
|
||||
@@ -2809,6 +2841,8 @@ public static class Options
|
||||
CheatResponses = StringOptionItem.Create(19319, "CheatResponses", CheatResponsesName, 2, TabGroup.SystemSettings, false)
|
||||
.SetHeader(true);
|
||||
|
||||
DisableVoteBan = BooleanOptionItem.Create(19320, "DisableVoteBan", false, TabGroup.SystemSettings, true);
|
||||
|
||||
//HighLevelAntiCheat = StringOptionItem.Create(19320, "HighLevelAntiCheat", CheatResponsesName, 0, TabGroup.SystemSettings, false)
|
||||
//.SetHeader(true);
|
||||
|
||||
@@ -2933,10 +2967,13 @@ public static class Options
|
||||
PolusChance = IntegerOptionItem.Create(19912, "PolusChance", new(0, 100, 5), 0, TabGroup.GameSettings, false)
|
||||
.SetParent(RandomMapsMode)
|
||||
.SetValueFormat(OptionFormat.Percent);
|
||||
DleksChance = IntegerOptionItem.Create(19914, "DleksChance", new(0, 100, 5), 0, TabGroup.GameSettings, false)
|
||||
.SetParent(RandomMapsMode)
|
||||
.SetValueFormat(OptionFormat.Percent);
|
||||
AirshipChance = IntegerOptionItem.Create(19913, "AirshipChance", new(0, 100, 5), 0, TabGroup.GameSettings, false)
|
||||
.SetParent(RandomMapsMode)
|
||||
.SetValueFormat(OptionFormat.Percent);
|
||||
FungleChance = IntegerOptionItem.Create(19922, "FungleChance", new(0, 100, 5), 10, TabGroup.GameSettings, false)
|
||||
FungleChance = IntegerOptionItem.Create(19922, "FungleChance", new(0, 100, 5), 0, TabGroup.GameSettings, false)
|
||||
.SetParent(RandomMapsMode)
|
||||
.SetValueFormat(OptionFormat.Percent);
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ public enum CustomRPC
|
||||
|
||||
//Roles
|
||||
SetDrawPlayer,
|
||||
SyncHeadHunter,
|
||||
SyncConvener,
|
||||
SyncPerceiver,
|
||||
SyncRabbit,
|
||||
@@ -411,6 +412,9 @@ internal class RPCHandlerPatch
|
||||
case CustomRPC.setPlaguedPlayer:
|
||||
PlagueBearer.ReceiveRPC(reader);
|
||||
break;
|
||||
case CustomRPC.SyncHeadHunter:
|
||||
HeadHunter.ReceiveRPC(reader);
|
||||
break;
|
||||
case CustomRPC.SyncDamoclesTimer:
|
||||
Damocles.ReceiveRPC(reader);
|
||||
break;
|
||||
|
||||
+10
-3
@@ -404,7 +404,7 @@ public static class Utils
|
||||
if (!subRole.IsAdditionRole())
|
||||
{
|
||||
str = GetString(subRole.ToString());
|
||||
Logger.Fatal("This is concerning....", "Utils.GetRoleText");
|
||||
//Logger.Fatal("This is concerning....", "Utils.GetRoleText");
|
||||
}
|
||||
RoleText = ColorString(GetRoleColor(subRole), (Options.AddBracketsToAddons.GetBool() ? "<#ffffff>(</color>" : string.Empty) + str + (Options.AddBracketsToAddons.GetBool() ? "<#ffffff>)</color>" : string.Empty) + " ") + RoleText;
|
||||
}
|
||||
@@ -846,7 +846,7 @@ public static class Utils
|
||||
break;
|
||||
case CustomRoles.NiceSwapper:
|
||||
ProgressText.Append(GetTaskCount(playerId, comms));
|
||||
ProgressText.Append(NiceSwapper.GetNiceSwappermax(playerId));
|
||||
ProgressText.Append(NiceSwapper.ProgressText);
|
||||
break;
|
||||
case CustomRoles.Veteran:
|
||||
Color TextColor21;
|
||||
@@ -1387,7 +1387,7 @@ public static class Utils
|
||||
switch (opt.Value.Name)
|
||||
{
|
||||
case "Maximum":
|
||||
case "DisableSkeldDevices" when Main.CurrentMap != MapNames.Skeld:
|
||||
case "DisableSkeldDevices" when Main.CurrentMap is not MapNames.Skeld and not MapNames.Dleks:
|
||||
case "DisableMiraHQDevices" when Main.CurrentMap != MapNames.Mira:
|
||||
case "DisablePolusDevices" when Main.CurrentMap != MapNames.Polus:
|
||||
case "DisableAirshipDevices" when Main.CurrentMap != MapNames.Airship:
|
||||
@@ -3274,6 +3274,13 @@ public static class Utils
|
||||
if (Hitman.targetId == target.PlayerId)
|
||||
Hitman.targetId = byte.MaxValue;
|
||||
|
||||
|
||||
if (Hacker.IsEnable) Hacker.AddDeadBody(target);
|
||||
if (Mortician.IsEnable) Mortician.OnPlayerDead(target);
|
||||
if (Bloodhound.IsEnable) Bloodhound.OnPlayerDead(target);
|
||||
if (Tracefinder.IsEnable) Tracefinder.OnPlayerDead(target);
|
||||
if (Vulture.IsEnable) Vulture.OnPlayerDead(target);
|
||||
|
||||
FixedUpdatePatch.LoversSuicide(target.PlayerId, onMeeting);
|
||||
}
|
||||
public static void ChangeInt(ref int ChangeTo, int input, int max)
|
||||
|
||||
@@ -232,7 +232,7 @@ internal class ChatCommands
|
||||
}
|
||||
if (!GuessManager.MsgToPlayerAndRole(subArgs, out byte resultId, out CustomRoles roleToSet, out _))
|
||||
{
|
||||
Utils.SendMessage("Invalid arguments", localPlayerId);
|
||||
Utils.SendMessage($"{GetString("InvalidArguments")}", localPlayerId);
|
||||
break;
|
||||
}
|
||||
else
|
||||
@@ -281,6 +281,7 @@ internal class ChatCommands
|
||||
settings.Append("</size>");
|
||||
var txt = sb.ToString();
|
||||
_ = sb.Clear().Append(txt.RemoveHtmlTags());
|
||||
if (role.PetActivatedAbility()) sb.Append("<size=50%>" + GetString("SupportsPetMessage").RemoveHtmlTags() + "</size>");
|
||||
sb.Append("<size=70%>");
|
||||
foreach (CustomRoles subRole in Main.PlayerStates[localPlayerId].SubRoles.ToArray())
|
||||
{
|
||||
@@ -293,6 +294,18 @@ internal class ChatCommands
|
||||
Utils.SendMessage((lp.FriendCode.GetDevUser().HasTag() ? "\n" : string.Empty) + GetString("Message.CanNotUseInLobby"), localPlayerId);
|
||||
break;
|
||||
|
||||
case "/tpout":
|
||||
canceled = true;
|
||||
if (!GameStates.IsLobby) break;
|
||||
PlayerControl.LocalPlayer.TP(new Vector2(0.1f, 3.8f));
|
||||
break;
|
||||
|
||||
case "/tpin":
|
||||
canceled = true;
|
||||
if (!GameStates.IsLobby) break;
|
||||
PlayerControl.LocalPlayer.TP(new Vector2(-0.2f, 1.3f));
|
||||
break;
|
||||
|
||||
case "/t":
|
||||
case "/template":
|
||||
canceled = true;
|
||||
@@ -496,6 +509,7 @@ internal class ChatCommands
|
||||
|
||||
case "/changerole":
|
||||
//if (!DebugModeManager.AmDebugger) break;
|
||||
if (GameStates.IsLobby || !PlayerControl.LocalPlayer.FriendCode.GetDevUser().IsUp) break;
|
||||
canceled = true;
|
||||
subArgs = text.Remove(0, 8);
|
||||
var setRole = FixRoleNameInput(subArgs.Trim());
|
||||
@@ -507,8 +521,13 @@ internal class ChatCommands
|
||||
{
|
||||
PlayerControl.LocalPlayer.RpcSetRole(rl.GetRoleTypes());
|
||||
PlayerControl.LocalPlayer.RpcSetCustomRole(rl);
|
||||
PlayerControl.LocalPlayer.SyncSettings();
|
||||
Utils.NotifyRoles(SpecifySeer: PlayerControl.LocalPlayer);
|
||||
PlayerControl.LocalPlayer.MarkDirtySettings();
|
||||
Utils.NotifyRoles(SpecifyTarget: PlayerControl.LocalPlayer);
|
||||
HudManager.Instance.SetHudActive(PlayerControl.LocalPlayer, PlayerControl.LocalPlayer.Data.Role, !GameStates.IsMeeting);
|
||||
Utils.AddRoles(PlayerControl.LocalPlayer.PlayerId, rl);
|
||||
Main.PlayerStates[PlayerControl.LocalPlayer.PlayerId].RemoveSubRole(CustomRoles.NotAssigned);
|
||||
Main.ChangedRole = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -820,10 +839,9 @@ internal class ChatCommands
|
||||
var roleName = GetString(rl.ToString());
|
||||
if (role == roleName.ToLower().Trim().TrimStart('*').Replace(" ", string.Empty))
|
||||
{
|
||||
string devMark = string.Empty;
|
||||
if ((isDev || isUp) && GameStates.IsLobby)
|
||||
{
|
||||
devMark = "▲";
|
||||
string devMark = "▲";
|
||||
if (rl.IsAdditionRole() || rl is CustomRoles.GM) devMark = string.Empty;
|
||||
if (rl.GetCount() < 1 || rl.GetMode() == 0) devMark = string.Empty;
|
||||
if (isUp)
|
||||
@@ -840,17 +858,18 @@ internal class ChatCommands
|
||||
if (isUp) return;
|
||||
}
|
||||
var sb = new StringBuilder();
|
||||
var title = $"{devMark}<{Main.roleColors[rl]}>{roleName}</color> {Utils.GetRoleMode(rl)}";
|
||||
var title = $"<{Main.roleColors[rl]}>{roleName}</color> {Utils.GetRoleMode(rl)}";
|
||||
_ = sb.Append($"{GetString($"{rl}InfoLong")}");
|
||||
var settings = new StringBuilder();
|
||||
if (Options.CustomRoleSpawnChances.ContainsKey(rl))
|
||||
{
|
||||
settings.AppendLine($"<size=70%><u>Settings for <{Main.roleColors[rl]}>{roleName}</color>:</u>");
|
||||
settings.AppendLine($"<size=70%><u>{GetString("SettingsForRoleText")} <{Main.roleColors[rl]}>{roleName}</color>:</u>");
|
||||
Utils.ShowChildrenSettings(Options.CustomRoleSpawnChances[rl], ref settings, disableColor: false);
|
||||
settings.Append("</size>");
|
||||
var txt = $"<size=90%>{sb}</size>";
|
||||
_ = sb.Clear().Append(txt);
|
||||
}
|
||||
if (rl.PetActivatedAbility()) sb.Append($"<size=50%>{GetString("SupportsPetMessage")}</size>");
|
||||
Utils.SendMessage(text: "\n", sendTo: playerId, title: settings.ToString());
|
||||
Utils.SendMessage(text: sb.ToString(), sendTo: playerId, title: title);
|
||||
return;
|
||||
@@ -943,6 +962,7 @@ internal class ChatCommands
|
||||
settings.Append("</size>");
|
||||
var txt = sb.ToString();
|
||||
_ = sb.Clear().Append(txt.RemoveHtmlTags());
|
||||
if (role.PetActivatedAbility()) sb.Append("<size=50%>" + GetString("SupportsPetMessage").RemoveHtmlTags() + "</size>");
|
||||
sb.Append("<size=70%>");
|
||||
foreach (CustomRoles subRole in Main.PlayerStates[player.PlayerId].SubRoles.ToArray())
|
||||
{
|
||||
@@ -995,6 +1015,18 @@ internal class ChatCommands
|
||||
}
|
||||
break;
|
||||
|
||||
case "/tpout":
|
||||
canceled = true;
|
||||
if (!GameStates.IsLobby) break;
|
||||
player.TP(new Vector2(0.1f, 3.8f));
|
||||
break;
|
||||
|
||||
case "/tpin":
|
||||
canceled = true;
|
||||
if (!GameStates.IsLobby) break;
|
||||
player.TP(new Vector2(-0.2f, 1.3f));
|
||||
break;
|
||||
|
||||
//case "/quit":
|
||||
//case "/qt":
|
||||
// subArgs = args.Length < 2 ? string.Empty : args[1];
|
||||
@@ -1012,8 +1044,6 @@ internal class ChatCommands
|
||||
// }
|
||||
// break;
|
||||
case "/id":
|
||||
if (Options.ApplyModeratorList.GetValue() == 0 || !IsPlayerModerator(player.FriendCode)) break;
|
||||
|
||||
string msgText = GetString("PlayerIdList");
|
||||
foreach (PlayerControl pc in Main.AllPlayerControls)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TOHE;
|
||||
|
||||
[HarmonyPatch(typeof(AmongUsClient._CoStartGameHost_d__30), nameof(AmongUsClient._CoStartGameHost_d__30.MoveNext))]
|
||||
public static class DleksPatch
|
||||
{
|
||||
public static bool Prefix(AmongUsClient._CoStartGameHost_d__30 __instance, ref bool __result)
|
||||
{
|
||||
if (__instance.__1__state != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
__instance.__1__state = -1;
|
||||
if (LobbyBehaviour.Instance)
|
||||
{
|
||||
LobbyBehaviour.Instance.Despawn();
|
||||
}
|
||||
|
||||
if (ShipStatus.Instance)
|
||||
{
|
||||
__instance.__2__current = null;
|
||||
__instance.__1__state = 2;
|
||||
__result = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// removed dleks check as it's always false
|
||||
var num2 = Mathf.Clamp(GameOptionsManager.Instance.CurrentGameOptions.MapId, 0, Constants.MapNames.Length - 1);
|
||||
__instance.__2__current = __instance.__4__this.ShipLoadingAsyncHandle = __instance.__4__this.ShipPrefabs[num2].InstantiateAsync();
|
||||
__instance.__1__state = 1;
|
||||
|
||||
__result = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(KeyValueOption), nameof(KeyValueOption.OnEnable))]
|
||||
public static class AutoselectDleksPatch
|
||||
{
|
||||
public static void Postfix(KeyValueOption __instance)
|
||||
{
|
||||
if (__instance.Title == StringNames.GameMapName)
|
||||
{
|
||||
// vanilla clamps this to not autoselect dleks
|
||||
__instance.Selected = GameOptionsManager.Instance.CurrentGameOptions.MapId;
|
||||
}
|
||||
}
|
||||
}
|
||||
[HarmonyPatch(typeof(Vent), nameof(Vent.SetButtons))]
|
||||
public static class VentSetButtonsPatch
|
||||
{
|
||||
public static bool ShowButtons = false;
|
||||
// Fix arrows buttons in vent on Dleks map and "Index was outside the bounds of the array" errors
|
||||
private static bool Prefix(/*Vent __instance,*/ [HarmonyArgument(0)] ref bool enabled)
|
||||
{
|
||||
if (Main.CurrentMap == MapNames.Dleks && Main.introDestroyed)
|
||||
{
|
||||
enabled = false;
|
||||
if (GameStates.IsMeeting)
|
||||
ShowButtons = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static void Postfix(Vent __instance, [HarmonyArgument(0)] bool enabled)
|
||||
{
|
||||
if (Main.CurrentMap != MapNames.Dleks) return;
|
||||
if (enabled || !Main.introDestroyed) return;
|
||||
|
||||
var setActive = ShowButtons || !PlayerControl.LocalPlayer.inVent && !GameStates.IsMeeting;
|
||||
switch (__instance.Id)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 5:
|
||||
case 6:
|
||||
__instance.Buttons[0].gameObject.SetActive(setActive);
|
||||
__instance.Buttons[1].gameObject.SetActive(setActive);
|
||||
break;
|
||||
case 7:
|
||||
case 12:
|
||||
case 13:
|
||||
__instance.Buttons[0].gameObject.SetActive(setActive);
|
||||
break;
|
||||
case 4:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
__instance.Buttons[1].gameObject.SetActive(setActive);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
[HarmonyPatch(typeof(Vent), nameof(Vent.TryMoveToVent))]
|
||||
class VentTryMoveToVentPatch
|
||||
{
|
||||
// Update arrows buttons when player move to vents
|
||||
private static void Postfix(Vent __instance, [HarmonyArgument(0)] Vent otherVent)
|
||||
{
|
||||
if (__instance == null || otherVent == null || Main.CurrentMap != MapNames.Dleks) return;
|
||||
|
||||
VentSetButtonsPatch.ShowButtons = true;
|
||||
VentSetButtonsPatch.Postfix(otherVent, false);
|
||||
VentSetButtonsPatch.ShowButtons = false;
|
||||
}
|
||||
}
|
||||
[HarmonyPatch(typeof(Vent), nameof(Vent.UpdateArrows))]
|
||||
class VentUpdateArrowsPatch
|
||||
{
|
||||
// Fixes "Index was outside the bounds of the array" errors when arrows updates in vent on Dleks map
|
||||
private static bool Prefix()
|
||||
{
|
||||
return Main.CurrentMap != MapNames.Dleks;
|
||||
}
|
||||
}
|
||||
+2
-10
@@ -129,16 +129,7 @@ class ExileControllerWrapUpPatch
|
||||
Witch.RemoveSpelledPlayer();
|
||||
HexMaster.RemoveHexedPlayer();
|
||||
|
||||
if (NiceSwapper.Vote.Count > 0 && NiceSwapper.VoteTwo.Count > 0)
|
||||
{
|
||||
foreach (var swapper in Main.AllAlivePlayerControls.Where(swapper => swapper.Is(CustomRoles.NiceSwapper)).ToArray())
|
||||
{
|
||||
NiceSwapper.NiceSwappermax[swapper.PlayerId]--;
|
||||
NiceSwapper.Vote.Clear();
|
||||
NiceSwapper.VoteTwo.Clear();
|
||||
Main.NiceSwapSend = false;
|
||||
}
|
||||
}
|
||||
NiceSwapper.OnExileFinish();
|
||||
|
||||
foreach (PlayerControl pc in Main.AllPlayerControls)
|
||||
{
|
||||
@@ -160,6 +151,7 @@ class ExileControllerWrapUpPatch
|
||||
0 => new RandomSpawn.SkeldSpawnMap(),
|
||||
1 => new RandomSpawn.MiraHQSpawnMap(),
|
||||
2 => new RandomSpawn.PolusSpawnMap(),
|
||||
3 => new RandomSpawn.DleksSpawnMap(),
|
||||
5 => new RandomSpawn.FungleSpawnMap(),
|
||||
_ => null,
|
||||
};
|
||||
|
||||
@@ -19,8 +19,19 @@ public static class GameSettingMenuPatch
|
||||
// オンラインモードで部屋を立て直さなくてもマップを変更できるように変更
|
||||
__instance.HideForOnline = new Il2CppReferenceArray<Transform>(0);
|
||||
}
|
||||
|
||||
// Add dleks to map selection
|
||||
public static void Postfix([HarmonyArgument(0)] Il2CppReferenceArray<Transform> items)
|
||||
{
|
||||
items.FirstOrDefault(i => i.gameObject.activeSelf && i.name.Equals("MapName", StringComparison.OrdinalIgnoreCase))?
|
||||
.GetComponent<KeyValueOption>()?
|
||||
.Values?
|
||||
// using .Insert will convert managed values and break the struct resulting in crashes
|
||||
.System_Collections_IList_Insert((int)MapNames.Dleks, new Il2CppSystem.Collections.Generic.KeyValuePair<string, int>(Constants.MapNames[(int)MapNames.Dleks], (int)MapNames.Dleks));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[HarmonyPatch(typeof(GameOptionsMenu), nameof(GameOptionsMenu.Start))]
|
||||
[HarmonyPriority(Priority.First)]
|
||||
public static class GameOptionsMenuPatch
|
||||
@@ -177,7 +188,7 @@ public class GameOptionsMenuUpdatePatch
|
||||
__instance.transform.FindChild("../../GameGroup/Text").GetComponent<TMPro.TextMeshPro>().SetText($"<color={tabcolor}>" + GetString("TabGroup." + tab) + "</color>");
|
||||
|
||||
_timer += Time.deltaTime;
|
||||
if (_timer < 0.1f) return;
|
||||
if (_timer < 0.2f) return;
|
||||
_timer = 0f;
|
||||
|
||||
float numItems = __instance.Children.Length;
|
||||
@@ -264,8 +275,10 @@ public class StringOptionEnablePatch
|
||||
__instance.OnValueChanged = new Action<OptionBehaviour>((o) => { });
|
||||
__instance.TitleText.text = option.GetName();
|
||||
if (option.Id == Options.UsePets.Id) LoadLangs();
|
||||
else if (!Options.UsePets.GetBool() && CustomRolesHelper.OnlySpawnsWithPetsRoleList.Any(role => role.ToString().Equals(option.GetName().RemoveHtmlTags())))
|
||||
else if (!Options.UsePets.GetBool() && CustomRolesHelper.OnlySpawnsWithPetsRoleList.Any(role => role.ToString().Equals(option.GetName().RemoveHtmlTags().Replace(" ", string.Empty))))
|
||||
__instance.TitleText.text += GetString("RequiresPetIndicator");
|
||||
else if (Options.UsePets.GetBool() && Enum.TryParse(option.GetName().RemoveHtmlTags().Replace(" ", string.Empty), out CustomRoles enumerable) && enumerable.PetActivatedAbility())
|
||||
__instance.TitleText.text += GetString("SupportsPetIndicator");
|
||||
__instance.Value = __instance.oldValue = option.CurrentValue;
|
||||
__instance.ValueText.text = option.GetString();
|
||||
|
||||
|
||||
@@ -307,6 +307,7 @@ public class GameStartRandomMap
|
||||
if (tempRand <= Options.SkeldChance.GetInt()) randomMaps.Add(0);
|
||||
if (tempRand <= Options.MiraChance.GetInt()) randomMaps.Add(1);
|
||||
if (tempRand <= Options.PolusChance.GetInt()) randomMaps.Add(2);
|
||||
if (tempRand <= Options.DleksChance.GetInt()) randomMaps.Add(3);
|
||||
if (tempRand <= Options.AirshipChance.GetInt()) randomMaps.Add(4);
|
||||
if (tempRand <= Options.FungleChance.GetInt()) randomMaps.Add(5);
|
||||
|
||||
@@ -322,6 +323,7 @@ public class GameStartRandomMap
|
||||
if (Options.SkeldChance.GetInt() > 0) randomMaps.Add(0);
|
||||
if (Options.MiraChance.GetInt() > 0) randomMaps.Add(1);
|
||||
if (Options.PolusChance.GetInt() > 0) randomMaps.Add(2);
|
||||
if (Options.DleksChance.GetInt() > 0) randomMaps.Add(3);
|
||||
if (Options.AirshipChance.GetInt() > 0) randomMaps.Add(4);
|
||||
if (Options.FungleChance.GetInt() > 0) randomMaps.Add(5);
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using HarmonyLib;
|
||||
|
||||
namespace TOHE;
|
||||
|
||||
// 来源:https://github.com/ykundesu/SuperNewRoles/blob/master/SuperNewRoles/Patches/HorseModePatch.cs
|
||||
[HarmonyPatch(typeof(Constants), nameof(Constants.ShouldHorseAround))]
|
||||
public static class HorseModePatch
|
||||
{
|
||||
public static bool isHorseMode;
|
||||
public static bool Prefix(ref bool __result)
|
||||
{
|
||||
__result = isHorseMode;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+3
-46
@@ -589,26 +589,9 @@ class HudManagerPatch
|
||||
__instance.KillButton?.ToggleVisible(false);
|
||||
}
|
||||
|
||||
bool CanUseVent = (player.CanUseImpostorVentButton() || player.inVent) && GameStates.IsInTask && !player.MyPhysics.Animations.IsPlayingEnterVentAnimation();
|
||||
bool CanUseVent = (player.CanUseImpostorVentButton() || player.inVent) && GameStates.IsInTask;
|
||||
__instance.ImpostorVentButton?.ToggleVisible(CanUseVent);
|
||||
player.Data.Role.CanVent = CanUseVent;
|
||||
|
||||
var vents = Object.FindObjectsOfType<Vent>().ToArray();
|
||||
if (player.PlayerId == 0 && player.inVent && GameStates.IsInTask) SetVentButtonEnabled(TryMoveToVentPatch.HostVentTarget);
|
||||
else if (CanUseVent && vents.Any(vent => Vector2.Distance(new Vector2(vent.transform.position.x, vent.transform.position.y + 0.3636f), player.Pos()) < 0.4f))
|
||||
{
|
||||
Vent vent = vents.FirstOrDefault(vent => Vector2.Distance(new Vector2(vent.transform.position.x, vent.transform.position.y + 0.3636f), player.Pos()) < 0.4f);
|
||||
SetVentButtonEnabled(vent);
|
||||
}
|
||||
void SetVentButtonEnabled(Vent target)
|
||||
{
|
||||
__instance.ImpostorVentButton.canInteract = true;
|
||||
__instance.ImpostorVentButton.enabled = true;
|
||||
__instance.ImpostorVentButton.isCoolingDown = false;
|
||||
__instance.ImpostorVentButton.SetEnabled();
|
||||
__instance.ImpostorVentButton.currentTarget = target;
|
||||
__instance.ImpostorVentButton.SetTarget(target);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -769,7 +752,6 @@ class SetHudActivePatch
|
||||
case CustomRoles.Magician:
|
||||
__instance.SabotageButton?.ToggleVisible(true);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (Main.PlayerStates.TryGetValue(player.PlayerId, out var ps) && ps.SubRoles.Contains(CustomRoles.Oblivious))
|
||||
@@ -778,42 +760,17 @@ class SetHudActivePatch
|
||||
}
|
||||
__instance.KillButton?.ToggleVisible(player.CanUseKillButton());
|
||||
__instance.ImpostorVentButton?.ToggleVisible(player.CanUseImpostorVentButton());
|
||||
__instance.SabotageButton?.ToggleVisible(player.CanUseSabotage() && isActive);
|
||||
__instance.SabotageButton?.ToggleVisible(player.CanUseSabotage());
|
||||
}
|
||||
}
|
||||
[HarmonyPatch(typeof(VentButton), nameof(VentButton.DoClick))]
|
||||
class VentButtonDoClickPatch
|
||||
{
|
||||
public static bool Animating = false;
|
||||
public static bool Prefix(VentButton __instance)
|
||||
public static void Prefix()
|
||||
{
|
||||
var pc = PlayerControl.LocalPlayer;
|
||||
if (pc.MyPhysics.Animations.IsPlayingEnterVentAnimation()) return false;
|
||||
|
||||
if (pc.inVent && pc.PlayerId == 0)
|
||||
{
|
||||
pc.MyPhysics.RpcExitVent(TryMoveToVentPatch.HostVentTarget.Id);
|
||||
TryMoveToVentPatch.HostVentTarget.SetButtons(false);
|
||||
Animating = true;
|
||||
_ = new LateTask(() => { Animating = false; }, 0.6f, log: false);
|
||||
return false;
|
||||
}
|
||||
if (pc.inVent || !pc.CanMove) return false;
|
||||
var vents = Object.FindObjectsOfType<Vent>().ToArray();
|
||||
if (vents.Any(vent => Vector2.Distance(new Vector2(vent.transform.position.x, vent.transform.position.y + 0.3636f), pc.Pos()) < 0.4f))
|
||||
{
|
||||
Vent vent = vents.FirstOrDefault(vent => Vector2.Distance(new Vector2(vent.transform.position.x, vent.transform.position.y + 0.3636f), pc.Pos()) < 0.4f);
|
||||
pc.MyPhysics.RpcEnterVent(vent.Id);
|
||||
vent.SetButtons(true);
|
||||
Animating = true;
|
||||
_ = new LateTask(() => { Animating = false; }, 0.6f, log: false);
|
||||
return false;
|
||||
}
|
||||
pc?.MyPhysics?.RpcEnterVent(__instance.currentTarget.Id);
|
||||
__instance.currentTarget.SetButtons(true);
|
||||
Animating = true;
|
||||
_ = new LateTask(() => { Animating = false; }, 0.6f, log: false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
[HarmonyPatch(typeof(MapBehaviour), nameof(MapBehaviour.Show))]
|
||||
|
||||
@@ -3,7 +3,6 @@ using HarmonyLib;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using TOHE.Modules;
|
||||
using UnityEngine;
|
||||
using static TOHE.Translator;
|
||||
|
||||
@@ -595,6 +594,7 @@ class IntroCutsceneDestroyPatch
|
||||
0 => new RandomSpawn.SkeldSpawnMap(),
|
||||
1 => new RandomSpawn.MiraHQSpawnMap(),
|
||||
2 => new RandomSpawn.PolusSpawnMap(),
|
||||
3 => new RandomSpawn.DleksSpawnMap(),
|
||||
5 => new RandomSpawn.FungleSpawnMap(),
|
||||
_ => null,
|
||||
};
|
||||
|
||||
@@ -133,25 +133,25 @@ public class MainMenuManagerPatch
|
||||
particles.Start();
|
||||
}
|
||||
}));
|
||||
var DleksButton = Object.Instantiate(bottomTemplate, bottomTemplate.transform.parent);
|
||||
var passiveDleksButton = DleksButton.GetComponent<PassiveButton>();
|
||||
var spriteDleksButton = DleksButton.GetComponent<SpriteRenderer>();
|
||||
if (DleksPatch.isDleks) spriteDleksButton.transform.localScale *= -1;
|
||||
//var DleksButton = Object.Instantiate(bottomTemplate, bottomTemplate.transform.parent);
|
||||
//var passiveDleksButton = DleksButton.GetComponent<PassiveButton>();
|
||||
//var spriteDleksButton = DleksButton.GetComponent<SpriteRenderer>();
|
||||
//if (DleksPatch.isDleks) spriteDleksButton.transform.localScale *= -1;
|
||||
|
||||
spriteDleksButton.sprite = Utils.LoadSprite($"TOHE.Resources.Images.DleksButton.png", 75f);
|
||||
passiveDleksButton.OnClick = new ButtonClickedEvent();
|
||||
passiveDleksButton.OnClick.AddListener((Action)(() =>
|
||||
{
|
||||
RunLoginPatch.ClickCount++;
|
||||
spriteDleksButton.transform.localScale *= -1;
|
||||
DleksPatch.isDleks = !DleksPatch.isDleks;
|
||||
var particles = Object.FindObjectOfType<PlayerParticles>();
|
||||
if (particles != null)
|
||||
{
|
||||
particles.pool.ReclaimAll();
|
||||
particles.Start();
|
||||
}
|
||||
}));
|
||||
//spriteDleksButton.sprite = Utils.LoadSprite($"TOHE.Resources.Images.DleksButton.png", 75f);
|
||||
//passiveDleksButton.OnClick = new ButtonClickedEvent();
|
||||
//passiveDleksButton.OnClick.AddListener((Action)(() =>
|
||||
//{
|
||||
// RunLoginPatch.ClickCount++;
|
||||
// spriteDleksButton.transform.localScale *= -1;
|
||||
// DleksPatch.isDleks = !DleksPatch.isDleks;
|
||||
// var particles = Object.FindObjectOfType<PlayerParticles>();
|
||||
// if (particles != null)
|
||||
// {
|
||||
// particles.pool.ReclaimAll();
|
||||
// particles.Start();
|
||||
// }
|
||||
//}));
|
||||
|
||||
var CreditsButton = Object.Instantiate(bottomTemplate, bottomTemplate.transform.parent);
|
||||
var passiveCreditsButton = CreditsButton.GetComponent<PassiveButton>();
|
||||
@@ -166,26 +166,4 @@ public class MainMenuManagerPatch
|
||||
|
||||
Application.targetFrameRate = Main.UnlockFPS.Value ? 165 : 60;
|
||||
}
|
||||
}
|
||||
|
||||
// 来源:https://github.com/ykundesu/SuperNewRoles/blob/master/SuperNewRoles/Patches/HorseModePatch.cs
|
||||
[HarmonyPatch(typeof(Constants), nameof(Constants.ShouldHorseAround))]
|
||||
public static class HorseModePatch
|
||||
{
|
||||
public static bool isHorseMode;
|
||||
public static bool Prefix(ref bool __result)
|
||||
{
|
||||
__result = isHorseMode;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
[HarmonyPatch(typeof(Constants), nameof(Constants.ShouldFlipSkeld))]
|
||||
public static class DleksPatch
|
||||
{
|
||||
public static bool isDleks;
|
||||
public static bool Prefix(ref bool __result)
|
||||
{
|
||||
__result = isDleks;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -201,66 +201,7 @@ class CheckForEndVotingPatch
|
||||
VotedForId = ps.VotedFor
|
||||
});
|
||||
|
||||
if (NiceSwapper.Vote.Count > 0 && NiceSwapper.VoteTwo.Count > 0)
|
||||
{
|
||||
List<byte> NiceList1 = [];
|
||||
List<byte> NiceList2 = [];
|
||||
PlayerVoteArea pva = new();
|
||||
var meetingHud = MeetingHud.Instance;
|
||||
PlayerControl swap1 = null;
|
||||
for (int i1 = 0; i1 < NiceSwapper.Vote.Count; i1++)
|
||||
{
|
||||
byte playerId = NiceSwapper.Vote[i1];
|
||||
var player = Utils.GetPlayerById(playerId);
|
||||
if (player != null)
|
||||
{
|
||||
swap1 = player;
|
||||
break;
|
||||
}
|
||||
}
|
||||
PlayerControl swap2 = null;
|
||||
for (int i1 = 0; i1 < NiceSwapper.VoteTwo.Count; i1++)
|
||||
{
|
||||
byte playerId = NiceSwapper.VoteTwo[i1];
|
||||
var player = Utils.GetPlayerById(playerId);
|
||||
if (player != null)
|
||||
{
|
||||
swap2 = player;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (swap1 != null && swap2 != null)
|
||||
{
|
||||
for (int i1 = 0; i1 < meetingHud.playerStates.Count; i1++)
|
||||
{
|
||||
PlayerVoteArea playerVoteArea = meetingHud.playerStates[i1];
|
||||
if (playerVoteArea.VotedFor != swap1.PlayerId) continue;
|
||||
var voteAreaPlayer = Utils.GetPlayerById(playerVoteArea.TargetPlayerId);
|
||||
playerVoteArea.UnsetVote();
|
||||
meetingHud.CastVote(voteAreaPlayer.PlayerId, swap2.PlayerId);
|
||||
playerVoteArea.VotedFor = swap2.PlayerId;
|
||||
NiceList1.Add(voteAreaPlayer.PlayerId);
|
||||
}
|
||||
for (int i1 = 0; i1 < meetingHud.playerStates.Count; i1++)
|
||||
{
|
||||
PlayerVoteArea playerVoteArea = meetingHud.playerStates[i1];
|
||||
if (playerVoteArea.VotedFor != swap2.PlayerId) continue;
|
||||
var voteAreaPlayer = Utils.GetPlayerById(playerVoteArea.TargetPlayerId);
|
||||
if (NiceList1.Contains(voteAreaPlayer.PlayerId)) continue;
|
||||
playerVoteArea.UnsetVote();
|
||||
meetingHud.CastVote(voteAreaPlayer.PlayerId, swap1.PlayerId);
|
||||
playerVoteArea.VotedFor = swap1.PlayerId;
|
||||
}
|
||||
if (Main.NiceSwapSend == false)
|
||||
{
|
||||
Utils.SendMessage(string.Format(GetString("SwapVote"), swap1.GetRealName(), swap2.GetRealName()), 255, Utils.ColorString(Utils.GetRoleColor(CustomRoles.NiceSwapper), GetString("SwapTitle")));
|
||||
Main.NiceSwapSend = true;
|
||||
NiceList1.Clear();
|
||||
}
|
||||
NiceSwapper.Vote.Clear();
|
||||
NiceSwapper.VoteTwo.Clear();
|
||||
}
|
||||
}
|
||||
statesList = NiceSwapper.OnCheckForEndVoting(statesList);
|
||||
|
||||
if (CheckRole(ps.TargetPlayerId, CustomRoles.Mayor) && !Options.MayorHideVote.GetBool()) //Mayorの投票数
|
||||
{
|
||||
@@ -293,7 +234,7 @@ class CheckForEndVotingPatch
|
||||
voteLog.Info("===Decision to expel player processing begins===");
|
||||
foreach (var data in VotingData)
|
||||
{
|
||||
voteLog.Info($"{data.Key}({Utils.GetVoteName(data.Key)}):{data.Value}票");
|
||||
voteLog.Info($"{data.Key} ({Utils.GetVoteName(data.Key)}): {data.Value} votes");
|
||||
if (data.Value > max)
|
||||
{
|
||||
voteLog.Info(data.Key + " has higher votes (" + data.Value + ")");
|
||||
@@ -313,7 +254,7 @@ class CheckForEndVotingPatch
|
||||
voteLog.Info($"Decide to evict player: {exileId} ({Utils.GetVoteName(exileId)})");
|
||||
|
||||
bool braked = false;
|
||||
if (tie) //破平者判断
|
||||
if (tie)
|
||||
{
|
||||
byte target = byte.MaxValue;
|
||||
foreach (var data in VotingData.Where(x => x.Key < 15 && x.Value == max))
|
||||
|
||||
@@ -31,6 +31,8 @@ class EndGamePatch
|
||||
Main.SetAddOns = [];
|
||||
SummaryText = [];
|
||||
|
||||
Main.ChangedRole = false;
|
||||
|
||||
foreach (var id in Main.PlayerStates.Keys)
|
||||
{
|
||||
if (Doppelganger.IsEnable && Doppelganger.DoppelVictim.ContainsKey(id))
|
||||
|
||||
+112
-61
@@ -253,7 +253,7 @@ class CheckMurderPatch
|
||||
if (!WeaponMaster.OnCheckMurder(killer, target)) return false;
|
||||
break;
|
||||
case CustomRoles.Cantankerous:
|
||||
if (Cantankerous.OnCheckMurder(killer)) return false;
|
||||
if (!Cantankerous.OnCheckMurder(killer)) return false;
|
||||
break;
|
||||
case CustomRoles.Postman:
|
||||
Postman.OnCheckMurder(killer, target);
|
||||
@@ -1211,16 +1211,6 @@ class MurderPlayerPatch
|
||||
if (Mediumshiper.IsEnable) foreach (var pc in Main.AllAlivePlayerControls.Where(x => x.Is(CustomRoles.Mediumshiper)).ToArray())
|
||||
pc.Notify(ColorString(GetRoleColor(CustomRoles.Mediumshiper), GetString("MediumshiperKnowPlayerDead")));
|
||||
|
||||
if (Executioner.Target.ContainsValue(target.PlayerId))
|
||||
Executioner.ChangeRoleByTarget(target);
|
||||
if (Lawyer.Target.ContainsValue(target.PlayerId))
|
||||
Lawyer.ChangeRoleByTarget(target);
|
||||
if (Hacker.IsEnable) Hacker.AddDeadBody(target);
|
||||
if (Mortician.IsEnable) Mortician.OnPlayerDead(target);
|
||||
if (Bloodhound.IsEnable) Bloodhound.OnPlayerDead(target);
|
||||
if (Tracefinder.IsEnable) Tracefinder.OnPlayerDead(target);
|
||||
if (Vulture.IsEnable) Vulture.OnPlayerDead(target);
|
||||
|
||||
AfterPlayerDeathTasks(target);
|
||||
|
||||
Main.PlayerStates[target.PlayerId].SetDead();
|
||||
@@ -1967,6 +1957,7 @@ class FixedUpdatePatch
|
||||
private static readonly Dictionary<byte, int> BufferTime = [];
|
||||
private static readonly Dictionary<byte, int> DeadBufferTime = [];
|
||||
private static readonly Dictionary<byte, long> LastUpdate = [];
|
||||
private static long LastAddAbilityTime = 0;
|
||||
|
||||
public static async void Postfix(PlayerControl __instance)
|
||||
{
|
||||
@@ -1974,7 +1965,7 @@ class FixedUpdatePatch
|
||||
if (!GameStates.IsModHost) return;
|
||||
|
||||
byte id = __instance.PlayerId;
|
||||
if (GameStates.IsInTask && ReportDeadBodyPatch.CanReport[id] && ReportDeadBodyPatch.WaitReport[id].Count > 0)
|
||||
if (AmongUsClient.Instance.AmHost && GameStates.IsInTask && ReportDeadBodyPatch.CanReport[id] && ReportDeadBodyPatch.WaitReport[id].Count > 0)
|
||||
{
|
||||
if (Glitch.hackedIdList.ContainsKey(id))
|
||||
{
|
||||
@@ -2204,6 +2195,7 @@ class FixedUpdatePatch
|
||||
Duellist.OnFixedUpdate();
|
||||
Kamikaze.OnFixedUpdate();
|
||||
Succubus.OnFixedUpdate();
|
||||
Necromancer.OnFixedUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2409,6 +2401,95 @@ class FixedUpdatePatch
|
||||
if (!lowLoad)
|
||||
{
|
||||
long now = GetTimeStamp();
|
||||
|
||||
// Ability Use Gain every 5 seconds
|
||||
|
||||
if (GameStates.IsInTask && player.IsAlive() && Main.PlayerStates.TryGetValue(playerId, out var state) && state.TaskState.IsTaskFinished && LastAddAbilityTime + 5 < now)
|
||||
{
|
||||
LastAddAbilityTime = now;
|
||||
switch (player.GetCustomRole())
|
||||
{
|
||||
case CustomRoles.Ventguard:
|
||||
Main.VentguardNumberOfAbilityUses += Options.VentguardAbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Grenadier:
|
||||
Main.GrenadierNumOfUsed[playerId] += Options.GrenadierAbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Lighter:
|
||||
Main.LighterNumOfUsed[playerId] += Options.LighterAbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.SecurityGuard:
|
||||
Main.SecurityGuardNumOfUsed[playerId] += Options.SecurityGuardAbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.DovesOfNeace:
|
||||
Main.DovesOfNeaceNumOfUsed[playerId] += Options.DovesOfNeaceAbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.TimeMaster:
|
||||
Main.TimeMasterNumOfUsed[playerId] += Options.TimeMasterAbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Veteran:
|
||||
Main.VeteranNumOfUsed[playerId] += Options.VeteranAbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Bloodhound:
|
||||
Bloodhound.UseLimit[playerId] += Bloodhound.AbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.CameraMan:
|
||||
CameraMan.UseLimit[playerId] += CameraMan.AbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Chameleon:
|
||||
Chameleon.UseLimit[playerId] += Chameleon.AbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Convener:
|
||||
Convener.UseLimit[playerId] += Convener.AbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Divinator:
|
||||
Divinator.CheckLimit[playerId] += Divinator.AbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Doormaster:
|
||||
Doormaster.UseLimit[playerId] += Doormaster.AbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Drainer:
|
||||
Drainer.DrainLimit += Drainer.AbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Druid:
|
||||
Druid.UseLimit[playerId] += Druid.AbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Judge:
|
||||
Judge.TrialLimit[playerId] += Judge.AbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Mediumshiper:
|
||||
Mediumshiper.ContactLimit[playerId] += Mediumshiper.AbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.NiceSwapper:
|
||||
NiceSwapper.UseLimit += NiceSwapper.AbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Oracle:
|
||||
Oracle.CheckLimit[playerId] += Oracle.AbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.ParityCop:
|
||||
ParityCop.MaxCheckLimit[playerId] += ParityCop.AbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Perceiver:
|
||||
Perceiver.UseLimit[playerId] += Perceiver.AbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Ricochet:
|
||||
Ricochet.UseLimit[playerId] += Ricochet.AbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.SabotageMaster:
|
||||
SabotageMaster.UsedSkillCount -= SabotageMaster.AbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Spy:
|
||||
Spy.UseLimit[playerId] += Spy.AbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Tether:
|
||||
Tether.UseLimit[playerId] += Tether.AbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
case CustomRoles.Tracker:
|
||||
Tracker.TrackLimit[playerId] += Tracker.AbilityChargesWhenFinishedTasks.GetFloat();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (player.GetCustomRole())
|
||||
{
|
||||
case CustomRoles.Veteran when GameStates.IsInTask:
|
||||
@@ -2613,7 +2694,7 @@ class FixedUpdatePatch
|
||||
if (__instance.AmOwner)
|
||||
{
|
||||
//キルターゲットの上書き処理
|
||||
if (GameStates.IsInTask && !__instance.Is(CustomRoleTypes.Impostor) && __instance.CanUseKillButton() && !__instance.Data.IsDead)
|
||||
if ((Main.ChangedRole && __instance == PlayerControl.LocalPlayer && AmongUsClient.Instance.AmHost) || (GameStates.IsInTask && !__instance.Is(CustomRoleTypes.Impostor) && __instance.CanUseKillButton() && !__instance.Data.IsDead))
|
||||
{
|
||||
var players = __instance.GetPlayersInAbilityRangeSorted(false);
|
||||
PlayerControl closest = players.Count == 0 ? null : players[0];
|
||||
@@ -3082,29 +3163,6 @@ class SetColorPatch
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(PlayerPhysics), nameof(PlayerPhysics.RpcBootFromVent))]
|
||||
class BootFromVentPatch
|
||||
{
|
||||
public static void Postfix(PlayerPhysics __instance)
|
||||
{
|
||||
if (!AmongUsClient.Instance.AmHost || __instance.myPlayer.PlayerId != 0) return;
|
||||
|
||||
TryMoveToVentPatch.HostVentTarget.SetButtons(false);
|
||||
}
|
||||
}
|
||||
[HarmonyPatch(typeof(Vent), nameof(Vent.TryMoveToVent))]
|
||||
class TryMoveToVentPatch
|
||||
{
|
||||
public static Vent HostVentTarget;
|
||||
public static void Postfix(Vent __instance, [HarmonyArgument(0)] Vent otherVent, bool __result)
|
||||
{
|
||||
if (__result && AmongUsClient.Instance.AmHost && PlayerControl.LocalPlayer.PlayerId == 0 && PlayerControl.LocalPlayer.inVent && (HostVentTarget.Equals(__instance) || HostVentTarget == __instance))
|
||||
{
|
||||
Logger.Info($"(Move) {__instance.name} => {otherVent.name}", "HostVentTarget");
|
||||
HostVentTarget = otherVent;
|
||||
}
|
||||
}
|
||||
}
|
||||
[HarmonyPatch(typeof(Vent), nameof(Vent.ExitVent))]
|
||||
class ExitVentPatch
|
||||
{
|
||||
@@ -3112,13 +3170,6 @@ class ExitVentPatch
|
||||
{
|
||||
Logger.Info($" {pc.GetNameWithRole()}, Vent ID: {__instance.Id} ({__instance.name})", "ExitVent");
|
||||
|
||||
if (pc.PlayerId == 0)
|
||||
{
|
||||
Logger.Info("(Exit) " + __instance.name, "HostVentTarget");
|
||||
TryMoveToVentPatch.HostVentTarget = __instance;
|
||||
__instance.SetButtons(false);
|
||||
}
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
|
||||
Drainer.OnAnyoneExitVent(pc);
|
||||
@@ -3139,13 +3190,6 @@ class EnterVentPatch
|
||||
{
|
||||
Logger.Info($" {pc.GetNameWithRole()}, Vent ID: {__instance.Id} ({__instance.name})", "EnterVent");
|
||||
|
||||
if (pc.PlayerId == 0)
|
||||
{
|
||||
Logger.Info("(Enter) " + __instance.name, "HostVentTarget");
|
||||
TryMoveToVentPatch.HostVentTarget = __instance;
|
||||
__instance.SetButtons(true);
|
||||
}
|
||||
|
||||
Drainer.OnAnyoneEnterVent(pc, __instance);
|
||||
Analyzer.OnAnyoneEnterVent(pc);
|
||||
|
||||
@@ -3563,7 +3607,7 @@ class CoEnterVentPatch
|
||||
}
|
||||
|
||||
//处理弹出管道的阻塞
|
||||
if (((__instance.myPlayer.Data.Role.Role != RoleTypes.Engineer && //不是工程师
|
||||
if (Main.NormalOptions.MapId == (int)MapNames.Dleks || ((__instance.myPlayer.Data.Role.Role != RoleTypes.Engineer && //不是工程师
|
||||
!__instance.myPlayer.CanUseImpostorVentButton()) || //不能使用内鬼的跳管按钮
|
||||
(__instance.myPlayer.Is(CustomRoles.Mayor) && Main.MayorUsedButtonCount.TryGetValue(__instance.myPlayer.PlayerId, out var count) && count >= Options.MayorNumOfUseButton.GetInt()) ||
|
||||
(__instance.myPlayer.Is(CustomRoles.Paranoia) && Main.ParaUsedButtonCount.TryGetValue(__instance.myPlayer.PlayerId, out var count2) && count2 >= Options.ParanoiaNumOfUseButton.GetInt()))
|
||||
@@ -3573,17 +3617,24 @@ class CoEnterVentPatch
|
||||
//(__instance.myPlayer.Is(CustomRoles.DovesOfNeace) && Main.DovesOfNeaceNumOfUsed.TryGetValue(__instance.myPlayer.PlayerId, out var count5) && count5 < 1)
|
||||
)
|
||||
{
|
||||
//MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(__instance.NetId, (byte)RpcCalls.BootFromVent, SendOption.Reliable, -1);
|
||||
//writer.WritePacked(127);
|
||||
//AmongUsClient.Instance.FinishRpcImmediately(writer);
|
||||
_ = new LateTask(() =>
|
||||
try
|
||||
{
|
||||
try { __instance?.RpcBootFromVent(id); } catch { }
|
||||
//int clientId = __instance.myPlayer.GetClientId();
|
||||
//MessageWriter writer2 = AmongUsClient.Instance.StartRpcImmediately(__instance.NetId, (byte)RpcCalls.BootFromVent, SendOption.Reliable, clientId);
|
||||
//writer2.Write(id);
|
||||
//AmongUsClient.Instance.FinishRpcImmediately(writer2);
|
||||
}, 0.5f, "Fix DesyncImpostor Stuck");
|
||||
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(__instance.NetId, (byte)RpcCalls.BootFromVent, SendOption.Reliable, -1);
|
||||
writer.WritePacked(127);
|
||||
AmongUsClient.Instance.FinishRpcImmediately(writer);
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
int clientId = __instance.myPlayer.GetClientId();
|
||||
MessageWriter writer2 = AmongUsClient.Instance.StartRpcImmediately(__instance.NetId, (byte)RpcCalls.BootFromVent, SendOption.Reliable, clientId);
|
||||
writer2.Write(id);
|
||||
AmongUsClient.Instance.FinishRpcImmediately(writer2);
|
||||
}
|
||||
catch { }
|
||||
}, 0.5f, "Fix DesyncImpostor Stuck");
|
||||
}
|
||||
catch { }
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -136,6 +136,14 @@ class RandomSpawn
|
||||
return positions.ToArray().OrderBy(_ => Guid.NewGuid()).Take(1).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
public class DleksSpawnMap : SpawnMap
|
||||
{
|
||||
public Dictionary<string, Vector2> positions = new SkeldSpawnMap().positions.ToDictionary(e => e.Key, e => new Vector2(-e.Value.x, e.Value.y));
|
||||
public override KeyValuePair<string, Vector2> GetLocation()
|
||||
{
|
||||
return positions.ToArray().OrderBy(_ => Guid.NewGuid()).Take(1).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
public class AirshipSpawnMap : SpawnMap
|
||||
{
|
||||
public Dictionary<string, Vector2> positions = new()
|
||||
|
||||
@@ -259,7 +259,7 @@ public static class SecurityCameraPatch
|
||||
{
|
||||
return !((MapNames)Main.NormalOptions.MapId switch
|
||||
{
|
||||
MapNames.Skeld => Options.DisableSkeldCamera.GetBool(),
|
||||
MapNames.Skeld or MapNames.Dleks => Options.DisableSkeldCamera.GetBool(),
|
||||
MapNames.Polus => Options.DisablePolusCamera.GetBool(),
|
||||
MapNames.Airship => Options.DisableAirshipCamera.GetBool(),
|
||||
_ => false,
|
||||
|
||||
@@ -37,9 +37,9 @@ public static class MessageReaderUpdateSystemPatch
|
||||
{
|
||||
try { RepairSystemPatch.Prefix(__instance, systemType, player, MessageReader.Get(reader).ReadByte()); } catch { }
|
||||
}
|
||||
public static void Postfix(ShipStatus __instance, [HarmonyArgument(0)] SystemTypes systemType, [HarmonyArgument(1)] PlayerControl player, [HarmonyArgument(2)] MessageReader reader)
|
||||
public static void Postfix(/*ShipStatus __instance,*/ [HarmonyArgument(0)] SystemTypes systemType, [HarmonyArgument(1)] PlayerControl player, [HarmonyArgument(2)] MessageReader reader)
|
||||
{
|
||||
try { RepairSystemPatch.Postfix(__instance, systemType, player, MessageReader.Get(reader).ReadByte()); } catch { }
|
||||
try { RepairSystemPatch.Postfix(/*__instance,*/ systemType, player, MessageReader.Get(reader).ReadByte()); } catch { }
|
||||
}
|
||||
}
|
||||
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.UpdateSystem), typeof(SystemTypes), typeof(PlayerControl), typeof(byte))]
|
||||
@@ -98,6 +98,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 (Options.CurrentGameMode is CustomGameMode.SoloKombat or CustomGameMode.FFA or CustomGameMode.MoveAndStop) return false;
|
||||
if (Main.BlockSabo.Count > 0) return false;
|
||||
if (Glitch.hackedIdList.ContainsKey(player.PlayerId))
|
||||
{
|
||||
@@ -158,7 +159,7 @@ class RepairSystemPatch
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static void Postfix(ShipStatus __instance,
|
||||
public static void Postfix(/*ShipStatus __instance,*/
|
||||
[HarmonyArgument(0)] SystemTypes systemType,
|
||||
[HarmonyArgument(1)] PlayerControl player,
|
||||
[HarmonyArgument(2)] byte amount)
|
||||
|
||||
+42
-39
@@ -32,55 +32,58 @@ class CanUseVentPatch
|
||||
[HarmonyArgument(2)] ref bool couldUse,
|
||||
ref float __result)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
PlayerControl playerControl = pc.Object;
|
||||
|
||||
//#######################################
|
||||
// ==ベント処理==
|
||||
//#######################################
|
||||
//参考:https://github.com/Eisbison/TheOtherRoles/blob/main/TheOtherRoles/Patches/UsablesPatch.cs
|
||||
// First half, Mod-specific processing
|
||||
|
||||
bool VentForTrigger = false;
|
||||
float num = float.MaxValue;
|
||||
// Determine if vent is available based on custom role
|
||||
// always true for engineer-based roles
|
||||
couldUse = playerControl.CanUseImpostorVentButton() || (pc.Role.Role == RoleTypes.Engineer && pc.Role.CanUse(__instance.Cast<IUsable>()));
|
||||
|
||||
var usableDistance = __instance.UsableDistance;
|
||||
|
||||
if (pc.IsDead) return false; //死んでる人は強制的にfalseに。
|
||||
|
||||
canUse = couldUse = pc.Object.CanUseImpostorVentButton();
|
||||
switch (pc.GetCustomRole())
|
||||
canUse = couldUse;
|
||||
// Not available if custom roles are not available
|
||||
if (!canUse)
|
||||
{
|
||||
case CustomRoles.Arsonist:
|
||||
if (pc.Object.IsDouseDone() && !Options.ArsonistCanIgniteAnytime.GetBool())
|
||||
VentForTrigger = true;
|
||||
break;
|
||||
case CustomRoles.Revolutionist://跳管解锁
|
||||
if (pc.Object.IsDrawDone())
|
||||
VentForTrigger = true;
|
||||
break;
|
||||
default:
|
||||
if (pc.Role.Role == RoleTypes.Engineer) // インポスター陣営ベースの役職とエンジニアベースの役職は常にtrue
|
||||
canUse = couldUse = true;
|
||||
break;
|
||||
}
|
||||
if (!canUse) return false;
|
||||
|
||||
canUse = couldUse = (pc.Object.inVent || canUse) && (pc.Object.CanMove || pc.Object.inVent);
|
||||
|
||||
if (VentForTrigger && pc.Object.inVent)
|
||||
{
|
||||
canUse = couldUse = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Mod's own processing up to this point
|
||||
// Replace vanilla processing from here
|
||||
|
||||
IUsable usableVent = __instance.Cast<IUsable>();
|
||||
// Distance between vent and player
|
||||
float actualDistance = float.MaxValue;
|
||||
|
||||
couldUse =
|
||||
// true for classic and for vanilla HnS
|
||||
GameManager.Instance.LogicUsables.CanUse(usableVent, playerControl) &&
|
||||
// CanUse(usableVent) && Ignore because the decision is based on custom role, not vanilla role
|
||||
// there is no vent task in the target vent or you are in the target vent now
|
||||
(!playerControl.MustCleanVent(__instance.Id) || (playerControl.inVent && Vent.currentVent == __instance)) &&
|
||||
playerControl.IsAlive() &&
|
||||
(playerControl.CanMove || playerControl.inVent);
|
||||
|
||||
// Check vent cleaning
|
||||
if (ShipStatus.Instance.Systems.TryGetValue(SystemTypes.Ventilation, out var systemType))
|
||||
{
|
||||
VentilationSystem ventilationSystem = systemType.TryCast<VentilationSystem>();
|
||||
// If someone is cleaning a vent, you can't get into that vent
|
||||
if (ventilationSystem != null && ventilationSystem.IsVentCurrentlyBeingCleaned(__instance.Id))
|
||||
{
|
||||
couldUse = false;
|
||||
}
|
||||
}
|
||||
|
||||
canUse = couldUse;
|
||||
if (canUse)
|
||||
{
|
||||
Vector2 truePosition = pc.Object.Pos();
|
||||
Vector3 position = __instance.transform.position;
|
||||
num = Vector2.Distance(truePosition, position);
|
||||
canUse &= num <= usableDistance && !PhysicsHelpers.AnythingBetween(truePosition, position, Constants.ShipOnlyMask, false);
|
||||
Vector3 center = playerControl.Collider.bounds.center;
|
||||
Vector3 ventPosition = __instance.transform.position;
|
||||
actualDistance = Vector2.Distance(center, ventPosition);
|
||||
canUse &= actualDistance <= __instance.UsableDistance && !PhysicsHelpers.AnythingBetween(playerControl.Collider, center, ventPosition, Constants.ShipOnlyMask, false);
|
||||
}
|
||||
__result = num;
|
||||
__result = actualDistance;
|
||||
return false;
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
}
|
||||
[HarmonyPatch(typeof(PlayerPurchasesData), nameof(PlayerPurchasesData.GetPurchase))]
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using HarmonyLib;
|
||||
|
||||
namespace TOHE.Patches
|
||||
{
|
||||
[HarmonyPatch(typeof(VoteBanSystem), nameof(VoteBanSystem.AddVote))]
|
||||
class VoteBanSystemPatch
|
||||
{
|
||||
public static bool Prefix()
|
||||
{
|
||||
return !AmongUsClient.Instance.AmHost || !Options.DisableVoteBan.GetBool();
|
||||
}
|
||||
}
|
||||
[HarmonyPatch(typeof(VoteBanSystem), nameof(VoteBanSystem.CmdAddVote))]
|
||||
class VoteBanSystemPatchCmd
|
||||
{
|
||||
public static bool Prefix()
|
||||
{
|
||||
return !AmongUsClient.Instance.AmHost || !Options.DisableVoteBan.GetBool();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -191,7 +191,6 @@ internal class ChangeRoleSettings
|
||||
RPC.SyncCustomSettingsRPC();
|
||||
Main.RefixCooldownDelay = 0;
|
||||
}
|
||||
Main.NiceSwapSend = false;
|
||||
FallFromLadder.Reset();
|
||||
BountyHunter.Init();
|
||||
SerialKiller.Init();
|
||||
@@ -367,6 +366,7 @@ internal class ChangeRoleSettings
|
||||
Agitater.Init();
|
||||
//Pirate.Init();
|
||||
|
||||
Main.ChangedRole = false;
|
||||
|
||||
SoloKombatManager.Init();
|
||||
FFAManager.Init();
|
||||
@@ -713,10 +713,6 @@ internal class SelectRolesPatch
|
||||
_ = new LateTask(() => { PlayerControl.LocalPlayer.NetTransform.SnapTo(new(15.5f, 0.0f), (ushort)(PlayerControl.LocalPlayer.NetTransform.lastSequenceId + 8)); }, 15f, "GM Auto-TP Failsafe"); // TP to Main Hall
|
||||
}
|
||||
|
||||
var vents = UnityEngine.Object.FindObjectsOfType<Vent>();
|
||||
var vent = vents[rd.Next(0, vents.Count)];
|
||||
TryMoveToVentPatch.HostVentTarget = vent;
|
||||
|
||||
RevivePreventerPatch.Ignore = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
</p>
|
||||
<p align="center">
|
||||
|
||||
<a href="https://toher.dev/" target="_blank"><img src="https://img.shields.io/badge/Website%20-%231DA1F2.svg?&style=for-the-badge&logo=vuedotjs&logoColor=white&color=3aa675"/></a>
|
||||
|
||||
<a href="https://sites.google.com/view/toheplus" target="_blank"><img src="https://img.shields.io/badge/Website%20-%231DA1F2.svg?&style=for-the-badge&logo=vuedotjs&logoColor=white&color=3aa675"/></a>
|
||||
<a href="https://discord.gg/m3ayxfumC8" target="_blank"><img src="https://img.shields.io/badge/Discord%20-%231DA1F2.svg?&style=for-the-badge&logo=discord&logoColor=white&color=5662f6"/></a>
|
||||
<a href="https://github.com/Gurge44/TOHE_PLUS_/releases/latest" target="_blank"><img src="https://img.shields.io/badge/Latest Version%20-%231DA1F2.svg?&style=for-the-badge&logo=github&logoColor=white&color=181717"/></a>
|
||||
|
||||
@@ -58,6 +58,8 @@
|
||||
- Everyone knows how many killers remain after each ejection (even if no one was ejected, like it was a skip or a tie)
|
||||
- You can chat during the game if the game mode is FFA
|
||||
- Simplified and shortened role descriptions
|
||||
- Loading animation
|
||||
- Set anyone's role for the next game using '/setrole [player ID] [role name]' (replaces /up)
|
||||
|
||||
### Role specific Improvements
|
||||
#### Crewmates
|
||||
@@ -134,6 +136,10 @@
|
||||
- Mole (Crewmate)
|
||||
- Tornado (Crewmate)
|
||||
- Sentinel (Crewmate)
|
||||
- Rabbit (Crewmate)
|
||||
- Perceiver (Crewmate)
|
||||
- Convener (Crewmate)
|
||||
- Mathematician (Crewmate)
|
||||
- Romantic (Neutral)
|
||||
- Werewolf (Neutral)
|
||||
- Imitator (Neutral)
|
||||
@@ -150,6 +156,8 @@
|
||||
- Bubble (Neutral)
|
||||
- Hookshot (Neutral)
|
||||
- Sprayer (Neutral)
|
||||
- Soul Hunter (Neutral)
|
||||
- Necromancer / Deathknight (Neutral)
|
||||
- Undertaker (Impostor)
|
||||
- Gambler (Impostor)
|
||||
- Mastermind (Impostor)
|
||||
@@ -162,11 +170,21 @@
|
||||
- Yin Yanger (Impostor)
|
||||
- Cantankerous (Impostor)
|
||||
- Duellist (Impostor)
|
||||
- Kamikaze (Impostor)
|
||||
- Swapster (Impostor)
|
||||
- Swiftclaw (Impostor)
|
||||
- Damocles (Impostor-only Add-on)
|
||||
- Deadly Quota (Impostor-only Add-on)
|
||||
- Nimble (Add-on)
|
||||
- Physicist (Add-on)
|
||||
- Stressed (Add-on)
|
||||
- Giant (Add-on)
|
||||
- Magnet (Add-on)
|
||||
- Sleuth (Add-on)
|
||||
- Asthmatic (Add-on)
|
||||
- Disco (Add-on)
|
||||
- Truant (Add-on)
|
||||
- Busy (Add-on)
|
||||
|
||||
## Note:
|
||||
- You can use parts of the code in here, but if you do, you'll have to credit me (Gurge44) or the mod by mentioning its name (TOHE+) and providing a link to this github page. (Or leaving the in-game credits as they are are also fine!)
|
||||
@@ -191,7 +209,7 @@
|
||||
### :star: [TOHY](https://github.com/Yumenopai/TownOfHost_Y) :
|
||||
>
|
||||
> - Many role ideas
|
||||
> - Provided roles: AntiAdminer, CursedWolf, Workaholic, Greedier, DarkHide
|
||||
> - Provided roles: AntiAdminer, CursedWolf, Workaholic, Greedier, DarkHide, Ignitor, Rabbit
|
||||
> - Reference: Modify game announcement
|
||||
>
|
||||
### :star: [TOH:TOR](https://github.com/music-discussion/TownOfHost-TheOtherRoles) :
|
||||
|
||||
@@ -1329,6 +1329,8 @@
|
||||
"TransporterTeleportMax": "Max number of teleports",
|
||||
"TriggerKill": "Kill",
|
||||
"RequiresPetIndicator": " <#ff0000>PET</color>",
|
||||
"SupportsPetIndicator": " <#00ff00>✓PET</color>",
|
||||
"SupportsPetMessage": "\\n\\n<#00ff00>[✓] This role supports Pet button usage for ability triggers or other actions, maybe replacing venting, shapeshifting or killing.</color>",
|
||||
"UsePetInsteadOfKillButton": "Use Pet Button As Kill Button",
|
||||
"UsePets": "Use Pet button instead of Vent / Shapeshift",
|
||||
"PetToAssign": "Pet to Assign to Everyone",
|
||||
@@ -2288,6 +2290,7 @@
|
||||
"CountdownText": "<color=#00ffa5>Re-Entering Lobby in</color> <b>{0}</b>s",
|
||||
"EAC.CheatDetected.HighLevel": "Warning: EAC detected High Level of cheats.",
|
||||
"EAC.CheatDetected.LowLevel": "Warning: EAC detected Low Level of cheats. One of the players is hacking.",
|
||||
"DisableVoteBan": "Disable Vote-Kick (prevent hackers from banning everyone)",
|
||||
"PlayerIsRole": "{0} was {1}.",
|
||||
"PlayerExiled": "{0} was ejected...",
|
||||
"ExiledJester": "You're all fools!\\n{0} the {1} laughing out loud tricked you into ejecting them.\\nGG!",
|
||||
@@ -2360,6 +2363,7 @@
|
||||
"SkeldChance": "Chance that the map is The Skeld",
|
||||
"MiraChance": "Chance that the map is MIRA HQ",
|
||||
"PolusChance": "Chance that the map is Polus",
|
||||
"DleksChance": "Chance that the map is <color=#66a186>dlekS ehT</color>",
|
||||
"AirshipChance": "Chance that the map is Airship",
|
||||
"FungleChance": "Chance that the map is The Fungle",
|
||||
"CamouflageMode.Default": "Default",
|
||||
@@ -2990,12 +2994,13 @@
|
||||
"ExpressSpeedDur": "Increased Speed Duration",
|
||||
"NiceSwapper": "Swapper",
|
||||
"NiceSwapperInfo": "Swap players' votes",
|
||||
"NiceSwapperInfoLong": "(Crewmates):\\nAs the Swapper, you can use the command <b>/sw <color=#0000ff>[ID]</color> twice to choose 2 players. Those votes received by those 2 players will be swapped.\\nYou can see everyone's <color=#0000ff>ID</color>s next to their name.\\n\\nFor example, if 3 players voted red, and 5 players voted yellow, and you swap red and yellows' IDs, then red will receive 5 votes, and yellow will receive 3 votes.\\n\\nDue to technical difficulties, the Host's original vote will seem unchanged, but it's only visual, their vote will still get swapped.",
|
||||
"NiceSwapperInfoLong": "(Crewmates):\\nAs the Swapper, you can use the command <b>/sw <color=#0000ff>[ID]</color></b> twice to choose 2 players. Those votes received by those 2 players will be swapped.\\nYou can see everyone's <color=#0000ff>ID</color>s next to their name.\\n\\nFor example, if 3 players voted red, and 5 players voted yellow, and you swap red and yellows' IDs, then red will receive 5 votes, and yellow will receive 3 votes.\\n\\nDue to technical difficulties, the Host's original vote will seem unchanged, but it's only visual, their vote will still get swapped.",
|
||||
"NiceSwapperMax": "Initial Number of Swaps",
|
||||
"NiceSwapperTrialMax": "Ability use limit reached",
|
||||
"CanSwapSelfVotes": "<color=#922348>Swapper</color> Can Swap Themselves",
|
||||
"SwapperHideMsg": "<color=#00ff00>Hide <color=#922348>Swapper</color>'s commands</color>",
|
||||
"CantSwapSelf": "You can't swap yourself",
|
||||
"SwapDead": "You cannot swap votes after you've died.",
|
||||
"SwapVote": "The votes received by <b>{0}</b> and <b>{1}</b> were swapped!",
|
||||
"SwapTitle": "[★ Swapper ★]",
|
||||
"SecurityGuard": "Security Guard",
|
||||
@@ -3006,6 +3011,8 @@
|
||||
"SecurityGuardSkillDuration": "Ability Duration",
|
||||
"SecurityGuardSkillInUse": "Ability in use",
|
||||
"SecurityGuardSkillStop": "Ability expired",
|
||||
"BusyLongTasks": "Amount of Extra Long Tasks",
|
||||
"BusyShortTasks": "Amount of Extra Short Tasks",
|
||||
"Doormaster": "Door Master",
|
||||
"DoormasterInfo": "Open All Doors Anytime",
|
||||
"DoormasterInfoLong": "(Crewmates):\\nAs the Door Master, you can vent/pet to open all closed doors.\\n\\nDue to technical difficulties, this may not work on some maps.",
|
||||
|
||||
@@ -17,14 +17,14 @@
|
||||
"TeamImpostor": "Impostor",
|
||||
"TeamNeutral": "Neutro",
|
||||
"TeamCrewmate": "Tripulante",
|
||||
"TeamMadmate": "Cúmplice",
|
||||
"TeamMadmate": "Louco",
|
||||
"YouAreCrewmate": "Você é um Tripulante",
|
||||
"YouAreImpostor": "Você é um Impostor",
|
||||
"YouAreNeutral": "Você é um Neutro",
|
||||
"YouAreMadmate": "Você é um Cúmplice",
|
||||
"YouAreMadmate": "Você é um Louco",
|
||||
"CrewmateSub": "Encontre e expulse os <color=#ff1919>Impostores</color>",
|
||||
"ImpostorSub": "Sabote e mate todos",
|
||||
"NeutralSub": "Trabalhe sozinho e alcance a vitória",
|
||||
"NeutralSub": "Vença por sua conta!",
|
||||
"MadmateSub": "Ajude os <color=#ff1919>Impostores</color>",
|
||||
"KB_Normal": "Desafiante",
|
||||
"KB_NormalInfo": "Mate todos!",
|
||||
@@ -1251,7 +1251,7 @@
|
||||
"CanTargetNeutralEvil": "O seu alvo pode ser um <color=#7f8c8d>Neutro</color> <color=#912900>Malvado</color>",
|
||||
"CanTargetNeutralChaos": "O seu alvo pode ser um <color=#7f8c8d>Neutro</color> do <color=#D4AF37>Caos</color>",
|
||||
"SidekickSheriffCanGoBerserk": "<color=#f8cd46>Xerife</color> <color=#00b4eb>Recrutado</color> pode enlouquecer",
|
||||
"LawyerCanTargetImpostor": "O seu cliente pode ser um <color=#ff1919>Impostor</color>",
|
||||
"LawyerCanTargetImpostor": "O alvo poderá ser <color=#ff1919>Impostor</color>",
|
||||
"LawyerCanTargetNeutralKiller": "O seu cliente pode ser um <color=#7f8c8d>Neutro Assassino</color>",
|
||||
"LawyerCanTargetCrewmate": "O seu cliente pode ser um <color=#8cffff>Tripulante</color>",
|
||||
"LawyerCanTargetJester": "O seu cliente pode ser um <color=#ec62a5>Palhaço</color>",
|
||||
@@ -1329,6 +1329,8 @@
|
||||
"TransporterTeleportMax": "Número máximo de teletransportes",
|
||||
"TriggerKill": "Abate",
|
||||
"RequiresPetIndicator": " <#ff0000>PET</color>",
|
||||
"SupportsPetIndicator": " <#00ff00>✓PET</color>",
|
||||
"SupportsPetMessage": "\\n\\n<#00ff00>[✓] Este cargo suporta o uso de botões para animais por habilidades acionadas ou outras ações, talvez substituindo ventas, shapeshifting ou killing.</color>",
|
||||
"UsePetInsteadOfKillButton": "Usar botão Acariciar ao inves do Botão Matar",
|
||||
"UsePets": "Usar Botão Acariciar ao invés de Duto / Metamorfose",
|
||||
"PetToAssign": "Pet para Atribuir a todos",
|
||||
@@ -2288,6 +2290,7 @@
|
||||
"CountdownText": "Voltando para o lobby em {0}s",
|
||||
"EAC.CheatDetected.HighLevel": "Aviso: EAC detectou altos níveis de trapaças.",
|
||||
"EAC.CheatDetected.LowLevel": "Aviso: EAC detectou baixo nível de trapaças. Um dos jogadores está hackeando.",
|
||||
"DisableVoteBan": "Desativar Vote-Kick (impedir que hackers proíbam todos)",
|
||||
"PlayerIsRole": "{0} era o {1}",
|
||||
"PlayerExiled": "{0} foi ejetado",
|
||||
"ExiledJester": "Você foi enganado!\\n{0} era o {1} rindo da maneira que enganou vocês.\\nGG!",
|
||||
@@ -2360,6 +2363,7 @@
|
||||
"SkeldChance": "Chance do mapa ser <color=#66a186>The Skeld</color>",
|
||||
"MiraChance": "Chance do mapa ser <color=#e84b56>MIRA HQ</color>",
|
||||
"PolusChance": "Chance do mapa ser <color=#a167c0>Polus</color>",
|
||||
"DleksChance": "Chance de que o mapa seja <color=#66a186>dlekS ehT</color>",
|
||||
"AirshipChance": "Chance do mapa ser <color=#ed0007>Airship</color>",
|
||||
"FungleChance": "Chance do mapa ser <color=#ffa646>The Fungle</color>",
|
||||
"CamouflageMode.Default": "Padrão",
|
||||
@@ -2943,7 +2947,7 @@
|
||||
"SoulHunterTargetNotifyNoVent": "<color=#ffff00>Você não pode usar os dutos no tempo de caça</color>",
|
||||
"SoulHunterTargetNotifyNoMeeting": "<color=#ffff00>Você não pode chamar uma reunião no tempo de caça</color>",
|
||||
"SoulHunterTargetNotifyNoKill": "<color=#ffff00>Você não pode matar o <color=#3f2c61>Ceifador de Almas</color>no tempo de caça</color>",
|
||||
"SoulHunterNotify": "Você tem <color=#00ffa5>{0}s</color> para matar <color=#3f2c61>{1}</color>{0",
|
||||
"SoulHunterNotify": "Você tem <color=#00ffa5>{0}s</color> para matar <color=#3f2c61>{1}</color>",
|
||||
"SoulHunterNotifySuccess": "<color=#00ff00>Sucesso!</color>",
|
||||
"SoulHunterNotifyFreeze": "Você pode começar a caçar <color=#3f2c61>{0}</color> em <color=#00ffa5>{1}s</color>",
|
||||
"Librarian": "Bibliotecário",
|
||||
@@ -2990,12 +2994,13 @@
|
||||
"ExpressSpeedDur": "Duração do Impulso de Velocidade",
|
||||
"NiceSwapper": "Trocador",
|
||||
"NiceSwapperInfo": "Troque os Votos de Jogadores",
|
||||
"NiceSwapperInfoLong": "(Tripulantes):\\nComo Trocador, você pode usar o comando <b>/sw <color=#0000ff>[ID]</color> duas vezes para escolher 2 jogadores. os votos recebidos nesses 2 jogadores serão trocados.\\nVocê pode ver os <color=#0000ff>ID</color>s de todos proximo ao nome.\\n\\nPor Exemplo, se 3 jogadores votaram no Vermelho, e 5 jogadores votaram no Amarelo, e você trocar os IDs do Vermelho e do Amarelo, então o Vermelho receberá 5 votos, e o Amarelo receberá 3.\\n\\nDevido a Dificuldades Tecnicas, o voto original do Anfitrião aparecerá normal (Nada Muda), mas é só visual, os votos ainda serão trocados.",
|
||||
"NiceSwapperInfoLong": "(Tripulantes):\\nComo Trocador, você pode usar o comando <b>/sw <color=#0000ff>[ID]</color></b> duas vezes para escolher 2 jogadores. os votos recebidos nesses 2 jogadores serão trocados.\\nVocê pode ver os <color=#0000ff>ID</color>s de todos proximo ao nome.\\n\\nPor Exemplo, se 3 jogadores votaram no Vermelho, e 5 jogadores votaram no Amarelo, e você trocar os IDs do Vermelho e do Amarelo, então o Vermelho receberá 5 votos, e o Amarelo receberá 3.\\n\\nDevido a Dificuldades Tecnicas, o voto original do Anfitrião aparecerá normal (Nada Muda), mas é só visual, os votos ainda serão trocados.",
|
||||
"NiceSwapperMax": "Numero Inicial de Trocas",
|
||||
"NiceSwapperTrialMax": "Você atingiu seu limite de usos de habilidade!",
|
||||
"CanSwapSelfVotes": "Pode trocar seus próprios votos.",
|
||||
"SwapperHideMsg": "<color=#00ff00>Esconder Comandos do <color=#922348>Trocador</color></color>",
|
||||
"CantSwapSelf": "Não é possível trocar o próprio voto",
|
||||
"SwapDead": "Não é possível trocar votos depois de ter morrido.",
|
||||
"SwapVote": "<b>{0}</b> e <b>{1}</b> Os votos foram trocados pelo Trocador",
|
||||
"SwapTitle": "[ ★ Troca de Votos ★ ]",
|
||||
"SecurityGuard": "Guarda de Segurança",
|
||||
@@ -3006,6 +3011,8 @@
|
||||
"SecurityGuardSkillDuration": "Duração da Habilidade",
|
||||
"SecurityGuardSkillInUse": "Habilidade em uso",
|
||||
"SecurityGuardSkillStop": "Habilidade Expirou",
|
||||
"BusyLongTasks": "Quantidade de tarefas longas extras",
|
||||
"BusyShortTasks": "Quantidade de Tarefas Extras Curtas",
|
||||
"Doormaster": "Porteiro",
|
||||
"DoormasterInfo": "Abra portas",
|
||||
"DoormasterInfoLong": "(Tripulantes):\\nComo Porteiro, você pode dutar/usar pet para abrir todas as portas fechadas.\\n\\nDevido a dificuldades técnicas, isso pode nmão funcionar em alguns mapas.",
|
||||
|
||||
+21
-21
@@ -320,27 +320,27 @@ namespace TOHE.Roles.Crewmate
|
||||
var str = new StringBuilder();
|
||||
switch (PotionID)
|
||||
{
|
||||
case 1: // Shield
|
||||
str.Append($" <color=#00ffa5>{GetString("Stored")}:</color> <color=#00ff97>{GetString("ShieldPotion")}</color>");
|
||||
break;
|
||||
case 2: // Suicide
|
||||
str.Append($" <color=#00ffa5>{GetString("Stored")}:</color> <color=#ff0000>{GetString("AwkwardPotion")}</color>");
|
||||
break;
|
||||
case 3: // TP to random player
|
||||
str.Append($" <color=#00ffa5>{GetString("Stored")}:</color> <color=#42d1ff>{GetString("TeleportPotion")}</color>");
|
||||
break;
|
||||
case 4: // Increased speed
|
||||
str.Append($" <color=#00ffa5>{GetString("Stored")}:</color> <color=#ff8400>{GetString("SpeedPotion")}</color>");
|
||||
break;
|
||||
case 5: // Quick fix next sabo
|
||||
str.Append($" <color=#00ffa5>{GetString("Stored")}:</color> <color=#3333ff>{GetString("QuickFixPotion")}</color>");
|
||||
break;
|
||||
case 6: // Invisibility
|
||||
str.Append($" <color=#00ffa5>{GetString("Stored")}:</color> <color=#01c834>{GetString("InvisibilityPotion")}</color>");
|
||||
break;
|
||||
case 7: // Increased vision
|
||||
str.Append($" <color=#00ffa5>{GetString("Stored")}:</color> <color=#eee5be>{GetString("SightPotion")}</color>");
|
||||
break;
|
||||
case 1: // Shield
|
||||
str.Append($" <color=#00ffa5>{GetString("Stored")}:</color> <color=#00ff97>{GetString("ShieldPotion")}</color>");
|
||||
break;
|
||||
case 2: // Suicide
|
||||
str.Append($" <color=#00ffa5>{GetString("Stored")}:</color> <color=#ff0000>{GetString("AwkwardPotion")}</color>");
|
||||
break;
|
||||
case 3: // TP to random player
|
||||
str.Append($" <color=#00ffa5>{GetString("Stored")}:</color> <color=#42d1ff>{GetString("TeleportPotion")}</color>");
|
||||
break;
|
||||
case 4: // Increased speed
|
||||
str.Append($" <color=#00ffa5>{GetString("Stored")}:</color> <color=#ff8400>{GetString("SpeedPotion")}</color>");
|
||||
break;
|
||||
case 5: // Quick fix next sabo
|
||||
str.Append($" <color=#00ffa5>{GetString("Stored")}:</color> <color=#3333ff>{GetString("QuickFixPotion")}</color>");
|
||||
break;
|
||||
case 6: // Invisibility
|
||||
str.Append($" <color=#00ffa5>{GetString("Stored")}:</color> <color=#01c834>{GetString("InvisibilityPotion")}</color>");
|
||||
break;
|
||||
case 7: // Increased vision
|
||||
str.Append($" <color=#00ffa5>{GetString("Stored")}:</color> <color=#eee5be>{GetString("SightPotion")}</color>");
|
||||
break;
|
||||
}
|
||||
if (FixNextSabo) str.Append($" <color=#777777>({Translator.GetString("QuickFix")})</color>");
|
||||
return str.ToString();
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
public static OptionItem LeaveDeadBodyUnreportable;
|
||||
public static OptionItem NotifyKiller;
|
||||
public static OptionItem BloodhoundAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
@@ -32,6 +33,9 @@
|
||||
BloodhoundAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 13, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Bloodhound])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(Id + 15, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Bloodhound])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace TOHE.Roles.Crewmate
|
||||
public static OptionItem VentCooldown;
|
||||
public static OptionItem UseLimitOpt;
|
||||
public static OptionItem CameraManAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
@@ -28,6 +29,9 @@ namespace TOHE.Roles.Crewmate
|
||||
CameraManAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 12, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 1f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.CameraMan])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(Id + 13, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.CameraMan])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -66,13 +70,14 @@ namespace TOHE.Roles.Crewmate
|
||||
UseLimit[pc.PlayerId] -= 1;
|
||||
SendRPC(pc.PlayerId);
|
||||
|
||||
Vector2 pos = Main.NormalOptions.MapId switch
|
||||
Vector2 pos = Main.CurrentMap switch
|
||||
{
|
||||
0 => new(-13.5f, -5.5f),
|
||||
1 => new(15.3f, 3.8f),
|
||||
2 => new(3.0f, -12.0f),
|
||||
4 => new(5.8f, -10.8f),
|
||||
5 => new(9.5f, 1.2f),
|
||||
MapNames.Skeld => new(-13.5f, -5.5f),
|
||||
MapNames.Mira => new(15.3f, 3.8f),
|
||||
MapNames.Polus => new(3.0f, -12.0f),
|
||||
MapNames.Dleks => new(-13.5f, -5.5f),
|
||||
MapNames.Airship => new(5.8f, -10.8f),
|
||||
MapNames.Fungle => new(9.5f, 1.2f),
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ public static class Chameleon
|
||||
private static OptionItem ChameleonDuration;
|
||||
public static OptionItem UseLimitOpt;
|
||||
public static OptionItem ChameleonAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
|
||||
private static Dictionary<byte, long> InvisTime = [];
|
||||
private static Dictionary<byte, long> lastTime = [];
|
||||
@@ -33,8 +34,11 @@ public static class Chameleon
|
||||
UseLimitOpt = IntegerOptionItem.Create(Id + 4, "AbilityUseLimit", new(0, 20, 1), 1, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Chameleon])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
ChameleonAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 5, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.5f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Chameleon])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Chameleon])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(Id + 6, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Chameleon])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace TOHE.Roles.Crewmate
|
||||
public static OptionItem CD;
|
||||
public static OptionItem Limit;
|
||||
public static OptionItem ConvenerAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
public static readonly Dictionary<byte, float> UseLimit = [];
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
@@ -21,6 +22,9 @@ namespace TOHE.Roles.Crewmate
|
||||
ConvenerAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 4, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.4f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Convener])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(Id + 5, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Convener])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
}
|
||||
public static void Init() => UseLimit.Clear();
|
||||
public static void Add(byte playerId) => UseLimit[playerId] = Limit.GetInt();
|
||||
|
||||
@@ -173,9 +173,6 @@ public static class CopyCat
|
||||
case CustomRoles.Judge:
|
||||
Judge.TrialLimit.Remove(player);
|
||||
break;
|
||||
case CustomRoles.NiceSwapper:
|
||||
NiceSwapper.NiceSwappermax.Remove(player);
|
||||
break;
|
||||
case CustomRoles.Mayor:
|
||||
Main.MayorUsedButtonCount.Remove(player);
|
||||
break;
|
||||
@@ -205,6 +202,7 @@ public static class CopyCat
|
||||
CustomRoles.Escort or
|
||||
CustomRoles.DonutDelivery or
|
||||
CustomRoles.Gaulois or
|
||||
CustomRoles.NiceSwapper or
|
||||
CustomRoles.Analyzer or
|
||||
//bcoz of arrows
|
||||
CustomRoles.Mortician or
|
||||
|
||||
@@ -16,6 +16,7 @@ public static class Divinator
|
||||
public static OptionItem HideVote;
|
||||
public static OptionItem ShowSpecificRole;
|
||||
public static OptionItem AbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
public static List<byte> didVote = [];
|
||||
@@ -34,6 +35,9 @@ 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);
|
||||
AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(Id + 16, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, 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);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace TOHE.Roles.Crewmate
|
||||
public static OptionItem VentCooldown;
|
||||
public static OptionItem UseLimitOpt;
|
||||
public static OptionItem DoormasterAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
@@ -29,6 +30,9 @@ namespace TOHE.Roles.Crewmate
|
||||
DoormasterAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 12, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 1f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Doormaster])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(Id + 13, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Doormaster])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace TOHE.Roles.Crewmate
|
||||
private static OptionItem VentCD;
|
||||
private static OptionItem UseLimit;
|
||||
public static OptionItem DrainerAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
|
||||
public static float DrainLimit;
|
||||
|
||||
@@ -31,6 +32,9 @@ namespace TOHE.Roles.Crewmate
|
||||
DrainerAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 12, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.5f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Drainer])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(Id + 13, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Drainer])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace TOHE.Roles.Crewmate
|
||||
private static OptionItem TriggerPlaceDelay;
|
||||
private static OptionItem UseLimitOpt;
|
||||
public static OptionItem DruidAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
|
||||
private static Dictionary<byte, long> TriggerDelays = [];
|
||||
private static Dictionary<byte, Dictionary<Vector2, string>> Triggers = [];
|
||||
@@ -39,6 +40,9 @@ namespace TOHE.Roles.Crewmate
|
||||
DruidAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 13, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 1f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Druid])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(Id + 14, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Druid])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
|
||||
@@ -25,6 +25,7 @@ public static class Judge
|
||||
private static OptionItem CanTrialNeutralE;
|
||||
private static OptionItem CanTrialNeutralC;
|
||||
public static OptionItem JudgeAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
public static Dictionary<byte, float> TrialLimit;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
@@ -43,6 +44,7 @@ public static class Judge
|
||||
CanTrialNeutralK = BooleanOptionItem.Create(Id + 15, "JudgeCanTrialNeutralK", true, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Judge]);
|
||||
TryHideMsg = BooleanOptionItem.Create(Id + 11, "JudgeTryHideMsg", true, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Judge]).SetColor(Color.green);
|
||||
JudgeAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 19, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.3f, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Judge]).SetValueFormat(OptionFormat.Times);
|
||||
AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(Id + 20, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Judge]).SetValueFormat(OptionFormat.Times);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ public static class Mediumshiper
|
||||
public static OptionItem ContactLimitOpt;
|
||||
public static OptionItem OnlyReceiveMsgFromCrew;
|
||||
public static OptionItem MediumAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
|
||||
public static Dictionary<byte, byte> ContactPlayer = [];
|
||||
public static Dictionary<byte, float> ContactLimit = [];
|
||||
@@ -26,6 +27,9 @@ public static class Mediumshiper
|
||||
MediumAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 12, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 1f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Mediumshiper])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(Id + 13, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Mediumshiper])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
|
||||
@@ -79,6 +79,12 @@ internal class Monitor
|
||||
if (!Options.DisablePolusVital.GetBool())
|
||||
Vital |= Vector2.Distance(PlayerPos, DisableDevice.DevicePos["PolusVital"]) <= DisableDevice.UsableDistance();
|
||||
break;
|
||||
case 3:
|
||||
if (!Options.DisableSkeldAdmin.GetBool())
|
||||
Admin |= Vector2.Distance(PlayerPos, DisableDevice.DevicePos["DleksAdmin"]) <= DisableDevice.UsableDistance();
|
||||
if (!Options.DisableSkeldCamera.GetBool())
|
||||
Camera |= Vector2.Distance(PlayerPos, DisableDevice.DevicePos["DleksCamera"]) <= DisableDevice.UsableDistance();
|
||||
break;
|
||||
case 4:
|
||||
if (!Options.DisableAirshipCockpitAdmin.GetBool())
|
||||
Admin |= Vector2.Distance(PlayerPos, DisableDevice.DevicePos["AirshipCockpitAdmin"]) <= DisableDevice.UsableDistance();
|
||||
@@ -123,7 +129,7 @@ internal class Monitor
|
||||
{
|
||||
PlayerControl pc = Utils.GetPlayerById(id);
|
||||
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
||||
FixedUpdatePatch.Postfix(pc);
|
||||
FixedUpdatePatch.DoPostfix(pc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+158
-133
@@ -18,167 +18,187 @@ public static class NiceSwapper
|
||||
public static OptionItem CanSwapSelf;
|
||||
public static OptionItem CanStartMeeting;
|
||||
public static OptionItem NiceSwapperAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
|
||||
private static (byte, byte) SwapTargets;
|
||||
public static float UseLimit;
|
||||
private static byte NiceSwapperId = byte.MaxValue;
|
||||
private static PlayerControl NiceSwapper_ = null;
|
||||
|
||||
public static List<byte> playerIdList = [];
|
||||
public static List<byte> Vote = [];
|
||||
public static List<byte> VoteTwo = [];
|
||||
public static Dictionary<byte, float> NiceSwappermax = [];
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
Options.SetupSingleRoleOptions(Id, TabGroup.CrewmateRoles, CustomRoles.NiceSwapper, 1);
|
||||
SwapMax = IntegerOptionItem.Create(Id + 3, "NiceSwapperMax", new(0, 20, 1), 1, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.NiceSwapper])
|
||||
Options.SetupSingleRoleOptions(Id, TabGroup.OtherRoles, CustomRoles.NiceSwapper, 1);
|
||||
SwapMax = IntegerOptionItem.Create(Id + 3, "NiceSwapperMax", new(0, 20, 1), 1, TabGroup.OtherRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.NiceSwapper])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
CanSwapSelf = BooleanOptionItem.Create(Id + 2, "CanSwapSelfVotes", true, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.NiceSwapper]);
|
||||
CanStartMeeting = BooleanOptionItem.Create(Id + 4, "JesterCanUseButton", true, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.NiceSwapper]);
|
||||
NiceSwapperAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 6, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.3f, TabGroup.CrewmateRoles, false)
|
||||
CanSwapSelf = BooleanOptionItem.Create(Id + 2, "CanSwapSelfVotes", true, TabGroup.OtherRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.NiceSwapper]);
|
||||
CanStartMeeting = BooleanOptionItem.Create(Id + 4, "JesterCanUseButton", true, TabGroup.OtherRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.NiceSwapper]);
|
||||
NiceSwapperAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 6, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.3f, TabGroup.OtherRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.NiceSwapper])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
HideMsg = BooleanOptionItem.Create(Id + 5, "SwapperHideMsg", true, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.NiceSwapper]);
|
||||
AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(Id + 7, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.OtherRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.NiceSwapper])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
HideMsg = BooleanOptionItem.Create(Id + 5, "SwapperHideMsg", true, TabGroup.OtherRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.NiceSwapper]);
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
playerIdList = [];
|
||||
Vote = [];
|
||||
VoteTwo = [];
|
||||
NiceSwappermax = [];
|
||||
SwapTargets = (byte.MaxValue, byte.MaxValue);
|
||||
UseLimit = 0;
|
||||
NiceSwapperId = byte.MaxValue;
|
||||
NiceSwapper_ = null;
|
||||
}
|
||||
|
||||
public static void Add(byte playerId)
|
||||
{
|
||||
playerIdList.Add(playerId);
|
||||
NiceSwappermax.TryAdd(playerId, SwapMax.GetInt());
|
||||
NiceSwapperId = playerId;
|
||||
NiceSwapper_ = Utils.GetPlayerById(playerId);
|
||||
UseLimit = SwapMax.GetInt();
|
||||
}
|
||||
public static bool IsEnable => playerIdList.Count > 0;
|
||||
public static string GetNiceSwappermax(byte playerId) => Utils.ColorString((NiceSwappermax.TryGetValue(playerId, out var x) && x >= 1) ? Color.white : Color.red, NiceSwappermax.TryGetValue(playerId, out var changermax) ? $"<color=#777777>-</color> {Math.Round(changermax, 1)}" : "Invalid");
|
||||
|
||||
public static bool IsEnable => NiceSwapperId != byte.MaxValue;
|
||||
|
||||
public static string ProgressText => Utils.ColorString((UseLimit >= 1) ? Color.white : Color.red, $" <color=#777777>-</color> {Math.Round(UseLimit, 1)}");
|
||||
|
||||
public static bool SwapMsg(PlayerControl pc, string msg, bool isUI = false)
|
||||
{
|
||||
var originMsg = msg;
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return false;
|
||||
if (!GameStates.IsInGame || pc == null) return false;
|
||||
if (pc.GetCustomRole() != CustomRoles.NiceSwapper) return false;
|
||||
|
||||
int operate = 0;
|
||||
msg = msg.ToLower().TrimStart().TrimEnd();
|
||||
if (CheckCommond(ref msg, "id|guesslist|gl编号|玩家编号|玩家id|id列表|玩家列表|列表|所有id|全部id")) operate = 1;
|
||||
else if (CheckCommond(ref msg, "sw|换票|换|swap|st", false)) operate = 2;
|
||||
else return false;
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost || !GameStates.IsInGame || pc == null || pc.GetCustomRole() != CustomRoles.NiceSwapper) return false;
|
||||
if (!pc.IsAlive())
|
||||
{
|
||||
if (!isUI) Utils.SendMessage(GetString("SwapDead"), pc.PlayerId);
|
||||
pc.ShowPopUp(GetString("SwapDead"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (operate == 1)
|
||||
if (UseLimit < 1)
|
||||
{
|
||||
Utils.SendMessage(GuessManager.GetFormatString(), pc.PlayerId);
|
||||
if (!isUI) Utils.SendMessage(GetString("NiceSwapperTrialMax"), pc.PlayerId);
|
||||
pc.ShowPopUp(GetString("NiceSwapperTrialMax"));
|
||||
return true;
|
||||
}
|
||||
else if (operate == 2)
|
||||
|
||||
int operate = 0;
|
||||
msg = msg.ToLower().TrimStart().TrimEnd();
|
||||
if (CheckCommand(ref msg, "id|guesslist|gl编号|玩家编号|玩家id|id列表|玩家列表|列表|所有id|全部id")) operate = 1;
|
||||
else if (CheckCommand(ref msg, "sw|换票|换|swap|st", false)) operate = 2;
|
||||
else return false;
|
||||
|
||||
switch (operate)
|
||||
{
|
||||
if (HideMsg.GetBool() && !isUI) ChatManager.SendPreviousMessagesToAll();
|
||||
else if (pc.AmOwner && !isUI) Utils.SendMessage(originMsg, 255, pc.GetRealName());
|
||||
|
||||
if (!MsgToPlayerAndRole(msg, out byte targetId, out string error))
|
||||
{
|
||||
Utils.SendMessage(error, pc.PlayerId);
|
||||
case 1:
|
||||
Utils.SendMessage(GuessManager.GetFormatString(), pc.PlayerId);
|
||||
return true;
|
||||
}
|
||||
var target = Utils.GetPlayerById(targetId);
|
||||
if (target != null)
|
||||
{
|
||||
if (NiceSwappermax[pc.PlayerId] < 1)
|
||||
case 2:
|
||||
{
|
||||
if (!isUI) Utils.SendMessage(GetString("NiceSwapperTrialMax"), pc.PlayerId);
|
||||
pc.ShowPopUp(GetString("NiceSwapperTrialMax"));
|
||||
return true;
|
||||
}
|
||||
if (HideMsg.GetBool() && !isUI) ChatManager.SendPreviousMessagesToAll();
|
||||
else if (pc.AmOwner && !isUI) Utils.SendMessage(originMsg, 255, pc.GetRealName());
|
||||
|
||||
var dp = target;
|
||||
if (!MsgToPlayerAndRole(msg, out byte targetId, out string error))
|
||||
{
|
||||
Utils.SendMessage(error, pc.PlayerId);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool targetIsntSelected = !Vote.Contains(dp.PlayerId) && !VoteTwo.Contains(dp.PlayerId);
|
||||
var target = Utils.GetPlayerById(targetId);
|
||||
if (target == null) break;
|
||||
|
||||
bool Vote1Empty = Vote.Count == 0 && targetIsntSelected;
|
||||
bool Vote2Available = Vote.Count == 1 && VoteTwo.Count == 0 && targetIsntSelected;
|
||||
bool targetIsntSelected = SwapTargets.Item1 != target.PlayerId && SwapTargets.Item2 != target.PlayerId; // Whether the picked target isn't already being swapped
|
||||
|
||||
if ((Vote1Empty && CanSwapSelf.GetBool()) ||
|
||||
(Vote1Empty && dp != pc && !CanSwapSelf.GetBool()))
|
||||
{
|
||||
Vote.Add(dp.PlayerId);
|
||||
if (HideMsg.GetBool() && !isUI)
|
||||
{
|
||||
ChatManager.SendPreviousMessagesToAll();
|
||||
}
|
||||
if (!isUI) Utils.SendMessage(GetString("Swap1"), pc.PlayerId);
|
||||
//else pc.ShowPopUp(GetString("Swap1"));
|
||||
Logger.Info($"{pc.GetNameWithRole().RemoveHtmlTags()} 选择 {target.GetNameWithRole()}", "Swapper");
|
||||
}
|
||||
else if ((Vote2Available && CanSwapSelf.GetBool()) ||
|
||||
(Vote2Available && dp != pc && !CanSwapSelf.GetBool()))
|
||||
{
|
||||
VoteTwo.Add(dp.PlayerId);
|
||||
if (HideMsg.GetBool() && !isUI)
|
||||
{
|
||||
ChatManager.SendPreviousMessagesToAll();
|
||||
}
|
||||
if (!isUI) Utils.SendMessage(GetString("Swap2"), pc.PlayerId);
|
||||
//else pc.ShowPopUp(GetString("Swap2"));
|
||||
Logger.Info($"{pc.GetNameWithRole().RemoveHtmlTags()} 选择 {target.GetNameWithRole()}", "Swapper");
|
||||
}
|
||||
else if (Vote.Count > 0 && Vote.Contains(dp.PlayerId))
|
||||
{
|
||||
Vote.Remove(dp.PlayerId);
|
||||
if (HideMsg.GetBool() && !isUI)
|
||||
{
|
||||
ChatManager.SendPreviousMessagesToAll();
|
||||
}
|
||||
if (!isUI) Utils.SendMessage(GetString("CancelSwap1"), pc.PlayerId);
|
||||
//else pc.ShowPopUp(GetString("CancelSwap1"));
|
||||
Logger.Info($"{pc.GetNameWithRole().RemoveHtmlTags()} 取消选择 {target.GetNameWithRole()}", "Swapper");
|
||||
}
|
||||
else if (VoteTwo.Contains(dp.PlayerId) && VoteTwo.Count > 0)
|
||||
{
|
||||
VoteTwo.Remove(dp.PlayerId);
|
||||
if (HideMsg.GetBool() && !isUI)
|
||||
{
|
||||
ChatManager.SendPreviousMessagesToAll();
|
||||
}
|
||||
if (!isUI) Utils.SendMessage(GetString("CancelSwap2"), pc.PlayerId);
|
||||
//else pc.ShowPopUp(GetString("CancelSwap2"));
|
||||
Logger.Info($"{pc.GetNameWithRole().RemoveHtmlTags()} 取消选择 {target.GetNameWithRole()}", "Swapper");
|
||||
}
|
||||
else if (pc == dp && !CanSwapSelf.GetBool())
|
||||
{
|
||||
if (HideMsg.GetBool() && !isUI)
|
||||
{
|
||||
ChatManager.SendPreviousMessagesToAll();
|
||||
}
|
||||
if (!isUI) Utils.SendMessage(GetString("CantSwapSelf"), pc.PlayerId);
|
||||
else pc.ShowPopUp(GetString("CantSwapSelf"));
|
||||
}
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
if (Vote.Count > 0 && VoteTwo.Count > 0)
|
||||
{
|
||||
PlayerControl player1 = new();
|
||||
PlayerControl player2 = new();
|
||||
foreach (byte swap1 in Vote.ToArray())
|
||||
{
|
||||
player1.PlayerId = swap1;
|
||||
}
|
||||
foreach (byte swap2 in Vote.ToArray())
|
||||
{
|
||||
player2.PlayerId = swap2;
|
||||
}
|
||||
}
|
||||
Utils.NotifyRoles(isForMeeting: true, NoCache: true);
|
||||
}, 0.2f);
|
||||
}
|
||||
bool Vote1Empty = (SwapTargets.Item1 == byte.MaxValue) && targetIsntSelected; // Whether the first swapping slot is suitable to swap this target
|
||||
bool Vote2Available = (SwapTargets.Item1 != byte.MaxValue) && (SwapTargets.Item2 == byte.MaxValue) && targetIsntSelected; // Whether the second swapping slot is suitable to swap this target
|
||||
|
||||
if (Vote1Empty && (CanSwapSelf.GetBool() || target.PlayerId != pc.PlayerId)) // Take first slot
|
||||
{
|
||||
SwapTargets.Item1 = target.PlayerId;
|
||||
|
||||
if (HideMsg.GetBool() && !isUI) ChatManager.SendPreviousMessagesToAll();
|
||||
if (!isUI) Utils.SendMessage(GetString("Swap1"), pc.PlayerId);
|
||||
Logger.Info($"{pc.GetNameWithRole().RemoveHtmlTags()} chose to swap {target.GetNameWithRole()} (first target)", "Swapper");
|
||||
}
|
||||
|
||||
else if (Vote2Available && (CanSwapSelf.GetBool() || target.PlayerId != pc.PlayerId)) // Take second slot
|
||||
{
|
||||
SwapTargets.Item2 = target.PlayerId;
|
||||
|
||||
if (HideMsg.GetBool() && !isUI) ChatManager.SendPreviousMessagesToAll();
|
||||
if (!isUI) Utils.SendMessage(GetString("Swap2"), pc.PlayerId);
|
||||
Logger.Info($"{pc.GetNameWithRole().RemoveHtmlTags()} chose to swap {target.GetNameWithRole()} (second target)", "Swapper");
|
||||
}
|
||||
|
||||
else if (target.PlayerId == SwapTargets.Item1) // If this player is already chosen to be swapped in the first slot, cancel it
|
||||
{
|
||||
SwapTargets.Item1 = byte.MaxValue;
|
||||
|
||||
if (HideMsg.GetBool() && !isUI) ChatManager.SendPreviousMessagesToAll();
|
||||
if (!isUI) Utils.SendMessage(GetString("CancelSwap1"), pc.PlayerId);
|
||||
Logger.Info($"{pc.GetNameWithRole().RemoveHtmlTags()} canceled swapping on {target.GetNameWithRole()} (first target)", "Swapper");
|
||||
}
|
||||
|
||||
else if (target.PlayerId == SwapTargets.Item2) // If this player is already chosen to be swapped in the second slot, cancel it
|
||||
{
|
||||
SwapTargets.Item2 = byte.MaxValue;
|
||||
|
||||
if (HideMsg.GetBool() && !isUI) ChatManager.SendPreviousMessagesToAll();
|
||||
if (!isUI) Utils.SendMessage(GetString("CancelSwap2"), pc.PlayerId);
|
||||
Logger.Info($"{pc.GetNameWithRole().RemoveHtmlTags()} canceled swapping on {target.GetNameWithRole()} (second target)", "Swapper");
|
||||
}
|
||||
|
||||
else if (pc.PlayerId == target.PlayerId && !CanSwapSelf.GetBool()) // When the Swapper tries to swap themselves but they aren't allowed to
|
||||
{
|
||||
if (HideMsg.GetBool() && !isUI) ChatManager.SendPreviousMessagesToAll();
|
||||
if (!isUI) Utils.SendMessage(GetString("CantSwapSelf"), pc.PlayerId);
|
||||
else pc.ShowPopUp(GetString("CantSwapSelf"));
|
||||
}
|
||||
|
||||
_ = new LateTask(() => Utils.NotifyRoles(isForMeeting: true, NoCache: true), 0.2f);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void OnExileFinish()
|
||||
{
|
||||
if (SwapTargets != (byte.MaxValue, byte.MaxValue))
|
||||
{
|
||||
UseLimit--;
|
||||
SwapTargets = (byte.MaxValue, byte.MaxValue);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<MeetingHud.VoterState> OnCheckForEndVoting(List<MeetingHud.VoterState> votes)
|
||||
{
|
||||
if (!(SwapTargets != (byte.MaxValue, byte.MaxValue))) return votes;
|
||||
|
||||
var playerStates = MeetingHud.Instance.playerStates;
|
||||
var votedFor2 = playerStates.Where(x => x.VotedFor == SwapTargets.Item2).ToList();
|
||||
|
||||
playerStates.DoIf(x => x.VotedFor == SwapTargets.Item1, x =>
|
||||
{
|
||||
x.UnsetVote();
|
||||
if (x.TargetPlayerId == 0) MeetingHud.Instance.CmdCastVote(x.TargetPlayerId, SwapTargets.Item2);
|
||||
else MeetingHud.Instance.CastVote(x.TargetPlayerId, SwapTargets.Item2);
|
||||
x.VotedFor = SwapTargets.Item2;
|
||||
});
|
||||
playerStates.DoIf(votedFor2.Contains, x =>
|
||||
{
|
||||
x.UnsetVote();
|
||||
if (x.TargetPlayerId == 0) MeetingHud.Instance.CmdCastVote(x.TargetPlayerId, SwapTargets.Item1);
|
||||
else MeetingHud.Instance.CastVote(x.TargetPlayerId, SwapTargets.Item1);
|
||||
x.VotedFor = SwapTargets.Item1;
|
||||
});
|
||||
|
||||
PlayerControl Target1 = Utils.GetPlayerById(SwapTargets.Item1);
|
||||
PlayerControl Target2 = Utils.GetPlayerById(SwapTargets.Item2);
|
||||
if (Target1 == null || Target2 == null) return votes;
|
||||
|
||||
Utils.SendMessage(string.Format(GetString("SwapVote"), Target1.GetRealName(), Target2.GetRealName()), 255, Utils.ColorString(Utils.GetRoleColor(CustomRoles.NiceSwapper), GetString("SwapTitle")));
|
||||
|
||||
return votes;
|
||||
}
|
||||
|
||||
private static bool MsgToPlayerAndRole(string msg, out byte id, out string error)
|
||||
{
|
||||
if (msg.StartsWith("/")) msg = msg.Replace("/", string.Empty);
|
||||
@@ -188,7 +208,7 @@ public static class NiceSwapper
|
||||
string result = string.Empty;
|
||||
for (int i = 0; i < mc.Count; i++)
|
||||
{
|
||||
result += mc[i];//匹配结果是完整的数字,此处可以不做拼接的
|
||||
result += mc[i];
|
||||
}
|
||||
|
||||
if (int.TryParse(result, out int num))
|
||||
@@ -197,15 +217,11 @@ public static class NiceSwapper
|
||||
}
|
||||
else
|
||||
{
|
||||
//并不是玩家编号,判断是否颜色
|
||||
//byte color = GetColorFromMsg(msg);
|
||||
//好吧我不知道怎么取某位玩家的颜色,等会了的时候再来把这里补上
|
||||
id = byte.MaxValue;
|
||||
error = GetString("SwapHelp");
|
||||
return false;
|
||||
}
|
||||
|
||||
//判断选择的玩家是否合理
|
||||
PlayerControl target = Utils.GetPlayerById(id);
|
||||
if (target == null || target.Data.IsDead)
|
||||
{
|
||||
@@ -216,7 +232,8 @@ public static class NiceSwapper
|
||||
error = string.Empty;
|
||||
return true;
|
||||
}
|
||||
public static bool CheckCommond(ref string msg, string command, bool exact = true)
|
||||
|
||||
public static bool CheckCommand(ref string msg, string command, bool exact = true)
|
||||
{
|
||||
var comList = command.Split('|');
|
||||
foreach (string str in comList)
|
||||
@@ -236,6 +253,7 @@ public static class NiceSwapper
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void SendRPC(byte playerId)
|
||||
{
|
||||
if (!IsEnable || !Utils.DoRPC) return;
|
||||
@@ -243,22 +261,25 @@ public static class NiceSwapper
|
||||
writer.Write(playerId);
|
||||
AmongUsClient.Instance.FinishRpcImmediately(writer);
|
||||
}
|
||||
|
||||
public static void ReceiveRPC(MessageReader reader, PlayerControl pc)
|
||||
{
|
||||
byte PlayerId = reader.ReadByte();
|
||||
SwapMsg(pc, $"/sw {PlayerId}");
|
||||
//if (HideMsg.GetBool()) GuessManager.TryHideMsg();
|
||||
}
|
||||
|
||||
private static void SwapperOnClick(byte playerId, MeetingHud __instance)
|
||||
{
|
||||
Logger.Msg($"Click: ID {playerId}", "NiceSwapper UI");
|
||||
|
||||
var pc = Utils.GetPlayerById(playerId);
|
||||
if (pc == null || !pc.IsAlive() || !GameStates.IsVoting) return;
|
||||
|
||||
if (AmongUsClient.Instance.AmHost) SwapMsg(PlayerControl.LocalPlayer, $"/sw {playerId}", true);
|
||||
else SendRPC(playerId);
|
||||
|
||||
if (PlayerControl.LocalPlayer.GetCustomRole() == CustomRoles.NiceSwapper && PlayerControl.LocalPlayer.IsAlive())
|
||||
{
|
||||
//MeetingHudUpdatePatch.ClearShootButton(__instance, true);
|
||||
bool forceAll = true;
|
||||
__instance.playerStates.ToList().ForEach(x => { if ((forceAll || !Main.PlayerStates.TryGetValue(x.TargetPlayerId, out var ps) || ps.IsDead) && x.transform.FindChild("ShootButton") != null) UnityEngine.Object.Destroy(x.transform.FindChild("ShootButton").gameObject); });
|
||||
CreateSwapperButton(__instance);
|
||||
@@ -274,19 +295,23 @@ public static class NiceSwapper
|
||||
CreateSwapperButton(__instance);
|
||||
}
|
||||
}
|
||||
|
||||
public static void CreateSwapperButton(MeetingHud __instance)
|
||||
{
|
||||
foreach (PlayerVoteArea pva in __instance.playerStates.ToArray())
|
||||
{
|
||||
var pc = Utils.GetPlayerById(pva.TargetPlayerId);
|
||||
if (pc == null || !pc.IsAlive()) continue;
|
||||
|
||||
GameObject template = pva.Buttons.transform.Find("CancelButton").gameObject;
|
||||
GameObject targetBox = UnityEngine.Object.Instantiate(template, pva.transform);
|
||||
targetBox.name = "ShootButton";
|
||||
targetBox.transform.localPosition = new Vector3(-0.35f, 0.03f, -1.31f);
|
||||
SpriteRenderer renderer = targetBox.GetComponent<SpriteRenderer>();
|
||||
if ((pc.PlayerId == pva.TargetPlayerId) && (Vote.Contains(pc.PlayerId) || VoteTwo.Contains(pc.PlayerId))) renderer.sprite = CustomButton.Get("SwapYes");
|
||||
|
||||
if ((pc.PlayerId == pva.TargetPlayerId) && (SwapTargets.Item1 == pc.PlayerId || SwapTargets.Item2 == pc.PlayerId)) renderer.sprite = CustomButton.Get("SwapYes");
|
||||
else renderer.sprite = CustomButton.Get("SwapNo");
|
||||
|
||||
PassiveButton button = targetBox.GetComponent<PassiveButton>();
|
||||
button.OnClick.RemoveAllListeners();
|
||||
button.OnClick.AddListener((Action)(() => SwapperOnClick(pva.TargetPlayerId, __instance)));
|
||||
|
||||
@@ -15,6 +15,7 @@ public static class Oracle
|
||||
public static OptionItem HideVote;
|
||||
public static OptionItem FailChance;
|
||||
public static OptionItem OracleAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
public static List<byte> didVote = [];
|
||||
@@ -34,6 +35,9 @@ 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);
|
||||
AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(Id + 15, "AbilityChargesWhenFinishedTasks", 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()
|
||||
|
||||
@@ -29,6 +29,7 @@ public static class ParityCop
|
||||
public static OptionItem ParityCheckBaitCountType;
|
||||
public static OptionItem ParityCheckRevealTargetTeam;
|
||||
public static OptionItem ParityAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
@@ -47,6 +48,9 @@ public static class ParityCop
|
||||
ParityAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 18, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 1.5f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.ParityCop])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(Id + 19, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.ParityCop])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
OverrideTasksData.Create(Id + 20, TabGroup.CrewmateRoles, CustomRoles.ParityCop);
|
||||
}
|
||||
public static int ParityCheckEgoistInt()
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace TOHE.Roles.Crewmate
|
||||
public static OptionItem CD;
|
||||
public static OptionItem Limit;
|
||||
public static OptionItem PerceiverAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
public static readonly Dictionary<byte, float> UseLimit = [];
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
@@ -25,6 +26,9 @@ namespace TOHE.Roles.Crewmate
|
||||
PerceiverAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 5, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.4f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Perceiver])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(Id + 6, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Perceiver])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
}
|
||||
public static void Init() => UseLimit.Clear();
|
||||
public static void Add(byte id) => UseLimit[id] = Limit.GetInt();
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace TOHE.Roles.Crewmate
|
||||
|
||||
public static OptionItem UseLimitOpt;
|
||||
public static OptionItem RicochetAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
@@ -27,6 +28,9 @@ namespace TOHE.Roles.Crewmate
|
||||
RicochetAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 11, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.5f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Ricochet])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(Id + 13, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Ricochet])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
CancelVote = CreateVoteCancellingUseSetting(Id + 12, CustomRoles.Ricochet, TabGroup.CrewmateRoles);
|
||||
}
|
||||
public static void Init()
|
||||
|
||||
@@ -15,6 +15,7 @@ public static class SabotageMaster
|
||||
public static OptionItem FixesComms;
|
||||
public static OptionItem FixesElectrical;
|
||||
public static OptionItem SMAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
public static OptionItem UsesUsedWhenFixingReactorOrO2;
|
||||
public static OptionItem UsesUsedWhenFixingLightsOrComms;
|
||||
public static float UsedSkillCount;
|
||||
@@ -34,6 +35,9 @@ public static class SabotageMaster
|
||||
SMAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 16, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 3f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.SabotageMaster])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(Id + 19, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.SabotageMaster])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
UsesUsedWhenFixingReactorOrO2 = FloatOptionItem.Create(Id + 17, "SMUsesUsedWhenFixingReactorOrO2", new(0f, 5f, 0.1f), 4f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.SabotageMaster])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
|
||||
@@ -136,6 +136,7 @@ public static class Sheriff
|
||||
killer.Is(CustomRoles.Madmate)
|
||||
|| killer.Is(CustomRoles.Charmed)
|
||||
|| killer.Is(CustomRoles.Contagious)
|
||||
|| killer.Is(CustomRoles.Undead)
|
||||
)
|
||||
&& ((target.GetCustomRole().IsImpostor() && NonCrewCanKillImp.GetBool()) || (target.GetCustomRole().IsCrewmate() && NonCrewCanKillCrew.GetBool()) || (target.GetCustomRole().IsNeutral() && NonCrewCanKillNeutral.GetBool()))
|
||||
))
|
||||
|
||||
+11
-5
@@ -19,17 +19,23 @@ namespace TOHE.Roles.Crewmate
|
||||
public static OptionItem SpyRedNameDur;
|
||||
public static OptionItem UseLimitOpt;
|
||||
public static OptionItem SpyAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
SetupSingleRoleOptions(Id, TabGroup.CrewmateRoles, CustomRoles.Spy, 1);
|
||||
UseLimitOpt = IntegerOptionItem.Create(Id + 10, "AbilityUseLimit", new(0, 20, 1), 1, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Spy])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
SpyRedNameDur = FloatOptionItem.Create(Id + 11, "SpyRedNameDur", new(0f, 70f, 1f), 3f, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Spy])
|
||||
UseLimitOpt = IntegerOptionItem.Create(Id + 10, "AbilityUseLimit", new(0, 20, 1), 1, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Spy])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
SpyRedNameDur = FloatOptionItem.Create(Id + 11, "SpyRedNameDur", new(0f, 70f, 1f), 3f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Spy])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
SpyAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 12, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.5f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Spy])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Spy])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(Id + 13, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Spy])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace TOHE.Roles.Crewmate
|
||||
public static OptionItem VentCooldown;
|
||||
public static OptionItem UseLimitOpt;
|
||||
public static OptionItem TetherAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
@@ -30,6 +31,9 @@ namespace TOHE.Roles.Crewmate
|
||||
TetherAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 12, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.4f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Tether])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(Id + 14, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Tether])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
CancelVote = CreateVoteCancellingUseSetting(Id + 13, CustomRoles.Tether, TabGroup.CrewmateRoles);
|
||||
}
|
||||
public static void Init()
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace TOHE.Roles.Crewmate
|
||||
MapNames.Skeld => new RandomSpawn.SkeldSpawnMap(),
|
||||
MapNames.Mira => new RandomSpawn.MiraHQSpawnMap(),
|
||||
MapNames.Polus => new RandomSpawn.PolusSpawnMap(),
|
||||
MapNames.Dleks => new RandomSpawn.DleksSpawnMap(),
|
||||
MapNames.Airship => new RandomSpawn.AirshipSpawnMap(),
|
||||
MapNames.Fungle => new RandomSpawn.FungleSpawnMap(),
|
||||
_ => throw new NotImplementedException(),
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace TOHE.Roles.Crewmate
|
||||
private static OptionItem CanGetColoredArrow;
|
||||
public static OptionItem HideVote;
|
||||
public static OptionItem TrackerAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
public static bool CanSeeLastRoomInMeeting;
|
||||
@@ -38,6 +39,9 @@ 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);
|
||||
AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(Id + 3, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Tracker])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
CancelVote = CreateVoteCancellingUseSetting(Id + 4, CustomRoles.Tracker, TabGroup.CrewmateRoles);
|
||||
}
|
||||
public static void Init()
|
||||
|
||||
@@ -77,6 +77,12 @@ internal class AntiAdminer
|
||||
if (!Options.DisablePolusVital.GetBool())
|
||||
Vital |= Vector2.Distance(PlayerPos, DisableDevice.DevicePos["PolusVital"]) <= DisableDevice.UsableDistance();
|
||||
break;
|
||||
case 3:
|
||||
if (!Options.DisableSkeldAdmin.GetBool())
|
||||
Admin |= Vector2.Distance(PlayerPos, DisableDevice.DevicePos["DleksAdmin"]) <= DisableDevice.UsableDistance();
|
||||
if (!Options.DisableSkeldCamera.GetBool())
|
||||
Camera |= Vector2.Distance(PlayerPos, DisableDevice.DevicePos["DleksCamera"]) <= DisableDevice.UsableDistance();
|
||||
break;
|
||||
case 4:
|
||||
if (!Options.DisableAirshipCockpitAdmin.GetBool())
|
||||
Admin |= Vector2.Distance(PlayerPos, DisableDevice.DevicePos["AirshipCockpitAdmin"]) <= DisableDevice.UsableDistance();
|
||||
@@ -121,7 +127,7 @@ internal class AntiAdminer
|
||||
{
|
||||
PlayerControl pc = Utils.GetPlayerById(id);
|
||||
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
||||
FixedUpdatePatch.Postfix(pc);
|
||||
FixedUpdatePatch.DoPostfix(pc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace TOHE.Roles.Impostor
|
||||
}
|
||||
break;
|
||||
case CustomRoles.NiceSwapper:
|
||||
NiceSwapper.NiceSwappermax[target.PlayerId]--;
|
||||
NiceSwapper.UseLimit--;
|
||||
break;
|
||||
case CustomRoles.Oracle:
|
||||
Oracle.CheckLimit[target.PlayerId]--;
|
||||
|
||||
@@ -128,6 +128,6 @@ namespace TOHE.Roles.Impostor
|
||||
pc2.Suicide(PlayerState.DeathReason.YinYanged, yy);
|
||||
}
|
||||
}
|
||||
public static string ModeText => YinYangedPlayers.Count == 2 ? $"<color=#00ffa5>{Translator.GetString("Mode")}:</color> {Translator.GetString("YinYangModeNormal")}" : $"<color=#00ffa5>{Translator.GetString("Mode")}:</color> {Translator.GetString("YinYangMode")} ({YinYangedPlayers.Count}/2)";
|
||||
public static string ModeText => YinYangedPlayers.Count == 2 ? $"<color=#00ffa5>{Translator.GetString("Mode")}:</color> {Translator.GetString("YinYangModeNormal")}" : $"<color=#00ffa5>{Translator.GetString("Mode")}:</color> {Translator.GetString("YinYangMode")} ({YinYangedPlayers.Count}/2)";
|
||||
}
|
||||
}
|
||||
@@ -196,7 +196,7 @@ public static class Amnesiac
|
||||
}
|
||||
}
|
||||
killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Amnesiac), GetString("AmnesiacInvalidTarget")));
|
||||
|
||||
|
||||
if (CanBeRememberedImpostor(target))
|
||||
{
|
||||
RememberLimit--;
|
||||
@@ -218,7 +218,7 @@ public static class Amnesiac
|
||||
return;
|
||||
}
|
||||
killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Amnesiac), GetString("AmnesiacInvalidTarget")));
|
||||
|
||||
|
||||
if (CanBeRememberedCrewmate(target))
|
||||
{
|
||||
RememberLimit--;
|
||||
@@ -242,7 +242,7 @@ public static class Amnesiac
|
||||
return;
|
||||
}
|
||||
killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Amnesiac), GetString("AmnesiacInvalidTarget")));
|
||||
|
||||
|
||||
if (CanBeRememberedPoisoner(target))
|
||||
{
|
||||
RememberLimit--;
|
||||
@@ -266,7 +266,7 @@ public static class Amnesiac
|
||||
return;
|
||||
}
|
||||
killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Amnesiac), GetString("AmnesiacInvalidTarget")));
|
||||
|
||||
|
||||
if (CanBeRememberedJuggernaut(target))
|
||||
{
|
||||
RememberLimit--;
|
||||
@@ -290,7 +290,7 @@ public static class Amnesiac
|
||||
return;
|
||||
}
|
||||
killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Amnesiac), GetString("AmnesiacInvalidTarget")));
|
||||
|
||||
|
||||
if (CanBeRememberedHexMaster(target))
|
||||
{
|
||||
RememberLimit--;
|
||||
@@ -314,7 +314,7 @@ public static class Amnesiac
|
||||
return;
|
||||
}
|
||||
killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Amnesiac), GetString("AmnesiacInvalidTarget")));
|
||||
|
||||
|
||||
if (CanBeRememberedBloodKnight(target))
|
||||
{
|
||||
RememberLimit--;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using AmongUs.GameOptions;
|
||||
using Hazel;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static TOHE.Options;
|
||||
@@ -56,6 +57,19 @@ public static class HeadHunter
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
private static void SendRPC()
|
||||
{
|
||||
var writer = Utils.CreateCustomRoleRPC(CustomRPC.SyncHeadHunter);
|
||||
writer.Write(Targets.Count);
|
||||
foreach (var target in Targets.ToArray()) writer.Write(target);
|
||||
Utils.EndRPC(writer);
|
||||
}
|
||||
public static void ReceiveRPC(MessageReader reader)
|
||||
{
|
||||
Targets.Clear();
|
||||
int count = reader.ReadInt32();
|
||||
for (int i = 0; i < count; i++) Targets.Add(reader.ReadByte());
|
||||
}
|
||||
public static bool IsEnable => playerIdList.Count > 0;
|
||||
public static void ApplyGameOptions(IGameOptions opt) => opt.SetVision(HasImpostorVision.GetBool());
|
||||
public static void OnReportDeadBody()
|
||||
@@ -100,6 +114,7 @@ public static class HeadHunter
|
||||
}
|
||||
}
|
||||
|
||||
SendRPC();
|
||||
Utils.NotifyRoles(SpecifySeer: Utils.GetPlayerById(playerIdList[0]));
|
||||
}
|
||||
}
|
||||
@@ -107,6 +107,17 @@ namespace TOHE.Roles.Neutral
|
||||
killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Necromancer), GetString("InvalidUndeadTarget")));
|
||||
}
|
||||
|
||||
public static void OnFixedUpdate()
|
||||
{
|
||||
if (!GameStates.IsInTask || !IsEnable || Necromancer_.IsAlive() || !Deathknight.Deathknight_.IsAlive()) return;
|
||||
|
||||
Deathknight.Deathknight_.RpcSetCustomRole(CustomRoles.Necromancer);
|
||||
Add(Deathknight.DeathknightId);
|
||||
|
||||
Deathknight.Deathknight_ = null;
|
||||
Deathknight.DeathknightId = byte.MaxValue;
|
||||
}
|
||||
|
||||
public static bool KnowRole(PlayerControl player, PlayerControl target)
|
||||
{
|
||||
if (player.Is(CustomRoles.Undead) && (target.Is(CustomRoles.Necromancer) || target.Is(CustomRoles.Deathknight))) return true;
|
||||
|
||||
@@ -33,7 +33,7 @@ public static class Pelican
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
public static bool IsEnable => playerIdList.Count > 0;
|
||||
private static void SyncEatenList(byte playerId)
|
||||
private static void SyncEatenList(/*byte playerId*/)
|
||||
{
|
||||
SendRPC(byte.MaxValue);
|
||||
foreach (var el in eatenList)
|
||||
@@ -92,6 +92,7 @@ public static class Pelican
|
||||
0 => new(-27f, 3.3f), // The Skeld
|
||||
1 => new(-11.4f, 8.2f), // MIRA HQ
|
||||
2 => new(42.6f, -19.9f), // Polus
|
||||
3 => new Vector2(27f, 3.3f), // dlekS ehT
|
||||
4 => new(-16.8f, -6.2f), // Airship
|
||||
5 => new Vector2(9.6f, 23.2f), // The Fungle
|
||||
_ => throw new System.NotImplementedException(),
|
||||
@@ -112,7 +113,7 @@ public static class Pelican
|
||||
if (!eatenList.ContainsKey(pc.PlayerId)) eatenList.Add(pc.PlayerId, []);
|
||||
eatenList[pc.PlayerId].Add(target.PlayerId);
|
||||
|
||||
SyncEatenList(pc.PlayerId);
|
||||
SyncEatenList(/*pc.PlayerId*/);
|
||||
|
||||
originalSpeed.Remove(target.PlayerId);
|
||||
originalSpeed.Add(target.PlayerId, Main.AllPlayerSpeed[target.PlayerId]);
|
||||
@@ -147,7 +148,7 @@ public static class Pelican
|
||||
}
|
||||
}
|
||||
eatenList.Clear();
|
||||
SyncEatenList(byte.MaxValue);
|
||||
SyncEatenList(/*byte.MaxValue*/);
|
||||
}
|
||||
|
||||
public static void OnPelicanDied(byte pc)
|
||||
@@ -168,7 +169,7 @@ public static class Pelican
|
||||
Logger.Info($"{Utils.GetPlayerById(pc).GetRealName()} 吐出了 {target.GetRealName()}", "Pelican");
|
||||
}
|
||||
eatenList.Remove(pc);
|
||||
SyncEatenList(pc);
|
||||
SyncEatenList(/*pc*/);
|
||||
}
|
||||
|
||||
private static int Count;
|
||||
@@ -179,7 +180,7 @@ public static class Pelican
|
||||
if (eatenList.Count > 0)
|
||||
{
|
||||
eatenList.Clear();
|
||||
SyncEatenList(byte.MaxValue);
|
||||
SyncEatenList(/*byte.MaxValue*/);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -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.3.0";
|
||||
public const string PluginDisplayVersion = "2.3.0";
|
||||
public const string PluginVersion = "2.3.1";
|
||||
public const string PluginDisplayVersion = "2.3.1";
|
||||
public static readonly string SupportedAUVersion = "2023.10.24";
|
||||
public const int PluginCreate = 3;
|
||||
public const bool Canary = false;
|
||||
@@ -80,6 +80,7 @@ public class Main : BasePlugin
|
||||
public static ConfigEntry<string> BetaBuildURL { get; private set; }
|
||||
public static ConfigEntry<float> LastKillCooldown { get; private set; }
|
||||
public static ConfigEntry<float> LastShapeshifterCooldown { get; private set; }
|
||||
public static bool ChangedRole = false;
|
||||
public static OptionBackupData RealOptionsData;
|
||||
public static Dictionary<byte, float> KillTimers = [];
|
||||
public static Dictionary<byte, PlayerState> PlayerStates = [];
|
||||
@@ -194,7 +195,6 @@ public class Main : BasePlugin
|
||||
public static Dictionary<byte, string> SleuthMsgs = [];
|
||||
public static int AliveImpostorCount;
|
||||
public static bool isCursed;
|
||||
public static bool NiceSwapSend;
|
||||
public static List<byte> InsightKnownRolesOfPlayerIds = [];
|
||||
public static Dictionary<byte, bool> CheckShapeshift = [];
|
||||
public static Dictionary<byte, byte> ShapeshiftTarget = [];
|
||||
|
||||
Reference in new issue
Block a user