mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-19 15:51:58 +00:00
Android & Submerged compatibility
This commit is contained in:
1 parent
eb0cc841e9
commit
470acb6239
57 files changed
+696
-116
No files matched your search
@@ -235,7 +235,7 @@ public static class CaptureTheFlag
|
||||
|
||||
if (!ValidTag) return false;
|
||||
|
||||
switch (aapc.Length)
|
||||
switch (aapc.Length + ExtendedPlayerControl.TempExiled.Count)
|
||||
{
|
||||
case 0:
|
||||
ResetSkins();
|
||||
|
||||
@@ -236,6 +236,7 @@ public static class KingOfTheZones
|
||||
AllRooms.Remove(SystemTypes.Outside);
|
||||
AllRooms.Remove(SystemTypes.Ventilation);
|
||||
AllRooms.RemoveWhere(x => x.ToString().Contains("Decontamination"));
|
||||
if (SubmergedCompatibility.IsSubmerged()) AllRooms.RemoveWhere(x => (byte)x > 135);
|
||||
|
||||
Zones = DefaultZones[Main.CurrentMap][NumZones.GetInt() - 1];
|
||||
|
||||
@@ -582,7 +583,7 @@ public static class KingOfTheZones
|
||||
|
||||
if (!Main.IntroDestroyed) return false;
|
||||
|
||||
switch (aapc.Length)
|
||||
switch (aapc.Length + ExtendedPlayerControl.TempExiled.Count)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
|
||||
+18
-16
@@ -2,7 +2,6 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AmongUs.GameOptions;
|
||||
using EHR.Modules;
|
||||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
@@ -162,6 +161,8 @@ public static class Quiz
|
||||
|
||||
if (FFAEndTS == 0)
|
||||
{
|
||||
int numPlayers = Main.AllAlivePlayerControls.Length;
|
||||
|
||||
if (QuestionTimeLimitEndTS != 0)
|
||||
{
|
||||
string answers = string.Empty;
|
||||
@@ -190,7 +191,8 @@ public static class Quiz
|
||||
if (index != -1) question = question.Insert(index + 1, "\n");
|
||||
}
|
||||
|
||||
return $"<#ffff44>{question}</color>\n{answers}<#CF2472>{QuestionTimeLimitEndTS - Utils.TimeStamp}</color>";
|
||||
string invis = numPlayers <= 3 && CurrentDifficulty > Difficulty.Test ? $"\n<#888888>{GetString("Quiz.Suffix.Invisible")}</color>" : string.Empty;
|
||||
return $"<#ffff44>{question}</color>\n{answers}<#CF2472>{QuestionTimeLimitEndTS - Utils.TimeStamp}</color>{invis}";
|
||||
}
|
||||
|
||||
string correctAnswer = CurrentQuestion.Answers[CurrentQuestion.CorrectAnswerIndex];
|
||||
@@ -199,7 +201,6 @@ public static class Quiz
|
||||
string color = DyingPlayers.Contains(seer.PlayerId) ? "#FF0000" : "#00FF00";
|
||||
string str = string.Format(GetString("Quiz.Notify.CorrectAnswer"), color, correctAnswerLetter, correctAnswer, correctRoom);
|
||||
|
||||
int numPlayers = Main.AllAlivePlayerControls.Length;
|
||||
if (DyingPlayers.Count == numPlayers) str += "\n" + GetString(numPlayers <= 3 ? "Quiz.Notify.AllWrongShort" : "Quiz.Notify.AllWrong");
|
||||
|
||||
if (CurrentDifficulty > Difficulty.Test && Settings[CurrentDifficulty].QuestionsAsked.GetInt() <= QuestionsAsked)
|
||||
@@ -348,6 +349,11 @@ public static class Quiz
|
||||
if (Main.CurrentMap is MapNames.Skeld or MapNames.Dleks) time -= 3;
|
||||
QuestionTimeLimitEndTS = Utils.TimeStamp + time;
|
||||
|
||||
PlayerControl[] aapc = Main.AllAlivePlayerControls;
|
||||
|
||||
if (aapc.Length is 3 or 2 && CurrentDifficulty > Difficulty.Test)
|
||||
aapc.Do(x => x.RpcMakeInvisible());
|
||||
|
||||
Logger.Info($"New question: {CurrentQuestion.Question} | {string.Join(", ", CurrentQuestion.Answers)} | {CurrentQuestion.Answers[CurrentQuestion.CorrectAnswerIndex]}", "Quiz");
|
||||
Logger.Info($"Time limit: {time}", "Quiz");
|
||||
}
|
||||
@@ -439,7 +445,7 @@ public static class Quiz
|
||||
Logger.Info($"Number of correct answers for everyone currently: {string.Join(", ", NumCorrectAnswers.Select(x => $"{Main.AllPlayerNames.GetValueOrDefault(x.Key, string.Empty)}: {x.Value[CurrentDifficulty][Round]}"))}", "Quiz");
|
||||
|
||||
if (everyoneWasWrong) QuestionsAsked--;
|
||||
else Utils.NotifyRoles();
|
||||
Utils.NotifyRoles();
|
||||
|
||||
yield return new WaitForSeconds(everyoneWasWrong ? aapc.Length <= 3 ? 4f : 6f : 3f);
|
||||
if (GameStates.IsMeeting || ExileController.Instance || !GameStates.InGame || GameStates.IsLobby) yield break;
|
||||
@@ -468,27 +474,22 @@ public static class Quiz
|
||||
yield break;
|
||||
case 1:
|
||||
var pc = dyingPlayers[0].GetPlayer();
|
||||
if (pc != null) pc.Suicide();
|
||||
if (pc == null) goto case 0;
|
||||
pc.RpcMakeVisible();
|
||||
pc.Suicide();
|
||||
goto case 0;
|
||||
case var x when x == aapc.Length:
|
||||
Round--;
|
||||
NumCorrectAnswers.Values.Do(d => d[CurrentDifficulty][Round] = 0);
|
||||
goto case 0;
|
||||
default:
|
||||
if (aapc.Length is 3 or 2) aapc.Do(x => x.RpcMakeVisible());
|
||||
yield return new WaitForSeconds(2f);
|
||||
AllowKills = true;
|
||||
FFAEndTS = Utils.TimeStamp + FFAEventLength.GetInt();
|
||||
var spectators = aapc.ExceptBy(dyingPlayers, x => x.PlayerId).ToArray();
|
||||
|
||||
foreach (PlayerControl spectator in spectators)
|
||||
{
|
||||
spectator.RpcExileV2();
|
||||
spectator.RpcSetRoleDesync(RoleTypes.GuardianAngel, spectator.OwnerId);
|
||||
}
|
||||
|
||||
spectators.Do(x => x.ExileTemporarily());
|
||||
yield return new WaitForSeconds(0.2f);
|
||||
spectators.Do(x => x.RpcResetAbilityCooldown());
|
||||
Main.PlayerStates.Values.IntersectBy(spectators.Select(x => x.PlayerId), x => x.Player.PlayerId).Do(x => x.SetDead());
|
||||
var stillLiving = dyingPlayers.ToValidPlayers().FindAll(x => x.IsAlive());
|
||||
stillLiving.ForEach(x => x.RpcChangeRoleBasis(CustomRoles.NSerialKiller));
|
||||
Utils.SendRPC(CustomRPC.QuizSync, AllowKills);
|
||||
@@ -507,13 +508,13 @@ public static class Quiz
|
||||
Utils.SendRPC(CustomRPC.QuizSync, AllowKills);
|
||||
|
||||
var location = RandomSpawn.SpawnMap.GetSpawnMap().Positions.IntersectBy(UsedRooms[Main.CurrentMap].Values, x => x.Key).RandomElement().Value;
|
||||
PlayerControl ffaSurvivor = stillLiving[0];
|
||||
|
||||
|
||||
switch (stillLiving.Count)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
PlayerControl ffaSurvivor = stillLiving[0];
|
||||
ffaSurvivor.RpcChangeRoleBasis(CustomRoles.QuizPlayer);
|
||||
ffaSurvivor.TP(location);
|
||||
break;
|
||||
@@ -579,6 +580,7 @@ public static class Quiz
|
||||
SystemTypes correctRoom = UsedRooms[Main.CurrentMap][(char)('A' + CurrentQuestion.CorrectAnswerIndex)];
|
||||
DyingPlayers = Main.AllAlivePlayerControls.Select(x => (ID: x.PlayerId, Room: x.GetPlainShipRoom())).Where(x => correctRoom == SystemTypes.Outside ? x.Room != null : x.Room == null || x.Room.RoomId != correctRoom).Select(x => x.ID).ToList();
|
||||
QuestionTimeLimitEndTS = 0;
|
||||
Utils.NotifyRoles();
|
||||
}
|
||||
else
|
||||
Main.Instance.StartCoroutine(EndQuestion());
|
||||
|
||||
@@ -103,6 +103,13 @@ public static class RoomRush
|
||||
[(SystemTypes.MiningPit, SystemTypes.Storage)] = 2,
|
||||
[(SystemTypes.MiningPit, SystemTypes.Dropship)] = 2,
|
||||
[(SystemTypes.MiningPit, SystemTypes.Comms)] = 2
|
||||
},
|
||||
[(MapNames)6] = new()
|
||||
{
|
||||
[(SystemTypes.Admin, SystemTypes.Lounge)] = 2,
|
||||
[(SystemTypes.Comms, SystemTypes.Medical)] = 2,
|
||||
[((SystemTypes)SubmergedCompatibility.SubmergedSystemTypes.Research, SystemTypes.Medical)] = 3,
|
||||
[((SystemTypes)SubmergedCompatibility.SubmergedSystemTypes.Ballast, SystemTypes.Security)] = 2
|
||||
}
|
||||
};
|
||||
|
||||
@@ -188,6 +195,7 @@ public static class RoomRush
|
||||
AllRooms.Remove(SystemTypes.Outside);
|
||||
AllRooms.Remove(SystemTypes.Ventilation);
|
||||
AllRooms.RemoveWhere(x => x.ToString().Contains("Decontamination"));
|
||||
if (SubmergedCompatibility.IsSubmerged()) AllRooms.RemoveWhere(x => (byte)x > 135);
|
||||
|
||||
DonePlayers = [];
|
||||
Points = [];
|
||||
@@ -313,6 +321,7 @@ public static class RoomRush
|
||||
MapNames.Polus => SystemTypes.Dropship,
|
||||
MapNames.Airship => SystemTypes.MainHall,
|
||||
MapNames.Fungle => SystemTypes.Dropship,
|
||||
(MapNames)6 => (SystemTypes)SubmergedCompatibility.SubmergedSystemTypes.UpperCentral,
|
||||
_ => throw new ArgumentOutOfRangeException(map.ToString(), "Invalid map")
|
||||
};
|
||||
|
||||
@@ -330,6 +339,7 @@ public static class RoomRush
|
||||
{
|
||||
MapNames.MiraHQ => previous is SystemTypes.Laboratory or SystemTypes.Reactor ^ RoomGoal is SystemTypes.Laboratory or SystemTypes.Reactor,
|
||||
MapNames.Polus => previous == SystemTypes.Specimens || RoomGoal == SystemTypes.Specimens,
|
||||
(MapNames)6 => (previous == (SystemTypes)SubmergedCompatibility.SubmergedSystemTypes.Ballast) ^ (RoomGoal == (SystemTypes)SubmergedCompatibility.SubmergedSystemTypes.Ballast),
|
||||
_ => false
|
||||
};
|
||||
|
||||
@@ -341,6 +351,7 @@ public static class RoomRush
|
||||
: Options.DecontaminationTimeOnMiraHQ.GetInt() + Options.DecontaminationDoorOpenTimeOnMiraHQ.GetInt()
|
||||
: 6;
|
||||
|
||||
if (SubmergedCompatibility.IsSubmerged()) decontaminationTime = 3;
|
||||
time += decontaminationTime + 3;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ public static class Speedrun
|
||||
{
|
||||
int timer = TimeLimit.GetInt();
|
||||
if (Main.CurrentMap is MapNames.Airship or MapNames.Fungle) timer += 5;
|
||||
if (SubmergedCompatibility.IsSubmerged()) timer *= 2;
|
||||
|
||||
if (TimeStacksUp.GetBool())
|
||||
Timers[pc.PlayerId] += timer;
|
||||
|
||||
@@ -266,6 +266,7 @@ public static class TheMindGame
|
||||
if (currentMap is MapNames.Fungle) AllRooms.Remove(SystemTypes.FishingDock);
|
||||
if (currentMap is MapNames.Fungle) AllRooms.Remove(SystemTypes.Greenhouse);
|
||||
AllRooms.RemoveAll(x => x.ToString().Contains("Decontamination"));
|
||||
if (SubmergedCompatibility.IsSubmerged()) AllRooms.RemoveAll(x => (byte)x > 135);
|
||||
|
||||
PlayerControl[] aapc = Main.AllAlivePlayerControls;
|
||||
Points = aapc.ToDictionary(x => x.PlayerId, _ => 0);
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace EHR;
|
||||
[BepInIncompatibility("MalumMenu")]
|
||||
[BepInIncompatibility("com.ten.thebetterroles")]
|
||||
[BepInIncompatibility("xyz.crowdedmods.crowdedmod")]
|
||||
[BepInDependency(SubmergedCompatibility.SubmergedGuid, BepInDependency.DependencyFlags.SoftDependency)]
|
||||
[BepInProcess("Among Us.exe")]
|
||||
[SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
|
||||
public class Main : BasePlugin
|
||||
@@ -55,7 +56,7 @@ public class Main : BasePlugin
|
||||
public const string ForkId = "EHR";
|
||||
public const string SupportedAUVersion = "2025.4.15";
|
||||
|
||||
public const string DataPath =
|
||||
public static readonly string DataPath =
|
||||
#if ANDROID
|
||||
Application.persistentDataPath;
|
||||
#else
|
||||
@@ -811,6 +812,9 @@ public class Main : BasePlugin
|
||||
try { DevManager.StartFetchingTags(); }
|
||||
catch (Exception e) { Utils.ThrowException(e); }
|
||||
|
||||
try { SubmergedCompatibility.Initialize(); }
|
||||
catch (Exception e) { Utils.ThrowException(e); }
|
||||
|
||||
Logger.Msg("========= EHR loaded! =========", "Plugin Load");
|
||||
Logger.Msg($"EHR Version: {PluginVersion}, Test Build: {TestBuild}", "Plugin Load");
|
||||
};
|
||||
|
||||
@@ -91,6 +91,7 @@ public static class AFKDetector
|
||||
case Data.Phase.Detection:
|
||||
data.CurrentPhase = Data.Phase.Warning;
|
||||
data.Timer = 15f;
|
||||
Utils.NotifyRoles(SpecifyTarget: pc);
|
||||
if (pc.IsAlive() && !MeetingStates.FirstMeeting) pc.FixBlackScreen();
|
||||
break;
|
||||
case Data.Phase.Warning:
|
||||
|
||||
@@ -109,7 +109,7 @@ public static class Achievements
|
||||
ItsJustAPrankBro // As Bomber, Kill half the lobby in 1 bomb
|
||||
}
|
||||
|
||||
private const string SaveFilePath = $"{Main.DataPath}/EHR_DATA/Achievements.json";
|
||||
private static readonly string SaveFilePath = $"{Main.DataPath}/EHR_DATA/Achievements.json";
|
||||
|
||||
private const string ApiBaseUrl = "https://gurge44.pythonanywhere.com/achievements";
|
||||
private const string ApiSaveEndpoint = $"{ApiBaseUrl}/save";
|
||||
|
||||
@@ -15,10 +15,10 @@ namespace EHR;
|
||||
|
||||
public static class BanManager
|
||||
{
|
||||
private const string DenyNameListPath = $"{Main.DataPath}/EHR_DATA/DenyName.txt";
|
||||
private const string BanListPath = $"{Main.DataPath}/EHR_DATA/BanList.txt";
|
||||
private const string ModeratorListPath = $"{Main.DataPath}/EHR_DATA/Moderators.txt";
|
||||
private const string WhiteListListPath = $"{Main.DataPath}/EHR_DATA/WhiteList.txt";
|
||||
private static readonly string DenyNameListPath = $"{Main.DataPath}/EHR_DATA/DenyName.txt";
|
||||
private static readonly string BanListPath = $"{Main.DataPath}/EHR_DATA/BanList.txt";
|
||||
private static readonly string ModeratorListPath = $"{Main.DataPath}/EHR_DATA/Moderators.txt";
|
||||
private static readonly string WhiteListListPath = $"{Main.DataPath}/EHR_DATA/WhiteList.txt";
|
||||
private static readonly List<string> EACList = [];
|
||||
public static readonly List<string> TempBanWhiteList = []; // To prevent writing to the banlist
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Linq;
|
||||
using AmongUs.InnerNet.GameDataMessages;
|
||||
using EHR;
|
||||
using EHR.Crewmate;
|
||||
using EHR.Impostor;
|
||||
using EHR.Modules;
|
||||
using HarmonyLib;
|
||||
using Hazel;
|
||||
@@ -44,7 +45,7 @@ namespace EHR
|
||||
string skinId = PlayerControl.LocalPlayer.Data.Outfits[PlayerOutfitType.Default].SkinId;
|
||||
string petId = PlayerControl.LocalPlayer.Data.Outfits[PlayerOutfitType.Default].PetId;
|
||||
string visorId = PlayerControl.LocalPlayer.Data.Outfits[PlayerOutfitType.Default].VisorId;
|
||||
var sender = CustomRpcSender.Create("SetFakeData", this is BedWarsItemGenerator ? SendOption.None : SendOption.Reliable, log: false);
|
||||
var sender = CustomRpcSender.Create("CustomNetObject.RpcChangeSprite", this is BedWarsItemGenerator ? SendOption.None : SendOption.Reliable, log: false);
|
||||
MessageWriter writer = sender.stream;
|
||||
sender.StartMessage();
|
||||
PlayerControl.LocalPlayer.Data.Outfits[PlayerOutfitType.Default].PlayerName = "<size=14><br></size>" + sprite;
|
||||
@@ -218,7 +219,7 @@ namespace EHR
|
||||
string skinId = PlayerControl.LocalPlayer.Data.Outfits[PlayerOutfitType.Default].SkinId;
|
||||
string petId = PlayerControl.LocalPlayer.Data.Outfits[PlayerOutfitType.Default].PetId;
|
||||
string visorId = PlayerControl.LocalPlayer.Data.Outfits[PlayerOutfitType.Default].VisorId;
|
||||
var sender = CustomRpcSender.Create("SetFakeData", SendOption.Reliable, log: false);
|
||||
var sender = CustomRpcSender.Create("CustomNetObject.CreateNetObject", SendOption.Reliable, log: false);
|
||||
MessageWriter writer = sender.stream;
|
||||
sender.StartMessage();
|
||||
PlayerControl.LocalPlayer.Data.Outfits[PlayerOutfitType.Default].PlayerName = "<size=14><br></size>" + sprite;
|
||||
@@ -270,7 +271,7 @@ namespace EHR
|
||||
|
||||
LateTask.New(() =>
|
||||
{
|
||||
var sender = CustomRpcSender.Create("SetFakeData", SendOption.Reliable, log: false);
|
||||
var sender = CustomRpcSender.Create("CustomNetObject.CreateNetObject (2)", SendOption.Reliable, log: false);
|
||||
MessageWriter writer = sender.stream;
|
||||
sender.StartMessage(pc.OwnerId);
|
||||
writer.StartMessage(1);
|
||||
@@ -326,7 +327,8 @@ namespace EHR
|
||||
{
|
||||
if (!(Options.IntegrateNaturalDisasters.GetBool() && Options.CurrentGameMode != CustomGameMode.NaturalDisasters))
|
||||
TempDespawnedObjects = AllObjects.ToList();
|
||||
|
||||
|
||||
if (Abyssbringer.ShouldDespawnCNOOnMeeting) TempDespawnedObjects.RemoveAll(x => x is BlackHole);
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
||||
@@ -112,6 +112,7 @@ public class GrabOxygenMaskSabotage : CustomSabotage
|
||||
MapNames.Polus => SystemTypes.Specimens,
|
||||
MapNames.Airship => SystemTypes.Medical,
|
||||
MapNames.Fungle => SystemTypes.Kitchen,
|
||||
(MapNames)6 => (SystemTypes)SubmergedCompatibility.SubmergedSystemTypes.Filtration,
|
||||
_ => SystemTypes.Outside
|
||||
};
|
||||
|
||||
|
||||
@@ -230,6 +230,9 @@ public class CustomLogger
|
||||
""";
|
||||
|
||||
Builder.Append(logEntry);
|
||||
#if DEBUG
|
||||
Finish(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
private IEnumerator InactivityCheck()
|
||||
@@ -250,5 +253,6 @@ public class CustomLogger
|
||||
if (dump) append += HtmlFooter;
|
||||
File.AppendAllText(LOGFilePath, append);
|
||||
PrivateInstance = null;
|
||||
if (dump) Main.Instance.StopCoroutine(InactivityCheck());
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,7 @@ internal static class DisableDevice
|
||||
MapNames.Dleks => 1.5f,
|
||||
MapNames.Airship => 1.8f,
|
||||
MapNames.Fungle => 1.8f,
|
||||
_ => 0.0f
|
||||
_ => 2f
|
||||
};
|
||||
|
||||
public static void FixedUpdate()
|
||||
|
||||
@@ -197,7 +197,7 @@ public enum ErrorCode
|
||||
|
||||
// 002 Support related
|
||||
UnsupportedVersion = 002_000_3, // 002-000-1 AmongUs version is outdated
|
||||
UnsupportedMap = 002_000_2, // 002-000-2 Unsupported Map
|
||||
UnsupportedMap = 002_000_1, // 002-000-1 Unsupported Map
|
||||
|
||||
// ==========
|
||||
// 000 Test
|
||||
|
||||
@@ -261,8 +261,12 @@ internal static class ExtendedPlayerControl
|
||||
if (init) Main.PlayerStates[player.PlayerId].InitTask(player);
|
||||
}
|
||||
|
||||
public static HashSet<byte> TempExiled = [];
|
||||
|
||||
public static void ExileTemporarily(this PlayerControl pc)
|
||||
{
|
||||
if (!TempExiled.Add(pc.PlayerId)) return;
|
||||
|
||||
pc.Exiled();
|
||||
Main.PlayerStates[pc.PlayerId].SetDead();
|
||||
|
||||
@@ -341,6 +345,7 @@ internal static class ExtendedPlayerControl
|
||||
return;
|
||||
}
|
||||
|
||||
TempExiled.Remove(player.PlayerId);
|
||||
GhostRolesManager.RemoveGhostRole(player.PlayerId);
|
||||
Main.PlayerStates[player.PlayerId].IsDead = false;
|
||||
Main.PlayerStates[player.PlayerId].deathReason = PlayerState.DeathReason.etc;
|
||||
@@ -652,6 +657,7 @@ internal static class ExtendedPlayerControl
|
||||
MapNames.Skeld or MapNames.Dleks when room != null => true,
|
||||
MapNames.Polus when overlapPointNonAlloc >= 1 => true,
|
||||
MapNames.Polus when pos.y is >= -26.11f and <= -6.41f && pos.x is >= 3.56f and <= 32.68f => true,
|
||||
(MapNames)6 => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
@@ -93,6 +93,12 @@ public static class GuessManager
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!Options.CanGuessDuringDiscussionTime.GetBool() && MeetingHud.Instance && MeetingHud.Instance.state is MeetingHud.VoteStates.Discussion or MeetingHud.VoteStates.Animating)
|
||||
{
|
||||
ShowMessage("GuessDuringDiscussion");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pc.Is(CustomRoles.Decryptor) && Decryptor.GuessMode.GetValue() == 2) goto SkipCheck;
|
||||
|
||||
if ((pc.IsCrewmate() && !Options.CrewmatesCanGuess.GetBool()) ||
|
||||
@@ -1069,7 +1075,7 @@ public static class GuessManager
|
||||
|
||||
if (AmongUsClient.Instance.AmHost)
|
||||
{
|
||||
HashSet<byte> guessers = Main.AllPlayerControls.Where(x => CanGuess(x, false)).Select(x => x.PlayerId).ToHashSet();
|
||||
HashSet<byte> guessers = Main.AllAlivePlayerControls.Where(x => CanGuess(x, false)).Select(x => x.PlayerId).ToHashSet();
|
||||
LateTask.New(() => guessers.Do(x => Utils.SendMessage(GetString("YouCanGuess"), x, GetString("YouCanGuessTitle"))), 12f, log: false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,6 +337,7 @@ public static class Options
|
||||
public static OptionItem ReportBaitAtAllCost;
|
||||
|
||||
public static OptionItem GuesserDoesntDieOnMisguess;
|
||||
public static OptionItem CanGuessDuringDiscussionTime;
|
||||
|
||||
public static OptionItem GuesserMaxKillsPerMeeting;
|
||||
public static OptionItem GuesserMaxKillsPerGame;
|
||||
@@ -2658,6 +2659,9 @@ public static class Options
|
||||
GuesserDoesntDieOnMisguess = new BooleanOptionItem(19718, "GuesserDoesntDieOnMisguess", false, TabGroup.TaskSettings)
|
||||
.SetGameMode(CustomGameMode.Standard);
|
||||
|
||||
CanGuessDuringDiscussionTime = new BooleanOptionItem(19799, "CanGuessDuringDiscussionTime", true, TabGroup.TaskSettings)
|
||||
.SetGameMode(CustomGameMode.Standard);
|
||||
|
||||
LoadingPercentage = 92;
|
||||
MainLoadingText = "Building game settings";
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace EHR.Modules;
|
||||
|
||||
public static class PrivateTagManager
|
||||
{
|
||||
private const string TagFile = $"{Main.DataPath}/EHR_DATA/tags.txt";
|
||||
private static readonly string TagFile = $"{Main.DataPath}/EHR_DATA/tags.txt";
|
||||
public static Dictionary<string, string> Tags = [];
|
||||
|
||||
public static void AddTag(string friendcode, string tag)
|
||||
|
||||
+13
-2
@@ -136,8 +136,18 @@ public enum CustomRPC
|
||||
SyncRomanticTarget,
|
||||
SyncVengefulRomanticTarget,
|
||||
SetRevealedPlayer,
|
||||
SetCurrentRevealTarget,
|
||||
SetDoomsayerProgress,
|
||||
SetCurrentRevealTarget = 209,
|
||||
|
||||
/*
|
||||
* SUBMERGED RPCs
|
||||
* 210 - SetCustomData
|
||||
* 211 - RequestChangeFloor
|
||||
* 212 - AcknowledgeChangeFloor
|
||||
* 213 - EngineVent
|
||||
* 214 - OxygenDeath
|
||||
*/
|
||||
|
||||
SetDoomsayerProgress = 215,
|
||||
SetTrackerTarget,
|
||||
RpcPassBomb,
|
||||
SetAlchemistTimer,
|
||||
@@ -229,6 +239,7 @@ internal static class RPCHandlerPatch
|
||||
|
||||
private static bool TrustedRpc(byte id)
|
||||
{
|
||||
if (SubmergedCompatibility.IsSubmerged() && id is >= 120 and <= 124) return true;
|
||||
return (CustomRPC)id is CustomRPC.VersionCheck or CustomRPC.RequestRetryVersionCheck or CustomRPC.AntiBlackout or CustomRPC.SyncNameNotify or CustomRPC.RequestSendMessage or CustomRPC.RequestCommandProcessing or CustomRPC.Judge or CustomRPC.SetNiceSwapperVotes or CustomRPC.MeetingKill or CustomRPC.Guess or CustomRPC.MafiaRevenge or CustomRPC.BAU or CustomRPC.FFAKill or CustomRPC.TMGSync or CustomRPC.ParityCopCommand;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace EHR;
|
||||
|
||||
public static class SpamManager
|
||||
{
|
||||
private const string BannedWordsFilePath = $"{Main.DataPath}/EHR_DATA/BanWords.txt";
|
||||
private static readonly string BannedWordsFilePath = $"{Main.DataPath}/EHR_DATA/BanWords.txt";
|
||||
private static List<string> BanWords = [];
|
||||
|
||||
public static void Init()
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace EHR;
|
||||
|
||||
public static class TemplateManager
|
||||
{
|
||||
private const string TemplateFilePath = $"{Main.DataPath}/EHR_DATA/template.txt";
|
||||
private static readonly string TemplateFilePath = $"{Main.DataPath}/EHR_DATA/template.txt";
|
||||
|
||||
private static readonly Dictionary<string, Func<string>> ReplaceDictionary = new()
|
||||
{
|
||||
|
||||
@@ -120,6 +120,9 @@ public static class Translator
|
||||
|
||||
public static string GetString(string s, Dictionary<string, string> replacementDic = null, bool console = false)
|
||||
{
|
||||
if (SubmergedCompatibility.IsSubmerged() && int.TryParse(s, out int roomNumber) && roomNumber is >= 128 and <= 135)
|
||||
s = $"SubmergedRoomName.{roomNumber}";
|
||||
|
||||
SupportedLangs langId = TranslationController.InstanceExists ? TranslationController.Instance.currentLanguage.languageID : SupportedLangs.English;
|
||||
if (console) langId = SupportedLangs.English;
|
||||
|
||||
@@ -167,8 +170,9 @@ public static class Translator
|
||||
{
|
||||
#if ANDROID
|
||||
return TranslationController.Instance.GetString(stringName);
|
||||
#endif
|
||||
#else
|
||||
return FastDestroyableSingleton<TranslationController>.Instance.GetString(stringName, new Il2CppReferenceArray<Il2CppSystem.Object>(0));
|
||||
#endif
|
||||
}
|
||||
|
||||
public static string GetRoleString(string str, bool forUser = true)
|
||||
|
||||
+10
-1
@@ -153,12 +153,13 @@ public static class Utils
|
||||
{
|
||||
PlayerControl pc = nt.myPlayer;
|
||||
var sendOption = SendOption.Reliable;
|
||||
bool submerged = SubmergedCompatibility.IsSubmerged();
|
||||
|
||||
if (!noCheckState)
|
||||
{
|
||||
if (pc.Is(CustomRoles.AntiTP)) return false;
|
||||
|
||||
if (pc.inVent || pc.inMovingPlat || pc.onLadder || !pc.IsAlive() || pc.MyPhysics.Animations.IsPlayingAnyLadderAnimation() || pc.MyPhysics.Animations.IsPlayingEnterVentAnimation())
|
||||
if (pc.inVent || pc.inMovingPlat || pc.onLadder || !pc.IsAlive() || pc.MyPhysics.Animations.IsPlayingAnyLadderAnimation() || pc.MyPhysics.Animations.IsPlayingEnterVentAnimation() || (submerged && pc.IsLocalPlayer() && SubmergedCompatibility.GetInTransition()))
|
||||
{
|
||||
if (log) Logger.Warn($"Target ({pc.GetNameWithRole().RemoveHtmlTags()}) is in an un-teleportable state - Teleporting canceled", "TP");
|
||||
return false;
|
||||
@@ -209,6 +210,14 @@ public static class Utils
|
||||
|
||||
CheckInvalidMovementPatch.LastPosition[pc.PlayerId] = location;
|
||||
CheckInvalidMovementPatch.ExemptedPlayers.Add(pc.PlayerId);
|
||||
AFKDetector.TempIgnoredPlayers.Add(pc.PlayerId);
|
||||
LateTask.New(() => AFKDetector.TempIgnoredPlayers.Remove(pc.PlayerId), 0.2f + CalculatePingDelay(), log: false);
|
||||
|
||||
if (submerged)
|
||||
{
|
||||
SubmergedCompatibility.ChangeFloor(pc.PlayerId, pc.transform.position.y > -7);
|
||||
SubmergedCompatibility.CheckOutOfBoundsElevator(pc);
|
||||
}
|
||||
|
||||
if (sendOption == SendOption.Reliable) NumSnapToCallsThisRound++;
|
||||
return true;
|
||||
|
||||
@@ -237,7 +237,7 @@ internal static class ChatCommands
|
||||
if (LastModFileUpdate + 5 > now) { friendCodes = ModsFileCache; }
|
||||
else
|
||||
{
|
||||
const string friendCodesFilePath = $"{Main.DataPath}/EHR_DATA/Moderators.txt";
|
||||
var friendCodesFilePath = $"{Main.DataPath}/EHR_DATA/Moderators.txt";
|
||||
|
||||
if (!File.Exists(friendCodesFilePath))
|
||||
{
|
||||
@@ -265,7 +265,7 @@ internal static class ChatCommands
|
||||
if (LastVIPFileUpdate + 5 > now) { friendCodes = VIPsFileCache; }
|
||||
else
|
||||
{
|
||||
const string friendCodesFilePath = $"{Main.DataPath}/EHR_DATA/VIPs.txt";
|
||||
var friendCodesFilePath = $"{Main.DataPath}/EHR_DATA/VIPs.txt";
|
||||
|
||||
if (!File.Exists(friendCodesFilePath))
|
||||
{
|
||||
|
||||
@@ -173,6 +173,23 @@ internal static class AuthTimeoutPatch
|
||||
|
||||
// If you don't patch this, you still need to wait for 5 s.
|
||||
// I have no idea why this is happening
|
||||
#if ANDROID
|
||||
[HarmonyPatch(typeof(AmongUsClient._CoJoinOnlinePublicGame_d__50), nameof(AmongUsClient._CoJoinOnlinePublicGame_d__50.MoveNext))]
|
||||
[HarmonyPrefix]
|
||||
public static void EnableUdpMatchmakingPrefix(AmongUsClient._CoJoinOnlinePublicGame_d__50 __instance)
|
||||
{
|
||||
// Skip to state 1, which just calls CoJoinOnlineGameDirect
|
||||
if (__instance.__1__state == 0 && !ServerManager.Instance.IsHttp)
|
||||
{
|
||||
__instance.__1__state = 1;
|
||||
|
||||
__instance.__8__1 = new()
|
||||
{
|
||||
matchmakerToken = string.Empty
|
||||
};
|
||||
}
|
||||
}
|
||||
#else
|
||||
[HarmonyPatch(typeof(AmongUsClient._CoJoinOnlinePublicGame_d__49), nameof(AmongUsClient._CoJoinOnlinePublicGame_d__49.MoveNext))]
|
||||
[HarmonyPrefix]
|
||||
public static void EnableUdpMatchmakingPrefix(AmongUsClient._CoJoinOnlinePublicGame_d__49 __instance)
|
||||
@@ -188,4 +205,5 @@ internal static class AuthTimeoutPatch
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -7,7 +7,7 @@ public static class DeconSystemUpdateSystemPatch
|
||||
{
|
||||
public static void Prefix(DeconSystem __instance)
|
||||
{
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || SubmergedCompatibility.IsSubmerged()) return;
|
||||
|
||||
if (Options.ChangeDecontaminationTime.GetBool())
|
||||
{
|
||||
|
||||
+12
-3
@@ -32,6 +32,15 @@ internal static class AllMapIconsPatch
|
||||
dleksIcon.MapImage = Utils.LoadSprite("EHR.Resources.Images.DleksBanner.png", 100f);
|
||||
dleksIcon.NameImage = Utils.LoadSprite("EHR.Resources.Images.DleksBanner-Wordart.png", 100f);
|
||||
__instance.AllMapIcons.Add(dleksIcon);
|
||||
|
||||
if (SubmergedCompatibility.Loaded)
|
||||
{
|
||||
MapIconByName submergedIcon = Object.Instantiate(__instance, __instance.gameObject.transform).AllMapIcons[0];
|
||||
submergedIcon.Name = (MapNames)6;
|
||||
submergedIcon.MapImage = Utils.LoadSprite("EHR.Resources.Images.SubmergedBanner.png", 100f);
|
||||
submergedIcon.NameImage = Utils.LoadSprite("EHR.Resources.Images.Submerged-Wordart.png", 100f);
|
||||
__instance.AllMapIcons.Add(submergedIcon);
|
||||
}
|
||||
}
|
||||
catch (Exception e) { Utils.ThrowException(e); }
|
||||
}
|
||||
@@ -56,7 +65,7 @@ public static class DleksPatch
|
||||
}
|
||||
|
||||
// removed dleks check as it's always false
|
||||
int num2 = Mathf.Clamp(GameOptionsManager.Instance.CurrentGameOptions.MapId, 0, Constants.MapNames.Length - 1);
|
||||
int num2 = GameOptionsManager.Instance.CurrentGameOptions.MapId == 6 && SubmergedCompatibility.Loaded && SubmergedCompatibility.IsSupported(Options.CurrentGameMode) ? 6 : 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;
|
||||
|
||||
@@ -118,7 +127,7 @@ public static class VentSetButtonsPatch
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(Vent), nameof(Vent.TryMoveToVent))]
|
||||
internal class VentTryMoveToVentPatch
|
||||
internal static class VentTryMoveToVentPatch
|
||||
{
|
||||
// Update arrows buttons when player move to vents
|
||||
private static void Postfix(Vent __instance, [HarmonyArgument(0)] Vent otherVent)
|
||||
@@ -132,7 +141,7 @@ internal class VentTryMoveToVentPatch
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(Vent), nameof(Vent.UpdateArrows))]
|
||||
internal class VentUpdateArrowsPatch
|
||||
internal static class VentUpdateArrowsPatch
|
||||
{
|
||||
// Fixes "Index was outside the bounds of the array" errors when arrows updates in vent on Dleks map
|
||||
private static bool Prefix()
|
||||
|
||||
@@ -15,7 +15,7 @@ internal static class ExileControllerWrapUpPatch
|
||||
{
|
||||
public static NetworkedPlayerInfo LastExiled;
|
||||
|
||||
private static void WrapUpPostfix(NetworkedPlayerInfo exiled)
|
||||
public static void WrapUpPostfix(NetworkedPlayerInfo exiled)
|
||||
{
|
||||
var decidedWinner = false;
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
@@ -112,7 +112,7 @@ internal static class ExileControllerWrapUpPatch
|
||||
}, 2.5f, "AfterPlayerDeathTasks For Exiled Player");
|
||||
}
|
||||
|
||||
private static void WrapUpFinalizer()
|
||||
public static void WrapUpFinalizer()
|
||||
{
|
||||
// Even if an exception occurs in WrapUpPostfix, this part will be executed reliably.
|
||||
|
||||
|
||||
@@ -1124,6 +1124,7 @@ public static class GameSettingMenuPatch
|
||||
Vector3 gameSettingsLabelPos = gameSettingsLabel.transform.localPosition;
|
||||
|
||||
CustomGameMode[] gms = Enum.GetValues<CustomGameMode>()[..^1];
|
||||
if (Main.NormalOptions.MapId == 6 && SubmergedCompatibility.Loaded) gms = gms.Where(SubmergedCompatibility.IsSupported).ToArray();
|
||||
int totalCols = Mathf.Max(1, Mathf.CeilToInt(gms.Length / 5f));
|
||||
|
||||
GMButtons = [];
|
||||
|
||||
@@ -194,8 +194,9 @@ public static class GameStartManagerPatch
|
||||
CreateOptionsPickerPatch.SetDleks = Main.CurrentMap == MapNames.Dleks;
|
||||
}
|
||||
else if (CreateOptionsPickerPatch.SetDleks) Main.NormalOptions.MapId = 3;
|
||||
else if (CreateOptionsPickerPatch.SetSubmerged) Main.NormalOptions.MapId = 6;
|
||||
|
||||
if (Main.CurrentMap == MapNames.Dleks)
|
||||
if (Main.CurrentMap == MapNames.Dleks || Main.NormalOptions.MapId == 6)
|
||||
{
|
||||
var opt = Main.NormalOptions.CastFast<IGameOptions>();
|
||||
|
||||
@@ -233,7 +234,7 @@ public static class GameStartManagerPatch
|
||||
try { instance.UpdateMapImage((MapNames)GameManager.Instance.LogicOptions.MapId); }
|
||||
catch (Exception e)
|
||||
{
|
||||
if (GameManager.Instance.LogicOptions.MapId >= Enum.GetValues<MapNames>().Length)
|
||||
if (GameManager.Instance.LogicOptions.MapId >= Enum.GetValues<MapNames>().Length && !(GameManager.Instance.LogicOptions.MapId == 6 && SubmergedCompatibility.Loaded && SubmergedCompatibility.IsSupported(Options.CurrentGameMode)))
|
||||
ErrorText.Instance.AddError(ErrorCode.UnsupportedMap);
|
||||
|
||||
Utils.ThrowException(e);
|
||||
@@ -541,6 +542,7 @@ public static class GameStartRandomMap
|
||||
CreateOptionsPickerPatch.SetDleks = Main.CurrentMap == MapNames.Dleks;
|
||||
}
|
||||
else if (CreateOptionsPickerPatch.SetDleks) Main.NormalOptions.MapId = 3;
|
||||
else if (CreateOptionsPickerPatch.SetSubmerged) Main.NormalOptions.MapId = 6;
|
||||
}
|
||||
|
||||
public static byte SelectRandomMap()
|
||||
|
||||
+4
-2
@@ -667,6 +667,8 @@ internal static class SabotageMapPatch
|
||||
|
||||
public static void Postfix(InfectedOverlay __instance)
|
||||
{
|
||||
if (SubmergedCompatibility.IsSubmerged()) return;
|
||||
|
||||
float perc = __instance.sabSystem.PercentCool;
|
||||
int total = __instance.sabSystem.initialCooldown ? 10 : 30;
|
||||
if (SabotageSystemTypeRepairDamagePatch.IsCooldownModificationEnabled) total = (int)SabotageSystemTypeRepairDamagePatch.ModifiedCooldownSec;
|
||||
@@ -709,7 +711,7 @@ internal static class MapRoomDoorsUpdatePatch
|
||||
|
||||
public static bool Prefix(MapRoom __instance)
|
||||
{
|
||||
if (!__instance.door || !ShipStatus.Instance) return false;
|
||||
if (!__instance.door || !ShipStatus.Instance || SubmergedCompatibility.IsSubmerged()) return false;
|
||||
|
||||
SystemTypes room = __instance.room;
|
||||
|
||||
@@ -958,7 +960,7 @@ internal static class TaskPanelBehaviourPatch
|
||||
else
|
||||
{
|
||||
finalText += Main.AllPlayerControls
|
||||
.Select(x => (pc: x, points_string: RoomRush.GetPoints(x.PlayerId), points_int: int.Parse(RoomRush.GetPoints(x.PlayerId).Split('/')[0])))
|
||||
.Select(x => (pc: x, points_string: RoomRush.GetPoints(x.PlayerId), points_int: int.TryParse(RoomRush.GetPoints(x.PlayerId).Split('/')[0], out int points) ? points : 0))
|
||||
.OrderByDescending(x => x.points_int)
|
||||
.Aggregate("<size=70%>", (s, x) => $"{s}\r\n{x.pc.PlayerId.ColoredPlayerName()} - {x.points_string}");
|
||||
}
|
||||
|
||||
@@ -14,6 +14,19 @@ namespace EHR;
|
||||
|
||||
// Patch for non-host modded clients to ensure that the intro cutscene is shown correctly
|
||||
// and GameStates.InGame is set to true
|
||||
#if ANDROID
|
||||
[HarmonyPatch(typeof(IntroCutscene._ShowRole_d__40), nameof(IntroCutscene._ShowRole_d__40.MoveNext))]
|
||||
static class ShowRoleMoveNextPatchAndroid
|
||||
{
|
||||
public static void Postfix(IntroCutscene._ShowRole_d__40 __instance, ref bool __result)
|
||||
{
|
||||
if (AmongUsClient.Instance.AmHost || __instance.__1__state != 1 || !__result) return;
|
||||
|
||||
GameStates.InGame = true;
|
||||
SetUpRoleTextPatch.Postfix(__instance.__4__this);
|
||||
}
|
||||
}
|
||||
#else
|
||||
[HarmonyPatch(typeof(IntroCutscene._ShowRole_d__41), nameof(IntroCutscene._ShowRole_d__41.MoveNext))]
|
||||
static class ShowRoleMoveNextPatch
|
||||
{
|
||||
@@ -25,6 +38,7 @@ static class ShowRoleMoveNextPatch
|
||||
SetUpRoleTextPatch.Postfix(__instance.__4__this);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// For some reason, IntroCutScene.ShowRole is not called in the base game with this exact same code,
|
||||
// so we need to patch HudManager.CoShowIntro for the host entirely to ensure that the intro is shown correctly
|
||||
|
||||
@@ -14,6 +14,7 @@ internal static class LightSourceUpdatePatch
|
||||
|
||||
public static bool Prefix(LightSource __instance)
|
||||
{
|
||||
if (SubmergedCompatibility.IsSubmerged()) return true;
|
||||
Vector3 position = __instance.transform.position;
|
||||
position.z -= 7f;
|
||||
__instance.UpdateFlashlightAngle();
|
||||
@@ -40,6 +41,7 @@ internal static class LightSourceGpuRendererPatch
|
||||
|
||||
public static bool Prefix(LightSourceGpuRenderer __instance, [HarmonyArgument(0)] float effectiveRadius)
|
||||
{
|
||||
if (SubmergedCompatibility.IsSubmerged()) return true;
|
||||
if (!__instance.shadowTexture || !__instance.shadowCasterMaterial) return false;
|
||||
float width = __instance.shadowTexture.width;
|
||||
__instance.shadowCasterMaterial.SetFloat(DepthCompressionValue, effectiveRadius);
|
||||
|
||||
@@ -9,6 +9,9 @@ namespace EHR.Patches;
|
||||
// Thanks: https://github.com/SubmergedAmongUs/Submerged/blob/4a5a6b47cbed526670ae4b7eae76acd7c42e35de/Submerged/UI/Patches/MapSelectButtonPatches.cs#L49
|
||||
internal static class CreateOptionsPickerPatch
|
||||
{
|
||||
public static bool SetSubmerged;
|
||||
private static MapSelectButton SubmergedButton;
|
||||
|
||||
public static bool SetDleks;
|
||||
private static MapSelectButton DleksButton;
|
||||
|
||||
@@ -22,58 +25,108 @@ internal static class CreateOptionsPickerPatch
|
||||
if (SceneManager.GetActiveScene().name == "FindAGame") return;
|
||||
|
||||
const int dleksPos = 3;
|
||||
const int submergedPos = 6;
|
||||
|
||||
MapSelectButton[] AllMapButton = __instance.transform.GetComponentsInChildren<MapSelectButton>();
|
||||
|
||||
if (AllMapButton != null)
|
||||
{
|
||||
GameObject dlekS_ehT = Object.Instantiate(AllMapButton[0].gameObject, __instance.transform);
|
||||
dlekS_ehT.transform.position = AllMapButton[dleksPos].transform.position;
|
||||
dlekS_ehT.transform.SetSiblingIndex(dleksPos + 2);
|
||||
var dlekS_ehT_MapButton = dlekS_ehT.GetComponent<MapSelectButton>();
|
||||
DleksButton = dlekS_ehT_MapButton;
|
||||
|
||||
foreach (SpriteRenderer icon in dlekS_ehT_MapButton.MapIcon)
|
||||
// Dleks Button
|
||||
{
|
||||
if (icon == null || icon.transform == null) continue;
|
||||
icon.flipX = true;
|
||||
}
|
||||
GameObject dlekS_ehT = Object.Instantiate(AllMapButton[0].gameObject, __instance.transform);
|
||||
dlekS_ehT.transform.position = AllMapButton[dleksPos].transform.position;
|
||||
dlekS_ehT.transform.SetSiblingIndex(dleksPos + 2);
|
||||
var dlekS_ehT_MapButton = dlekS_ehT.GetComponent<MapSelectButton>();
|
||||
DleksButton = dlekS_ehT_MapButton;
|
||||
|
||||
dlekS_ehT_MapButton.Button.OnClick.RemoveAllListeners();
|
||||
|
||||
dlekS_ehT_MapButton.Button.OnClick.AddListener((Action)(() =>
|
||||
{
|
||||
__instance.SelectMap(__instance.AllMapIcons[0]);
|
||||
|
||||
if (__instance.selectedButton) __instance.selectedButton.Button.SelectButton(false);
|
||||
|
||||
__instance.selectedButton = dlekS_ehT_MapButton;
|
||||
__instance.selectedButton.Button.SelectButton(true);
|
||||
__instance.selectedMapId = 3;
|
||||
|
||||
Main.NormalOptions.MapId = 0;
|
||||
|
||||
__instance.MapImage.sprite = Utils.LoadSprite("EHR.Resources.Images.DleksBanner.png", 100f);
|
||||
__instance.MapName.sprite = Utils.LoadSprite("EHR.Resources.Images.DleksBanner-Wordart.png", 100f);
|
||||
}));
|
||||
|
||||
for (int i = dleksPos; i < AllMapButton.Length; i++) AllMapButton[i].transform.localPosition += new Vector3(0.625f, 0f, 0f);
|
||||
|
||||
if (DleksButton != null)
|
||||
{
|
||||
if (SetDleks)
|
||||
foreach (SpriteRenderer icon in dlekS_ehT_MapButton.MapIcon)
|
||||
{
|
||||
if (icon == null || icon.transform == null) continue;
|
||||
icon.flipX = true;
|
||||
}
|
||||
|
||||
dlekS_ehT_MapButton.Button.OnClick.RemoveAllListeners();
|
||||
|
||||
dlekS_ehT_MapButton.Button.OnClick.AddListener((Action)(() =>
|
||||
{
|
||||
__instance.SelectMap(__instance.AllMapIcons[0]);
|
||||
|
||||
if (__instance.selectedButton) __instance.selectedButton.Button.SelectButton(false);
|
||||
|
||||
DleksButton.Button.SelectButton(true);
|
||||
__instance.selectedButton = DleksButton;
|
||||
__instance.selectedButton = dlekS_ehT_MapButton;
|
||||
__instance.selectedButton.Button.SelectButton(true);
|
||||
__instance.selectedMapId = 3;
|
||||
|
||||
Main.NormalOptions.MapId = 0;
|
||||
|
||||
__instance.MapImage.sprite = Utils.LoadSprite("EHR.Resources.Images.DleksBanner.png", 100f);
|
||||
__instance.MapName.sprite = Utils.LoadSprite("EHR.Resources.Images.DleksBanner-Wordart.png", 100f);
|
||||
}));
|
||||
|
||||
for (int i = dleksPos; i < AllMapButton.Length; i++) AllMapButton[i].transform.localPosition += new Vector3(0.625f, 0f, 0f);
|
||||
|
||||
if (DleksButton != null)
|
||||
{
|
||||
if (SetDleks)
|
||||
{
|
||||
if (__instance.selectedButton) __instance.selectedButton.Button.SelectButton(false);
|
||||
|
||||
DleksButton.Button.SelectButton(true);
|
||||
__instance.selectedButton = DleksButton;
|
||||
__instance.selectedMapId = 3;
|
||||
|
||||
__instance.MapImage.sprite = Utils.LoadSprite("EHR.Resources.Images.DleksBanner.png", 100f);
|
||||
__instance.MapName.sprite = Utils.LoadSprite("EHR.Resources.Images.DleksBanner-Wordart.png", 100f);
|
||||
}
|
||||
else
|
||||
DleksButton.Button.SelectButton(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Submerged Button
|
||||
if (SubmergedCompatibility.Loaded)
|
||||
{
|
||||
GameObject submergedButton = Object.Instantiate(AllMapButton[0].gameObject, __instance.transform);
|
||||
submergedButton.transform.position = AllMapButton[submergedPos].transform.position;
|
||||
submergedButton.transform.SetSiblingIndex(submergedPos + 2);
|
||||
var submergedButton_MapButton = submergedButton.GetComponent<MapSelectButton>();
|
||||
SubmergedButton = submergedButton_MapButton;
|
||||
|
||||
submergedButton_MapButton.Button.OnClick.RemoveAllListeners();
|
||||
|
||||
submergedButton_MapButton.Button.OnClick.AddListener((Action)(() =>
|
||||
{
|
||||
__instance.SelectMap(__instance.AllMapIcons[6]);
|
||||
|
||||
if (__instance.selectedButton) __instance.selectedButton.Button.SelectButton(false);
|
||||
|
||||
__instance.selectedButton = submergedButton_MapButton;
|
||||
__instance.selectedMapId = 6;
|
||||
|
||||
Main.NormalOptions.MapId = 6;
|
||||
|
||||
__instance.MapImage.sprite = Utils.LoadSprite("EHR.Resources.Images.SubmergedBanner.png", 100f);
|
||||
__instance.MapName.sprite = Utils.LoadSprite("EHR.Resources.Images.SubmergedBanner-Wordart.png", 100f);
|
||||
}));
|
||||
|
||||
for (var i = 0; i < submergedPos; i++) AllMapButton[i].transform.localPosition += new Vector3(-0.625f, 0f, 0f);
|
||||
|
||||
if (SubmergedButton != null)
|
||||
{
|
||||
if (SetSubmerged)
|
||||
{
|
||||
if (__instance.selectedButton) __instance.selectedButton.Button.SelectButton(false);
|
||||
|
||||
SubmergedButton.Button.SelectButton(true);
|
||||
__instance.selectedButton = SubmergedButton;
|
||||
__instance.selectedMapId = 6;
|
||||
|
||||
__instance.MapImage.sprite = Utils.LoadSprite("EHR.Resources.Images.SubmergedBanner.png", 100f);
|
||||
__instance.MapName.sprite = Utils.LoadSprite("EHR.Resources.Images.SubmergedBanner-Wordart.png", 100f);
|
||||
}
|
||||
else
|
||||
SubmergedButton.Button.SelectButton(false);
|
||||
}
|
||||
else
|
||||
DleksButton.Button.SelectButton(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,6 +139,7 @@ internal static class CreateOptionsPickerPatch
|
||||
if (__instance.MapName == null) return false;
|
||||
|
||||
if (DleksButton != null) SetDleks = __instance.selectedMapId == 3;
|
||||
if (SubmergedButton != null) SetSubmerged = __instance.selectedMapId == 6;
|
||||
|
||||
if (__instance.selectedMapId == 3)
|
||||
{
|
||||
@@ -103,10 +157,12 @@ internal static class CreateOptionsPickerPatch
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(CreateOptionsPicker), nameof(CreateOptionsPicker.Awake))]
|
||||
private class MenuMapPickerPatch
|
||||
private static class MenuMapPickerPatch
|
||||
{
|
||||
public static void Postfix(CreateOptionsPicker __instance)
|
||||
{
|
||||
if (SubmergedCompatibility.Loaded) return;
|
||||
|
||||
Transform mapPickerTransform = __instance.transform.Find("MapPicker");
|
||||
var mapPickerMenu = mapPickerTransform.Find("Map Picker Menu").GetComponent<MapPickerMenu>();
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ internal static class ChangeRoleSettings
|
||||
RoleTypes.Tracker
|
||||
}.Do(x => Main.NormalOptions.roleOptions.SetRoleRate(x, 0, 0));
|
||||
|
||||
if (Main.NormalOptions.MapId > 5)
|
||||
if (Main.NormalOptions.MapId > 5 && !(Main.NormalOptions.MapId == 6 && SubmergedCompatibility.Loaded))
|
||||
{
|
||||
Logger.SendInGame(GetString("UnsupportedMap"), Color.red);
|
||||
ErrorText.Instance.AddError(ErrorCode.UnsupportedMap);
|
||||
@@ -545,7 +545,7 @@ internal static class StartGameHostPatch
|
||||
|
||||
if (!ShipStatus.Instance)
|
||||
{
|
||||
int index = Mathf.Clamp(GameOptionsManager.Instance.CurrentGameOptions.MapId, 0, Constants.MapNames.Length - 1);
|
||||
int index = GameOptionsManager.Instance.CurrentGameOptions.MapId == 6 && SubmergedCompatibility.Loaded && SubmergedCompatibility.IsSupported(Options.CurrentGameMode) ? 6 : Mathf.Clamp(GameOptionsManager.Instance.CurrentGameOptions.MapId, 0, Constants.MapNames.Length - 1);
|
||||
AUClient.ShipLoadingAsyncHandle = AUClient.ShipPrefabs[index].InstantiateAsync();
|
||||
|
||||
while (!AUClient.ShipLoadingAsyncHandle.IsDone)
|
||||
@@ -560,6 +560,7 @@ internal static class StartGameHostPatch
|
||||
GameObject result = AUClient.ShipLoadingAsyncHandle.Result;
|
||||
ShipStatus.Instance = result.GetComponent<ShipStatus>();
|
||||
AUClient.Spawn(ShipStatus.Instance);
|
||||
Logger.Info($"Successfully spawned ShipStatus for map {GameOptionsManager.Instance.CurrentGameOptions.MapId} ({Constants.MapNames[GameOptionsManager.Instance.CurrentGameOptions.MapId]})", "StartGameHost");
|
||||
}
|
||||
|
||||
try
|
||||
@@ -1048,6 +1049,8 @@ internal static class StartGameHostPatch
|
||||
pc.Data.SendGameData();
|
||||
}
|
||||
|
||||
Logger.Info("Successfully set everyone's data as Disconnected", "StartGameHost");
|
||||
|
||||
LoadingBarManager loadingBarManager = FastDestroyableSingleton<LoadingBarManager>.Instance;
|
||||
yield return loadingBarManager.WaitAndSmoothlyUpdate(90f, 100f, 1f, GetString("LoadingBarText.1"));
|
||||
loadingBarManager.ToggleLoadingBar(false);
|
||||
|
||||
@@ -1074,6 +1074,12 @@ internal static class ReportDeadBodyPatch
|
||||
Notify("TargetDisregarded");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (__instance.Is(CustomRoles.Oblivious))
|
||||
{
|
||||
Notify("AmOblivious");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (Options.SyncButtonMode.GetBool() && target == null)
|
||||
|
||||
@@ -114,6 +114,7 @@ internal abstract class RandomSpawn
|
||||
MapNames.Dleks => new DleksSpawnMap(),
|
||||
MapNames.Airship => new AirshipSpawnMap(),
|
||||
MapNames.Fungle => new FungleSpawnMap(),
|
||||
(MapNames)6 => new SubmergedSpawnMap(),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(Main.CurrentMap), Main.CurrentMap, "Invalid map")
|
||||
};
|
||||
}
|
||||
@@ -282,4 +283,34 @@ internal abstract class RandomSpawn
|
||||
return positions.ToArray().OrderBy(_ => Guid.NewGuid()).Take(1).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
public class SubmergedSpawnMap : SpawnMap
|
||||
{
|
||||
public readonly Dictionary<SystemTypes, Vector2> positions = new()
|
||||
{
|
||||
[(SystemTypes)SubmergedCompatibility.SubmergedSystemTypes.Filtration] = new(8.51f, -21.13f),
|
||||
[SystemTypes.Electrical] = new(10.8f, -27.15f),
|
||||
[SystemTypes.Storage] = new(2.55f, -34.73f),
|
||||
[(SystemTypes)SubmergedCompatibility.SubmergedSystemTypes.LowerLobby] = new(6.53f, -39.44f),
|
||||
[(SystemTypes)SubmergedCompatibility.SubmergedSystemTypes.Ballast] = new(-8.26f, -39.84f),
|
||||
[SystemTypes.Security] = new(-4.23f, -33.38f),
|
||||
[SystemTypes.Engine] = new(-12.58f, -27.83f),
|
||||
[SystemTypes.Admin] = new(-9.96f, 10.95f),
|
||||
[(SystemTypes)SubmergedCompatibility.SubmergedSystemTypes.Observatory] = new(-12.39f, 17.78f),
|
||||
[SystemTypes.Lounge] = new(-6.43f, 14.11f),
|
||||
[SystemTypes.MeetingRoom] = new(-1.85f, 12.32f),
|
||||
[SystemTypes.Cafeteria] = new(-8.57f, 25.47f),
|
||||
[(SystemTypes)SubmergedCompatibility.SubmergedSystemTypes.Research] = new(0.96f, 29.84f),
|
||||
[SystemTypes.Medical] = new(6.17f, 31.38f),
|
||||
[SystemTypes.Comms] = new(11.03f, 23.53f),
|
||||
[(SystemTypes)SubmergedCompatibility.SubmergedSystemTypes.UpperLobby] = new(7.72f, 8.66f)
|
||||
};
|
||||
|
||||
public override Dictionary<SystemTypes, Vector2> Positions => positions;
|
||||
|
||||
protected override KeyValuePair<SystemTypes, Vector2> GetLocation()
|
||||
{
|
||||
return positions.ToArray().OrderBy(_ => Guid.NewGuid()).Take(1).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -378,6 +378,8 @@ public static class SabotageSystemTypeRepairDamagePatch
|
||||
newReader.Recycle();
|
||||
}
|
||||
|
||||
if (SubmergedCompatibility.IsSubmerged()) return CheckSabotage(__instance, player, systemTypes);
|
||||
|
||||
if (Options.EnableCustomSabotages.GetBool())
|
||||
{
|
||||
if (Options.EnableGrabOxygenMaskCustomSabotage.GetBool() && systemTypes == SystemTypes.Comms)
|
||||
@@ -529,7 +531,7 @@ public static class SecurityCameraPatch
|
||||
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.RepairCriticalSabotages))]
|
||||
internal static class ShipStatusRepairCriticalSabotagesPatch
|
||||
{
|
||||
public static void Postfix(ShipStatus __instance)
|
||||
public static void Postfix()
|
||||
{
|
||||
CustomSabotage.Reset();
|
||||
}
|
||||
|
||||
@@ -94,6 +94,8 @@ internal static class RepairSystemPatch
|
||||
if ((Options.CurrentGameMode != CustomGameMode.Standard || Options.DisableSabotage.GetBool()) && systemType == SystemTypes.Sabotage) return false;
|
||||
if (player.Is(CustomRoles.Fool) && systemType is SystemTypes.Comms or SystemTypes.Electrical) return false;
|
||||
|
||||
if (SubmergedCompatibility.IsSubmerged() && systemType is not (SystemTypes.Electrical or SystemTypes.Comms)) return true;
|
||||
|
||||
switch (player.GetCustomRole())
|
||||
{
|
||||
case CustomRoles.SabotageMaster:
|
||||
@@ -171,7 +173,8 @@ internal static class RepairSystemPatch
|
||||
|
||||
break;
|
||||
}
|
||||
case SystemTypes.Sabotage when AmongUsClient.Instance.NetworkMode != NetworkModes.FreePlay: { return SabotageSystemTypeRepairDamagePatch.CheckSabotage(null, player, systemType); }
|
||||
case SystemTypes.Sabotage when AmongUsClient.Instance.NetworkMode != NetworkModes.FreePlay:
|
||||
return SabotageSystemTypeRepairDamagePatch.CheckSabotage(null, player, systemType);
|
||||
case SystemTypes.Security when amount == 1:
|
||||
{
|
||||
bool camerasDisabled = (MapNames)Main.NormalOptions.MapId switch
|
||||
@@ -468,6 +471,7 @@ internal static class ShipStatusSerializePatch
|
||||
{
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (initialState) return;
|
||||
if (SubmergedCompatibility.IsSubmerged()) return;
|
||||
|
||||
var cancel = false;
|
||||
|
||||
|
||||
@@ -287,6 +287,7 @@ public static class TextBoxPatch
|
||||
catch { }
|
||||
}
|
||||
|
||||
#if !ANDROID
|
||||
[HarmonyPatch(nameof(TextBoxTMP.Update))]
|
||||
[HarmonyPrefix]
|
||||
public static bool UpdatePatch(TextBoxTMP __instance)
|
||||
@@ -310,6 +311,7 @@ public static class TextBoxPatch
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
[HarmonyPatch(nameof(TextBoxTMP.IsCharAllowed))]
|
||||
[HarmonyPrefix]
|
||||
|
||||
@@ -52,6 +52,42 @@ internal static class CanUseVentPatch
|
||||
// always true for engineer-based roles
|
||||
couldUse = playerControl.CanUseImpostorVentButton() || (pc.Role.Role == RoleTypes.Engineer && pc.Role.CanUse(__instance.CastFast<IUsable>()));
|
||||
|
||||
if (SubmergedCompatibility.IsSubmerged()) // From TheOtherRoles
|
||||
{
|
||||
// As submerged does, only change stuff for vents 9 and 14 of submerged. Code partially provided by AlexejheroYTB
|
||||
if (SubmergedCompatibility.GetInTransition())
|
||||
{
|
||||
__result = float.MaxValue;
|
||||
return canUse = couldUse = false;
|
||||
}
|
||||
|
||||
switch (__instance.Id)
|
||||
{
|
||||
case 9: // Cannot enter vent 9 (Engine Room Exit Only Vent)!
|
||||
{
|
||||
if (playerControl.inVent) break;
|
||||
__result = float.MaxValue;
|
||||
return canUse = couldUse = false;
|
||||
}
|
||||
case 14: // Lower Central
|
||||
{
|
||||
__result = float.MaxValue;
|
||||
couldUse = couldUse && !pc.IsDead && (playerControl.CanMove || playerControl.inVent);
|
||||
canUse = couldUse;
|
||||
|
||||
if (canUse)
|
||||
{
|
||||
Vector3 center = playerControl.Collider.bounds.center;
|
||||
Vector3 position = __instance.transform.position;
|
||||
__result = Vector2.Distance(center, position);
|
||||
canUse &= __result <= __instance.UsableDistance;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
canUse = couldUse;
|
||||
// Not available if custom roles are not available
|
||||
if (!canUse) return false;
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 135 KiB |
@@ -929,6 +929,7 @@
|
||||
"LadderDeath": "Fall From Ladders",
|
||||
"LadderDeathChance": "Fall To Death Chance",
|
||||
"GuesserDoesntDieOnMisguess": "<color=#f3e304>Guesser Doesn't Die on Misguess</color>",
|
||||
"CanGuessDuringDiscussionTime": "<color=#f3e304>Guessers Can Guess During Discussion Time</color>",
|
||||
"YouCanGuessTitle": "<#00ffff>You can guess!</color>",
|
||||
"YouCanGuess": "Use the <b>/bt [player id] [role]</b> command to guess someone's role. You can see everyone's IDs next to their name, or type <b>/id</b>.",
|
||||
"DisableTasks": "Disable Tasks",
|
||||
@@ -1819,6 +1820,7 @@
|
||||
"PlayerWasRevived": "The player whose body you tried to report was revived",
|
||||
"HypnosisNoMeeting": "Everyone is in hypnosis, no meeting calls are allowed currently",
|
||||
"TargetDisregarded": "The player whose body you tried to report is <#FF6347>Disregarded</color>",
|
||||
"AmOblivious": "You are <color=#424242>Oblivious</color>, meaning you cannot report bodies",
|
||||
"ShipHasNoMoreMeetingsLeft": "The ship has no more emergency meetings left",
|
||||
"UnreportableBody": "This body is unreportable due to a role-specific action",
|
||||
"CheckMurderFail": "<#ff0000>The murder was canceled due to the following reason:\\n</color>",
|
||||
@@ -2110,6 +2112,7 @@
|
||||
"GodNoticeAlive": "During the meeting, each player felt a revelation from heaven, and it turned out that God is still alive!",
|
||||
"WorkaholicAdviceAlive": "It's not recommended to kill or vote <b>{0}</b> out. Doing so will help them finish their tasks quicker.",
|
||||
"GuessDead": "Sorry, but it's impossible to guess roles after your death",
|
||||
"GuessDuringDiscussion": "According to the host's settings, you cannot guess during discussion time.",
|
||||
"GuessSuperStar": "The Super Star can't be guessed.... you thought it would be that easy, right?",
|
||||
"GuessNotifiedBait": "Bait can't be guessed because it was announced, you thought it would be that easy, right?",
|
||||
"GuessGM": "Guessing the GM is impossible because they're already dead.... And why would you do that to the poor Host?",
|
||||
@@ -2884,7 +2887,7 @@
|
||||
"ERR-000-804-1": "EHR does not support the Vanilla HnS, so unloaded.",
|
||||
"ERR-001-000-3": "Main dictionary has duplicated keys.",
|
||||
"ERR-002-000-3": "Your Among Us version is outdated.",
|
||||
"ERR-002-000-2": "You're using an unsupported map, i.e. Submerged.",
|
||||
"ERR-002-000-1": "This game mode is incompatible with the current map.",
|
||||
"FixBlackScreenWaitForDead": "Everyone is alive, and the black screen fix requires a ghost, so it will wait until someone dies.",
|
||||
"DraftNotEnoughRoles": "There are not enough roles enabled to choose from, so drafting cannot be started. Please enable more roles and try again.",
|
||||
"DraftStart": "<size=90%>Drafting has started! You now have a chance to pick a role from the list below if you'd like to get one of them for the next game. The roles you get to choose from, with their indexes, are:</size>\\n\\n{0}\\n\\n<size=90%>Chat commands to use:</size>\\n- Pick role: <b>/draft [index]</b>\\n- View description of role: <b>/dd [index]</b>\\nReplace [index] with the number of the role you want to pick. Example: <b>/draft 4</b>\\n<size=70%>If you don't pick a role, you get a random one like you normally would.</size>",
|
||||
@@ -5153,6 +5156,7 @@
|
||||
"Bedwars.BedStatus.Broken": "<u><#ff0000>BED DESTROYED!</color></u>\\n<size=80%>You will no longer respawn!</size>",
|
||||
"Bedwars.BedStatus.EnemyBroken": "{0}'s bed has been destroyed!",
|
||||
"Bedwars.HudText.GracePeriodLeft": "Grace period ends\\nin <#ffff44>{0}</color> seconds",
|
||||
"BedWars.InventorySlotsOption": "Number of Inventory Slots",
|
||||
"BedWars.SpeedPotionDurationOption": "Speed Potion Duration",
|
||||
"BedWars.InvisPotionDurationOption": "Invisibility Potion Duration",
|
||||
"BedWars.ReviveTimeOption": "Revive Time",
|
||||
@@ -5216,6 +5220,7 @@
|
||||
"Quiz.Notify.FFAOngoing": "<size=80%><#ffff00><u>Kill everyone</u> and survive</color>\\nHint: Someone is in {0}\\n<#ffa500>{1}</color></size>",
|
||||
"Quiz.Notify.FFASpectating": "<size=80%><#00ffff>Spectate the chaos!</color>\\n<#00a5ff>{1}</color></size>",
|
||||
"Quiz.Notify.CorrectAnswerNum": "<size=80%>You got {0}/{1} questions correct! The required amount was {2}.</size>",
|
||||
"Quiz.Suffix.Invisible": "You cannot see where other people go\\nOther people cannot see where you go",
|
||||
"Quiz.TaskBarText": "---- GAME DATA ----\\n\\nDifficulty: {0}\\nRound: {1}\\nQuestion: {2}\\n\\nNumber of correct answers\\nfrom everyone so far:\\n\\n{3}",
|
||||
"Quiz.EndResults.CorrectAnswerNum": "Correct Answers: ",
|
||||
"Quiz.Questions.Test.0": "Which map are we on?",
|
||||
@@ -9063,6 +9068,7 @@
|
||||
"RememberedLover": "You remembered you were a Lover!",
|
||||
"RememberButtonText": "Remember",
|
||||
"CanRememberCrewPower": "Can Remember <#8cffff>Crewmate</color> <#fbff00>Power</color> Roles",
|
||||
"ReportBodyAfterRemember": "After remembering a role by reporting, report the body",
|
||||
"IncompatibleNeutralMode": "If neutral is incompatible, turn into",
|
||||
"ImmuneToAttacksWhenTasksDone": "Immune to attacks on task completion",
|
||||
"TwisterCooldown": "Twist Cooldown",
|
||||
@@ -9686,6 +9692,14 @@
|
||||
"AutoGMRotationStatusText.NextGM": "Next",
|
||||
"AutoGMRotationStatusText.GMPoll": "Player Vote (/gmpoll)",
|
||||
"AutoGMRotationStatusText.CooldownTimer": "Jumping to the next game mode on the list in <b>{0}</b> seconds",
|
||||
"SubmergedRoomName.128": "Research",
|
||||
"SubmergedRoomName.129": "Observatory",
|
||||
"SubmergedRoomName.130": "Upper Central",
|
||||
"SubmergedRoomName.131": "Upper Lobby",
|
||||
"SubmergedRoomName.132": "Filtration",
|
||||
"SubmergedRoomName.133": "Ballast",
|
||||
"SubmergedRoomName.134": "Lower Central",
|
||||
"SubmergedRoomName.135": "Lower Lobby",
|
||||
"ModLanguage": "Mod Language",
|
||||
"UseGameLanguage": "Use Game Language",
|
||||
"Hungarian": "Hungarian",
|
||||
|
||||
@@ -49,7 +49,7 @@ public class Allergic : IAddon
|
||||
|
||||
public static void OnFixedUpdate(PlayerControl pc)
|
||||
{
|
||||
if (Main.HasJustStarted || ExileController.Instance) return;
|
||||
if (Main.HasJustStarted || !Main.IntroDestroyed || ExileController.Instance || AntiBlackout.SkipTasks) return;
|
||||
|
||||
if (!AllergicPlayers.TryGetValue(pc.PlayerId, out byte targetId)) return;
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ public class CameraMan : RoleBase
|
||||
MapNames.Dleks => new(-13.5f, -5.5f),
|
||||
MapNames.Airship => new(5.8f, -10.8f),
|
||||
MapNames.Fungle => new(9.5f, 1.2f),
|
||||
(MapNames)6 => new(-4.23f, -33.38f),
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ public class Abyssbringer : RoleBase
|
||||
private int Count;
|
||||
|
||||
public override bool IsEnable => On;
|
||||
public static bool ShouldDespawnCNOOnMeeting => (DespawnMode)BlackHoleDespawnMode.GetValue() == DespawnMode.AfterMeeting;
|
||||
|
||||
public override void SetupCustomOption()
|
||||
{
|
||||
@@ -117,7 +118,7 @@ public class Abyssbringer : RoleBase
|
||||
|
||||
public override void OnReportDeadBody()
|
||||
{
|
||||
if ((DespawnMode)BlackHoleDespawnMode.GetValue() == DespawnMode.AfterMeeting)
|
||||
if (ShouldDespawnCNOOnMeeting)
|
||||
{
|
||||
Loop.Times(BlackHoles.Count, i => Utils.SendRPC(CustomRPC.SyncRoleData, AbyssbringerId, 3, i));
|
||||
|
||||
|
||||
@@ -75,9 +75,9 @@ public class Wiper : RoleBase
|
||||
|
||||
switch (Main.CurrentMap)
|
||||
{
|
||||
case MapNames.Skeld or MapNames.Dleks when room.RoomId == SystemTypes.Cafeteria: { return true; }
|
||||
case MapNames.Skeld or MapNames.Dleks when room.RoomId == SystemTypes.Cafeteria:
|
||||
return true;
|
||||
case MapNames.MiraHQ:
|
||||
{
|
||||
switch (MeetingStates.FirstMeeting, room.RoomId)
|
||||
{
|
||||
case (true, SystemTypes.Launchpad):
|
||||
@@ -86,9 +86,7 @@ public class Wiper : RoleBase
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MapNames.Polus:
|
||||
{
|
||||
switch (MeetingStates.FirstMeeting, room.RoomId)
|
||||
{
|
||||
case (true, SystemTypes.Dropship):
|
||||
@@ -97,8 +95,13 @@ public class Wiper : RoleBase
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MapNames.Fungle when !MeetingStates.FirstMeeting && room.RoomId == SystemTypes.MeetingRoom: { return true; }
|
||||
case MapNames.Fungle when !MeetingStates.FirstMeeting && room.RoomId == SystemTypes.MeetingRoom:
|
||||
return true;
|
||||
default:
|
||||
if (SubmergedCompatibility.IsSubmerged() && room.RoomId is (SystemTypes)SubmergedCompatibility.SubmergedSystemTypes.LowerCentral or (SystemTypes)SubmergedCompatibility.SubmergedSystemTypes.UpperCentral)
|
||||
return true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return room.RoomId is SystemTypes.Outside or SystemTypes.Hallway or SystemTypes.Ventilation || room.RoomId.ToString().Contains("Decontamination");
|
||||
|
||||
@@ -21,6 +21,7 @@ public class Amnesiac : RoleBase
|
||||
public static OptionItem CanVent;
|
||||
private static OptionItem VentCooldown;
|
||||
private static OptionItem VentDuration;
|
||||
private static OptionItem ReportBodyAfterRemember;
|
||||
|
||||
private static readonly CustomRoles[] AmnesiacIncompatibleNeutralMode =
|
||||
[
|
||||
@@ -69,6 +70,9 @@ public class Amnesiac : RoleBase
|
||||
VentDuration = new FloatOptionItem(Id + 15, "MaxInVentTime", new(0f, 180f, 0.5f), 5f, TabGroup.NeutralRoles)
|
||||
.SetParent(CanVent)
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
|
||||
ReportBodyAfterRemember = new BooleanOptionItem(Id + 16, "ReportBodyAfterRemember", true, TabGroup.NeutralRoles)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Amnesiac]);
|
||||
}
|
||||
|
||||
public override void Init()
|
||||
@@ -123,7 +127,7 @@ public class Amnesiac : RoleBase
|
||||
if (RememberMode.GetValue() == 0)
|
||||
{
|
||||
RememberRole(reporter, target.Object);
|
||||
return false;
|
||||
return ReportBodyAfterRemember.GetBool();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -78,6 +78,7 @@ internal class Bargainer : RoleBase
|
||||
get
|
||||
{
|
||||
var mapName = Main.CurrentMap.ToString();
|
||||
if (SubmergedCompatibility.IsSubmerged()) mapName = "Submerged";
|
||||
IEnumerable<KeyValuePair<string, Vector2>> devices = DisableDevice.DevicePos.SkipWhile(x => !x.Key.StartsWith(mapName)).TakeWhile(x => x.Key.StartsWith(mapName));
|
||||
return devices.Select(x => x.Value);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,8 @@ internal class Chemist : RoleBase
|
||||
[MapNames.Polus] = SystemTypes.Dropship,
|
||||
[MapNames.Dleks] = SystemTypes.Reactor,
|
||||
[MapNames.Airship] = SystemTypes.GapRoom,
|
||||
[MapNames.Fungle] = SystemTypes.Reactor
|
||||
[MapNames.Fungle] = SystemTypes.Reactor,
|
||||
[(MapNames)6] = (SystemTypes)SubmergedCompatibility.SubmergedSystemTypes.Ballast
|
||||
};
|
||||
|
||||
private static readonly Dictionary<Factory, Dictionary<string, (List<(int Count, Item Item)> Ingredients, List<(int Count, Item Item)> Results)>> Processes = new()
|
||||
|
||||
@@ -38,7 +38,7 @@ internal class Mario : RoleBase
|
||||
{
|
||||
On = true;
|
||||
MarioVentCount[playerId] = 0;
|
||||
MarioVentNumWin = MapWinCounts[Main.CurrentMap].GetInt();
|
||||
MarioVentNumWin = MapWinCounts[SubmergedCompatibility.IsSubmerged() ? MapNames.Airship : Main.CurrentMap].GetInt();
|
||||
}
|
||||
|
||||
public override void Init()
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using AmongUs.GameOptions;
|
||||
using EHR.Crewmate;
|
||||
using EHR.Modules;
|
||||
@@ -142,7 +141,7 @@ public class Pelican : RoleBase
|
||||
3 => new(27f, 3.3f), // dlekS ehT
|
||||
4 => new(-16.8f, -6.2f), // Airship
|
||||
5 => new(9.6f, 23.2f), // The Fungle
|
||||
_ => throw new ArgumentOutOfRangeException(Main.NormalOptions.MapId.ToString(), "Unsupported map")
|
||||
_ => new(50f, 50f) // Default position if the map is not recognized
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ public class RoomRusher : RoleBase
|
||||
AllRooms.Remove(SystemTypes.Outside);
|
||||
AllRooms.Remove(SystemTypes.Ventilation);
|
||||
AllRooms.RemoveWhere(x => x.ToString().Contains("Decontamination"));
|
||||
if (SubmergedCompatibility.IsSubmerged()) AllRooms.RemoveWhere(x => (byte)x > 135);
|
||||
|
||||
Map = RandomSpawn.SpawnMap.GetSpawnMap();
|
||||
|
||||
@@ -94,6 +95,7 @@ public class RoomRusher : RoleBase
|
||||
MapNames.Polus => afterMeeting ? SystemTypes.Office : SystemTypes.Dropship,
|
||||
MapNames.Airship => SystemTypes.MainHall,
|
||||
MapNames.Fungle => SystemTypes.Dropship,
|
||||
(MapNames)6 => (SystemTypes)SubmergedCompatibility.SubmergedSystemTypes.UpperCentral,
|
||||
_ => throw new ArgumentOutOfRangeException(map.ToString(), "Invalid map")
|
||||
};
|
||||
|
||||
@@ -112,20 +114,20 @@ public class RoomRusher : RoleBase
|
||||
{
|
||||
MapNames.MiraHQ => previous is SystemTypes.Laboratory or SystemTypes.Reactor ^ RoomGoal is SystemTypes.Laboratory or SystemTypes.Reactor,
|
||||
MapNames.Polus => previous == SystemTypes.Specimens || RoomGoal == SystemTypes.Specimens,
|
||||
(MapNames)6 => (previous == (SystemTypes)SubmergedCompatibility.SubmergedSystemTypes.Ballast) ^ (RoomGoal == (SystemTypes)SubmergedCompatibility.SubmergedSystemTypes.Ballast),
|
||||
_ => false
|
||||
};
|
||||
|
||||
if (involvesDecontamination)
|
||||
{
|
||||
bool polus = map == MapNames.Polus;
|
||||
|
||||
int decontaminationTime = Options.ChangeDecontaminationTime.GetBool()
|
||||
? polus
|
||||
? Options.DecontaminationTimeOnPolus.GetInt()
|
||||
: Options.DecontaminationTimeOnMiraHQ.GetInt()
|
||||
: 3;
|
||||
? map == MapNames.Polus
|
||||
? Options.DecontaminationTimeOnPolus.GetInt() + Options.DecontaminationDoorOpenTimeOnPolus.GetInt()
|
||||
: Options.DecontaminationTimeOnMiraHQ.GetInt() + Options.DecontaminationDoorOpenTimeOnMiraHQ.GetInt()
|
||||
: 6;
|
||||
|
||||
time += decontaminationTime * (polus ? 2 : 4);
|
||||
if (SubmergedCompatibility.IsSubmerged()) decontaminationTime = 3;
|
||||
time += decontaminationTime + 3;
|
||||
}
|
||||
|
||||
switch (map)
|
||||
@@ -133,12 +135,22 @@ public class RoomRusher : RoleBase
|
||||
case MapNames.Fungle when RoomGoal == SystemTypes.Laboratory || previous == SystemTypes.Laboratory:
|
||||
time += (int)(8 / speed);
|
||||
break;
|
||||
case MapNames.Polus when (RoomGoal == SystemTypes.Laboratory && previous is not SystemTypes.Storage and not SystemTypes.Specimens) || (previous == SystemTypes.Laboratory && RoomGoal is not SystemTypes.Office and not SystemTypes.Storage and not SystemTypes.Electrical):
|
||||
case MapNames.Polus when (RoomGoal == SystemTypes.Laboratory && previous is not SystemTypes.Storage and not SystemTypes.Specimens and not SystemTypes.Office) || (previous == SystemTypes.Laboratory && RoomGoal is not SystemTypes.Office and not SystemTypes.Storage and not SystemTypes.Electrical and not SystemTypes.Specimens):
|
||||
time -= (int)(5 * speed);
|
||||
break;
|
||||
case MapNames.Airship when previous == SystemTypes.GapRoom:
|
||||
time *= RoomGoal switch
|
||||
{
|
||||
SystemTypes.MeetingRoom => 6,
|
||||
SystemTypes.Brig or SystemTypes.VaultRoom or SystemTypes.Records or SystemTypes.Showers or SystemTypes.Lounge => 3,
|
||||
SystemTypes.Engine or SystemTypes.CargoBay or SystemTypes.Medical => 2,
|
||||
_ => 1
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
TimeLeft = Math.Max((int)Math.Round(time * GlobalTimeMultiplier.GetFloat()), 5);
|
||||
var maxTime = (int)Math.Ceiling(32 / speed);
|
||||
TimeLeft = Math.Clamp((int)Math.Round(time * GlobalTimeMultiplier.GetFloat()), 6, maxTime);
|
||||
Logger.Info($"Goal = from: {Translator.GetString(previous.ToString())} ({previous}), to: {Translator.GetString(RoomGoal.ToString())} ({RoomGoal}) - Time: {TimeLeft} ({map})", "Room Rusher");
|
||||
LocateArrow.RemoveAllTarget(RoomRusherId);
|
||||
LocateArrow.Add(RoomRusherId, goalPos);
|
||||
|
||||
@@ -0,0 +1,287 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using BepInEx;
|
||||
using BepInEx.Unity.IL2CPP;
|
||||
using EHR.Patches;
|
||||
using HarmonyLib;
|
||||
using Il2CppInterop.Runtime.InteropTypes;
|
||||
|
||||
namespace EHR;
|
||||
|
||||
// https://github.com/eDonnes124/Town-Of-Us-R/tree/master/source/Patches/SubmergedCompatibility.cs
|
||||
|
||||
public static class SubmergedCompatibility
|
||||
{
|
||||
/*
|
||||
public static class Classes
|
||||
{
|
||||
public const string ElevatorMover = "ElevatorMover";
|
||||
}
|
||||
*/
|
||||
|
||||
public const string SubmergedGuid = "Submerged";
|
||||
private const ShipStatus.MapType SubmergedMapType = (ShipStatus.MapType)6;
|
||||
|
||||
// public static SemanticVersioning.Version Version { get; private set; }
|
||||
public static bool Loaded { get; set; }
|
||||
private static BasePlugin Plugin { get; set; }
|
||||
private static Assembly Assembly { get; set; }
|
||||
private static Type[] Types { get; set; }
|
||||
// public static Dictionary<string, Type> InjectedTypes { get; private set; }
|
||||
|
||||
/*
|
||||
private static MonoBehaviour _submarineStatus;
|
||||
public static MonoBehaviour SubmarineStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!Loaded) return null;
|
||||
|
||||
if (_submarineStatus is null || _submarineStatus.WasCollected || !_submarineStatus || _submarineStatus == null)
|
||||
{
|
||||
if (ShipStatus.Instance is null || ShipStatus.Instance == null || !ShipStatus.Instance || ShipStatus.Instance.WasCollected)
|
||||
return _submarineStatus = null;
|
||||
|
||||
if (ShipStatus.Instance.Type == SUBMERGED_MAP_TYPE)
|
||||
return _submarineStatus = ShipStatus.Instance.GetComponent(Il2CppType.From(SubmarineStatusType))?.TryCast(SubmarineStatusType) as MonoBehaviour;
|
||||
|
||||
return _submarineStatus = null;
|
||||
}
|
||||
|
||||
return _submarineStatus;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
private static Type SubmarineStatusType;
|
||||
// private static MethodInfo CalculateLightRadiusMethod;
|
||||
|
||||
// private static MethodInfo RpcRequestChangeFloorMethod;
|
||||
// private static Type FloorHandlerType;
|
||||
// private static MethodInfo GetFloorHandlerMethod;
|
||||
|
||||
private static Type SubmarinePlayerFloorSystemType;
|
||||
private static MethodInfo SubmarinePlayerFloorSystemInstanceGetter;
|
||||
private static MethodInfo ChangePlayerFloorStateMethod;
|
||||
|
||||
private static Type VentPatchDataType;
|
||||
private static PropertyInfo InTransitionField;
|
||||
|
||||
// private static Type CustomTaskTypesType;
|
||||
// private static FieldInfo RetrieveOxigenMaskField;
|
||||
// public static TaskTypes RetrieveOxygenMask;
|
||||
// private static Type SubmarineOxygenSystemType;
|
||||
// private static PropertyInfo SubmarineOxygenSystemInstanceField;
|
||||
// private static MethodInfo RepairDamageMethod;
|
||||
|
||||
private static Type SubmergedExileController;
|
||||
private static MethodInfo SubmergedExileWrapUpMethod;
|
||||
|
||||
private static Type SubmarineElevator;
|
||||
|
||||
private static MethodInfo GetInElevator;
|
||||
|
||||
// private static MethodInfo GetMovementStageFromTime;
|
||||
private static FieldInfo GetSubElevatorSystem;
|
||||
|
||||
// private static Type ElevatorConsole;
|
||||
// private static MethodInfo CanUse;
|
||||
|
||||
private static Type SubmarineElevatorSystem;
|
||||
private static FieldInfo UpperDeckIsTargetFloor;
|
||||
|
||||
private static FieldInfo SubmergedInstance;
|
||||
private static FieldInfo SubmergedElevators;
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
Loaded = IL2CPPChainloader.Instance.Plugins.TryGetValue(SubmergedGuid, out PluginInfo plugin);
|
||||
if (!Loaded) return;
|
||||
|
||||
Plugin = plugin!.Instance as BasePlugin;
|
||||
// Version = plugin.Metadata.Version;
|
||||
|
||||
Assembly = Plugin!.GetType().Assembly;
|
||||
Types = AccessTools.GetTypesFromAssembly(Assembly);
|
||||
|
||||
AccessTools.PropertyGetter(Types.FirstOrDefault(t => t.Name == "ComponentExtensions"), "RegisteredTypes")
|
||||
.Invoke(null, []);
|
||||
|
||||
SubmarineStatusType = Types.First(t => t.Name == "SubmarineStatus");
|
||||
SubmergedInstance = AccessTools.Field(SubmarineStatusType, "instance");
|
||||
SubmergedElevators = AccessTools.Field(SubmarineStatusType, "elevators");
|
||||
|
||||
// CalculateLightRadiusMethod = AccessTools.Method(SubmarineStatusType, "CalculateLightRadius");
|
||||
|
||||
// FloorHandlerType = Types.First(t => t.Name == "FloorHandler");
|
||||
// GetFloorHandlerMethod = AccessTools.Method(FloorHandlerType, "GetFloorHandler", [typeof(PlayerControl)]);
|
||||
// RpcRequestChangeFloorMethod = AccessTools.Method(FloorHandlerType, "RpcRequestChangeFloor");
|
||||
|
||||
SubmarinePlayerFloorSystemType = Types.First(t => t.Name == "SubmarinePlayerFloorSystem");
|
||||
SubmarinePlayerFloorSystemInstanceGetter = AccessTools.PropertyGetter(SubmarinePlayerFloorSystemType, "Instance");
|
||||
ChangePlayerFloorStateMethod = AccessTools.Method(SubmarinePlayerFloorSystemType, "ChangePlayerFloorState");
|
||||
|
||||
VentPatchDataType = Types.First(t => t.Name == "VentPatchData");
|
||||
InTransitionField = AccessTools.Property(VentPatchDataType, "InTransition");
|
||||
|
||||
// CustomTaskTypesType = Types.First(t => t.Name == "CustomTaskTypes");
|
||||
// RetrieveOxigenMaskField = AccessTools.Field(CustomTaskTypesType, "RetrieveOxygenMask");
|
||||
// var retTaskType = AccessTools.Field(CustomTaskTypesType, "taskType");
|
||||
// RetrieveOxygenMask = (TaskTypes)retTaskType.GetValue(RetrieveOxigenMaskField.GetValue(null))!;
|
||||
|
||||
// SubmarineOxygenSystemType = Types.First(t => t.Name == "SubmarineOxygenSystem");
|
||||
// SubmarineOxygenSystemInstanceField = AccessTools.Property(SubmarineOxygenSystemType, "Instance");
|
||||
// RepairDamageMethod = AccessTools.Method(SubmarineOxygenSystemType, "RepairDamage");
|
||||
SubmergedExileController = Types.First(t => t.Name == "SubmergedExileController");
|
||||
SubmergedExileWrapUpMethod = AccessTools.Method(SubmergedExileController, "WrapUpAndSpawn");
|
||||
|
||||
SubmarineElevator = Types.First(t => t.Name == "SubmarineElevator");
|
||||
GetInElevator = AccessTools.Method(SubmarineElevator, "GetInElevator", [typeof(PlayerControl)]);
|
||||
// GetMovementStageFromTime = AccessTools.Method(SubmarineElevator, "GetMovementStageFromTime");
|
||||
GetSubElevatorSystem = AccessTools.Field(SubmarineElevator, "system");
|
||||
|
||||
// ElevatorConsole = Types.First(t => t.Name == "ElevatorConsole");
|
||||
// CanUse = AccessTools.Method(ElevatorConsole, "CanUse");
|
||||
|
||||
SubmarineElevatorSystem = Types.First(t => t.Name == "SubmarineElevatorSystem");
|
||||
UpperDeckIsTargetFloor = AccessTools.Field(SubmarineElevatorSystem, "upperDeckIsTargetFloor");
|
||||
var harmony = new Harmony("ehr.submerged.patch");
|
||||
MethodInfo exilerolechangePostfix = SymbolExtensions.GetMethodInfo(() => WrapUpPatch());
|
||||
harmony.Patch(SubmergedExileWrapUpMethod, null, new HarmonyMethod(exilerolechangePostfix));
|
||||
/*
|
||||
var canusePrefix = SymbolExtensions.GetMethodInfo(() => CanUsePrefix());
|
||||
var canusePostfix = SymbolExtensions.GetMethodInfo(() => CanUsePostfix());
|
||||
_harmony.Patch(CanUse, new HarmonyMethod(canusePrefix), new HarmonyMethod(canusePostfix));
|
||||
*/
|
||||
}
|
||||
|
||||
private static void WrapUpPatch()
|
||||
{
|
||||
try { ExileControllerWrapUpPatch.WrapUpPostfix(ExileControllerWrapUpPatch.LastExiled); }
|
||||
finally { ExileControllerWrapUpPatch.WrapUpFinalizer(); }
|
||||
}
|
||||
|
||||
public static void CheckOutOfBoundsElevator(PlayerControl player)
|
||||
{
|
||||
if (!Loaded) return;
|
||||
if (!IsSubmerged()) return;
|
||||
|
||||
Tuple<bool, object> elevator = GetPlayerElevator(player);
|
||||
if (!elevator.Item1) return;
|
||||
var currentFloor = (bool)UpperDeckIsTargetFloor.GetValue(GetSubElevatorSystem.GetValue(elevator.Item2))!; //true is top, false is bottom
|
||||
bool playerFloor = player.transform.position.y > -7f; //true is top, false is bottom
|
||||
|
||||
if (currentFloor != playerFloor)
|
||||
ChangeFloor(player.PlayerId, currentFloor);
|
||||
}
|
||||
|
||||
/*
|
||||
public static void MoveDeadPlayerElevator(PlayerControl player)
|
||||
{
|
||||
if (!isSubmerged()) return;
|
||||
Tuple<bool, object> elevator = GetPlayerElevator(player);
|
||||
if (!elevator.Item1) return;
|
||||
|
||||
int MovementStage = (int)GetMovementStageFromTime.Invoke(elevator.Item2, null)!;
|
||||
if (MovementStage >= 5)
|
||||
{
|
||||
//Fade to clear
|
||||
bool topfloortarget = (bool)UpperDeckIsTargetFloor.GetValue(getSubElevatorSystem.GetValue(elevator.Item2))!; //true is top, false is bottom
|
||||
bool topintendedtarget = player.transform.position.y > -7f; //true is top, false is bottom
|
||||
if (topfloortarget != topintendedtarget)
|
||||
{
|
||||
ChangeFloor(!topintendedtarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
private static Tuple<bool, object> GetPlayerElevator(PlayerControl player)
|
||||
{
|
||||
if (!IsSubmerged()) return Tuple.Create(false, (object)null);
|
||||
// ReSharper disable once RedundantAssignment
|
||||
IList elevatorlist = CreateList(SubmarineElevator);
|
||||
elevatorlist = (IList)SubmergedElevators.GetValue(SubmergedInstance.GetValue(null))!;
|
||||
foreach (object elevator in elevatorlist)
|
||||
if ((bool)GetInElevator.Invoke(elevator, [player])!)
|
||||
return Tuple.Create(true, elevator);
|
||||
|
||||
return Tuple.Create(false, (object)null);
|
||||
}
|
||||
|
||||
public static void ChangeFloor(byte playerId, bool toUpper)
|
||||
{
|
||||
if (!Loaded) return;
|
||||
ChangePlayerFloorStateMethod.Invoke(SubmarinePlayerFloorSystemInstanceGetter.Invoke(null, null), [playerId, toUpper]);
|
||||
}
|
||||
|
||||
public static bool GetInTransition()
|
||||
{
|
||||
if (!Loaded) return false;
|
||||
return (bool)InTransitionField.GetValue(null)!;
|
||||
}
|
||||
|
||||
public static bool IsSupported(CustomGameMode gameMode)
|
||||
{
|
||||
return gameMode is CustomGameMode.Standard or CustomGameMode.SoloKombat or CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato or CustomGameMode.HideAndSeek or CustomGameMode.Speedrun or CustomGameMode.NaturalDisasters or CustomGameMode.RoomRush;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
public static void RepairOxygen()
|
||||
{
|
||||
if (!Loaded) return;
|
||||
try
|
||||
{
|
||||
ShipStatus.Instance.RpcUpdateSystem((SystemTypes)130, 64);
|
||||
RepairDamageMethod.Invoke(SubmarineOxygenSystemInstanceField.GetValue(null), new object[] { PlayerControl.LocalPlayer, 64 });
|
||||
}
|
||||
catch (System.NullReferenceException)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
public static bool IsSubmerged()
|
||||
{
|
||||
return Loaded && ShipStatus.Instance && ShipStatus.Instance.Type == SubmergedMapType;
|
||||
}
|
||||
|
||||
private static object TryCast(this Il2CppObjectBase self, Type type)
|
||||
{
|
||||
return AccessTools.Method(self.GetType(), nameof(Il2CppObjectBase.TryCast)).MakeGenericMethod(type).Invoke(self, []);
|
||||
}
|
||||
|
||||
private static IList CreateList(Type myType)
|
||||
{
|
||||
Type genericListType = typeof(List<>).MakeGenericType(myType);
|
||||
return (IList)Activator.CreateInstance(genericListType);
|
||||
}
|
||||
|
||||
public enum SubmergedSystemTypes : byte
|
||||
{
|
||||
Research = 0x80, // 128
|
||||
Observatory = 0x81, // 129
|
||||
UpperCentral = 0x82, // 130 (SubmarineOxygenSystem)
|
||||
UpperLobby = 0x83, // 131
|
||||
Filtration = 0x84, // 132
|
||||
Ballast = 0x85, // 133
|
||||
LowerCentral = 0x86, // 134
|
||||
LowerLobby = 0x87, // 135
|
||||
ElevatorWestLeft = 0x88, // 136 (SubmarineElevatorSystem (HallwayLeft))
|
||||
ElevatorWestRight = 0x89, // 137 (SubmarineElevatorSystem (HallwayRight))
|
||||
ElevatorEastLeft = 0x8a, // 138 (SubmarineElevatorSystem (LobbyLeft))
|
||||
ElevatorEastRight = 0x8b, // 139 (SubmarineElevatorSystem (LobbyRight))
|
||||
ElevatorService = 0x8c, // 140 (SubmarineElevatorSystem (Service))
|
||||
|
||||
SubmarinePlayerFloorSystem = 0x8d, // 141
|
||||
SubmarineSecuritySabotageSystem = 0x8e, // 142
|
||||
SubmarineSpawnInSystem = 0x8f, // 143
|
||||
SubmarineBoxCatSystem = 0x90 // 144
|
||||
}
|
||||
}
|
||||
@@ -4,5 +4,6 @@
|
||||
<add key="nuget" value="https://api.nuget.org/v3/index.json"/>
|
||||
<add key="BepInEx" value="https://nuget.bepinex.dev/v3/index.json"/>
|
||||
<add key="Samboy" value="https://nuget.samboy.dev/v3/index.json"/>
|
||||
<add key="LocalPackages" value="D:\Coding\Packages"/>
|
||||
</packageSources>
|
||||
</configuration>
|
||||
Reference in new issue
Block a user