Compare commits

...
17 Commits
Author SHA1 Message Date
Gurge44 3817250793 Merge branch 'main' of https://github.com/Gurge44/TOHE_PLUS 2024-02-07 21:21:47 +01:00
Gurge44 3fdeaf6ef7 GitHub is dumb again 2024-02-07 21:21:43 +01:00
Gurge44 214783bbb5 New Crowdin updates (#32)
* New translations en_us.json (Portuguese, Brazilian)

* New translations en_us.json (Portuguese, Brazilian)

* New translations en_us.json (Portuguese, Brazilian)

* New translations en_us.json (Portuguese, Brazilian)

* New translations en_us.json (Portuguese, Brazilian)

* New translations en_us.json (Portuguese, Brazilian)
2024-02-07 21:01:15 +01:00
Gurge44 ebb7367e61 Fix & Recode Swapper, Add missing strings, Add Swapper to CopyCat blacklist 2024-02-07 20:33:55 +01:00
Gurge44 c7434e5f06 ignore spaces 2024-02-06 22:07:44 +01:00
Gurge44 3ec05fef35 pet support indicator 2024-02-06 22:02:57 +01:00
Gurge44 2dc400be01 Ability use gain every 5s, /changerole, votekick disable setting, add head hunter RPC, bug fixes 2024-02-06 22:01:47 +01:00
Gurge44 2ffab98391 Merge branch 'main' of https://github.com/Gurge44/TOHE_PLUS 2024-02-06 17:58:03 +01:00
Gurge44 e448341581 Sync 2024-02-06 17:57:56 +01:00
Gurge44 302b15d5d9 Add dev user 2024-02-05 19:35:17 +01:00
Gurge44 071b9256fd Fixes for dlekS 2024-02-05 19:28:16 +01:00
Gurge44 a85f9f5906 VS, are you okay? 2024-02-05 18:59:51 +01:00
Gurge44 a656c4ea7f Add support for dlekS ehT & Fix a few bugs 2024-02-05 18:55:02 +01:00
Dxgamer7405andDxgamer7405 75560254ec add tpout and tpin from tohe (#31)
* Added new strings (and my tag)

* fix and done

* reverted

* ok

* new translation strings

* revert

* fixed

* /tpout and /tpin from tohe

---------

Co-authored-by: Dxgamer7405 <ponteseduardo@gmail.com>
2024-01-29 21:11:22 +01:00
Gurge44 f61226f65c Fix name colors not working, Fix Cantankerous, Fix Deathknight not turning into Necromancer 2024-01-29 19:36:26 +01:00
Gurge44 f83b8f66d4 Update README.md 2024-01-29 17:35:34 +01:00
Gurge44 918deb5d5b Readme update 2024-01-29 17:34:14 +01:00
63 changed files with 857 additions and 489 deletions

No files matched your search

+8
View File
@@ -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()
{
+1 -1
View File
@@ -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:
+4 -1
View File
@@ -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));
+10 -1
View File
@@ -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;
+3 -2
View File
@@ -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
+1 -1
View File
@@ -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();
+2 -2
View File
@@ -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
View File
@@ -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);
+4
View File
@@ -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
View File
@@ -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)
+38 -8
View File
@@ -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)
{
+120
View File
@@ -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
View File
@@ -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,
};
+15 -2
View File
@@ -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();
+2
View File
@@ -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);
+15
View File
@@ -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
View File
@@ -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))]
+1 -1
View File
@@ -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,
};
+19 -41
View File
@@ -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;
}
}
}
+3 -62
View File
@@ -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))
+2
View File
@@ -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
View File
@@ -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;
}
+8
View File
@@ -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()
+1 -1
View File
@@ -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,
+4 -3
View File
@@ -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
View File
@@ -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))]
+21
View File
@@ -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();
}
}
}
+1 -5
View File
@@ -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)
+21 -3
View File
@@ -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) :
+8 -1
View File
@@ -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.",
+13 -6
View File
@@ -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
View File
@@ -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();
+4
View File
@@ -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()
{
+11 -6
View File
@@ -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(),
};
+6 -2
View File
@@ -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()
{
+4
View File
@@ -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();
+1 -3
View File
@@ -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
+4
View File
@@ -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);
}
+4
View File
@@ -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()
{
+4
View File
@@ -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()
+4
View File
@@ -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()
+2
View File
@@ -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()
{
+4
View File
@@ -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()
{
+7 -1
View File
@@ -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
View File
@@ -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)));
+4
View File
@@ -15,6 +15,7 @@ public static class Oracle
public static OptionItem HideVote;
public static OptionItem FailChance;
public static OptionItem OracleAbilityUseGainWithEachTaskCompleted;
public static OptionItem 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()
+4
View File
@@ -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()
+4
View File
@@ -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();
+4
View File
@@ -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()
+4
View File
@@ -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);
+1
View File
@@ -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
View File
@@ -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()
{
+4
View File
@@ -18,6 +18,7 @@ namespace TOHE.Roles.Crewmate
public static OptionItem VentCooldown;
public static OptionItem UseLimitOpt;
public static OptionItem TetherAbilityUseGainWithEachTaskCompleted;
public static OptionItem 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()
+1
View File
@@ -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(),
+4
View File
@@ -17,6 +17,7 @@ namespace TOHE.Roles.Crewmate
private static OptionItem CanGetColoredArrow;
public static OptionItem HideVote;
public static OptionItem TrackerAbilityUseGainWithEachTaskCompleted;
public static OptionItem 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()
+7 -1
View File
@@ -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);
}
}
}
+1 -1
View File
@@ -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]--;
+1 -1
View File
@@ -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)";
}
}
+6 -6
View File
@@ -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--;
+15
View File
@@ -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]));
}
}
+11
View File
@@ -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;
+6 -5
View File
@@ -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;
}
+3 -3
View File
@@ -33,8 +33,8 @@ public class Main : BasePlugin
public static ConfigEntry<string> DebugKeyInput { get; private set; }
public static readonly string MainMenuText = " ";
public const string PluginGuid = "com.gurge44.toheplus";
public const string PluginVersion = "2.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 = [];