mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-20 01:46:25 +00:00
some fixes
This commit is contained in:
1 parent
2d00117b84
commit
61f96ef388
14 files changed
+206
-167
No files matched your search
@@ -66,6 +66,7 @@
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TS/@EntryIndexedValue">TS</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UI/@EntryIndexedValue">UI</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=VN/@EntryIndexedValue">VN</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=XOR/@EntryIndexedValue">XOR</s:String>
|
||||
<s:String
|
||||
x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=42a3efd9_002Dd16d_002D4959_002Daa84_002D6ab8f5f87659/@EntryIndexedValue"><Policy><Descriptor Staticness="Any" AccessRightKinds="Private, Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="non_field_members_should_be_pascal_case"><ElementKinds><Kind Name="PROPERTY" /><Kind Name="EVENT" /><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="False" Prefix="Get" Suffix="" Style="AaBb" /></Policy></s:String>
|
||||
<s:String
|
||||
|
||||
+59
-22
@@ -3,7 +3,6 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using AmongUs.GameOptions;
|
||||
using EHR.Modules;
|
||||
using HarmonyLib;
|
||||
using Hazel;
|
||||
@@ -83,17 +82,19 @@ public static class Quiz
|
||||
private static int QuestionsAsked;
|
||||
private static long FFAEndTS;
|
||||
private static bool NoSuffix;
|
||||
|
||||
public static bool AllowKills;
|
||||
|
||||
private static OptionItem FFAEventLength;
|
||||
private static readonly Dictionary<Difficulty, (OptionItem Rounds, OptionItem QuestionsAsked, OptionItem CorrectRequirement, OptionItem TimeLimit)> Settings = [];
|
||||
private static OptionItem ChatDuringGame;
|
||||
|
||||
static Quiz()
|
||||
{
|
||||
UsedRooms[MapNames.Dleks] = UsedRooms[MapNames.Skeld];
|
||||
}
|
||||
|
||||
public static bool Chat => ChatDuringGame.GetBool();
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
var id = 69_220_001;
|
||||
@@ -115,6 +116,7 @@ public static class Quiz
|
||||
.SetGameMode(gameMode);
|
||||
|
||||
var questionsAsked = new IntegerOptionItem(id++, $"Quiz.Settings.QuestionsAsked.{difficulty}", new(1, 50, 1), 3, TabGroup.GameSettings)
|
||||
.SetHeader(difficulty == Difficulty.Hard)
|
||||
.SetColor(color)
|
||||
.SetGameMode(gameMode);
|
||||
|
||||
@@ -129,6 +131,11 @@ public static class Quiz
|
||||
|
||||
Settings[difficulty] = (rounds, questionsAsked, correctRequirement, timeLimit);
|
||||
}
|
||||
|
||||
ChatDuringGame = new BooleanOptionItem(id, "Quiz.Settings.ChatDuringGame", false, TabGroup.GameSettings)
|
||||
.SetHeader(true)
|
||||
.SetColor(color)
|
||||
.SetGameMode(gameMode);
|
||||
}
|
||||
|
||||
public static string GetStatistics(byte id)
|
||||
@@ -150,7 +157,9 @@ public static class Quiz
|
||||
{
|
||||
if (NoSuffix) return string.Empty;
|
||||
|
||||
bool wasWrong = DyingPlayers.Contains(seer.PlayerId);
|
||||
int requiredCorrect;
|
||||
int gotCorrect;
|
||||
bool failed;
|
||||
|
||||
if (FFAEndTS == 0)
|
||||
{
|
||||
@@ -188,17 +197,17 @@ public static class Quiz
|
||||
string correctAnswer = CurrentQuestion.Answers[CurrentQuestion.CorrectAnswerIndex];
|
||||
char correctAnswerLetter = (char)('A' + CurrentQuestion.CorrectAnswerIndex);
|
||||
string correctRoom = GetString(UsedRooms[Main.CurrentMap][correctAnswerLetter].ToString());
|
||||
string color = wasWrong ? "#FF0000" : "#00FF00";
|
||||
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("Quiz.Notify.AllWrong");
|
||||
if (DyingPlayers.Count == numPlayers) str += "\n" + GetString(numPlayers <= 3 ? "Quiz.Notify.AllWrongShort" : "Quiz.Notify.AllWrong");
|
||||
|
||||
if (CurrentDifficulty > Difficulty.Test && Settings[CurrentDifficulty].QuestionsAsked.GetInt() <= QuestionsAsked)
|
||||
{
|
||||
int requiredCorrect = Settings[CurrentDifficulty].CorrectRequirement.GetInt();
|
||||
int gotCorrect = NumCorrectAnswers[seer.PlayerId][CurrentDifficulty][Round];
|
||||
bool failed = gotCorrect < requiredCorrect;
|
||||
requiredCorrect = Settings[CurrentDifficulty].CorrectRequirement.GetInt();
|
||||
gotCorrect = NumCorrectAnswers[seer.PlayerId][CurrentDifficulty][Round];
|
||||
failed = gotCorrect < requiredCorrect;
|
||||
|
||||
if (seer.IsAlive()) str += "\n\n" + string.Format(Utils.ColorString(failed ? Color.red : Color.green, GetString("Quiz.Notify.CorrectAnswerNum")), gotCorrect, QuestionsAsked, requiredCorrect);
|
||||
|
||||
@@ -216,9 +225,13 @@ public static class Quiz
|
||||
|
||||
if (!AllowKills) return string.Empty;
|
||||
|
||||
requiredCorrect = Settings[CurrentDifficulty].CorrectRequirement.GetInt();
|
||||
gotCorrect = NumCorrectAnswers[seer.PlayerId][CurrentDifficulty][Round];
|
||||
failed = gotCorrect < requiredCorrect;
|
||||
|
||||
var ffaTimeLeft = FFAEndTS - Utils.TimeStamp;
|
||||
var rndRoom = Main.AllAlivePlayerControls.Without(seer).Select(x => x.GetPlainShipRoom()).Where(x => x != null).Select(x => x.RoomId).Distinct().Without(SystemTypes.Hallway).RandomElement();
|
||||
return string.Format(GetString(wasWrong ? "Quiz.Notify.FFAOngoing" : "Quiz.Notify.FFASpectating"), GetString(rndRoom.ToString()), ffaTimeLeft);
|
||||
var rooms = Main.AllAlivePlayerControls.Without(seer).Select(x => x.GetPlainShipRoom()).Where(x => x != null).Select(x => x.RoomId).Distinct().Without(SystemTypes.Hallway).Select(x => GetString(x.ToString())).Join();
|
||||
return string.Format(GetString(failed ? "Quiz.Notify.FFAOngoing" : "Quiz.Notify.FFASpectating"), rooms, ffaTimeLeft);
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
@@ -247,6 +260,8 @@ public static class Quiz
|
||||
|
||||
public static IEnumerator OnGameStart()
|
||||
{
|
||||
if (Chat) yield return new WaitForSeconds(11f);
|
||||
|
||||
NoSuffix = true;
|
||||
PlayerControl[] aapc = Main.AllAlivePlayerControls;
|
||||
bool showTutorial = aapc.ExceptBy(HasPlayedFriendCodes, x => x.FriendCode).Count() > aapc.Length / 2;
|
||||
@@ -285,9 +300,17 @@ public static class Quiz
|
||||
|
||||
aapc.NotifyPlayers(GetString("Quiz.Tutorial.OnCorrectAnswer"));
|
||||
yield return new WaitForSeconds(2f);
|
||||
if (GameStates.IsMeeting || ExileController.Instance || !GameStates.InGame || GameStates.IsLobby) yield break;
|
||||
NameNotifyManager.Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
NoSuffix = true;
|
||||
var settings = Settings[CurrentDifficulty];
|
||||
Main.AllAlivePlayerControls.NotifyPlayers(string.Format(GetString("Quiz.Notify.NextStage"), (int)CurrentDifficulty, settings.Rounds.GetInt(), settings.QuestionsAsked.GetInt(), settings.CorrectRequirement.GetInt(), settings.QuestionsAsked.GetInt(), settings.TimeLimit.GetInt()), 8f);
|
||||
yield return new WaitForSeconds(6f);
|
||||
}
|
||||
|
||||
if (GameStates.IsMeeting || ExileController.Instance || !GameStates.InGame || GameStates.IsLobby) yield break;
|
||||
NameNotifyManager.Reset();
|
||||
|
||||
yield return NewQuestion(increaseDifficulty: showTutorial, newRound: true);
|
||||
}
|
||||
@@ -301,7 +324,7 @@ public static class Quiz
|
||||
NoSuffix = true;
|
||||
var settings = Settings[CurrentDifficulty];
|
||||
Main.AllAlivePlayerControls.NotifyPlayers(string.Format(GetString("Quiz.Notify.NextStage"), (int)CurrentDifficulty, settings.Rounds.GetInt(), settings.QuestionsAsked.GetInt(), settings.CorrectRequirement.GetInt(), settings.QuestionsAsked.GetInt(), settings.TimeLimit.GetInt()), 8f);
|
||||
yield return new WaitForSeconds(7f);
|
||||
yield return new WaitForSeconds(6f);
|
||||
if (GameStates.IsMeeting || ExileController.Instance || !GameStates.InGame || GameStates.IsLobby) yield break;
|
||||
NameNotifyManager.Reset();
|
||||
}
|
||||
@@ -371,14 +394,14 @@ public static class Quiz
|
||||
SystemTypes correctRoom = UsedRooms[Main.CurrentMap][(char)('A' + CurrentQuestion.CorrectAnswerIndex)];
|
||||
DyingPlayers = aapc.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();
|
||||
bool everyoneWasWrong = DyingPlayers.Count == aapc.Length;
|
||||
if (!everyoneWasWrong) NumCorrectAnswers.DoIf(x => !DyingPlayers.Contains(x.Key), x => x.Value[CurrentDifficulty][Round]++);
|
||||
if (!everyoneWasWrong) NumCorrectAnswers.IntersectBy(aapc.Select(x => x.PlayerId), x => x.Key).DoIf(x => !DyingPlayers.Contains(x.Key), x => x.Value[CurrentDifficulty][Round]++);
|
||||
Logger.Info($"{(everyoneWasWrong ? "Everyone" : "Players who")} got the question wrong: {string.Join(", ", DyingPlayers.Select(x => Main.AllPlayerNames.GetValueOrDefault(x, $"Someone (ID {x})")))}", "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();
|
||||
|
||||
yield return new WaitForSeconds(everyoneWasWrong ? 11f : 7f);
|
||||
yield return new WaitForSeconds(everyoneWasWrong ? aapc.Length <= 3 ? 4f : 8f : 5f);
|
||||
if (GameStates.IsMeeting || ExileController.Instance || !GameStates.InGame || GameStates.IsLobby) yield break;
|
||||
|
||||
var settings = Settings[CurrentDifficulty];
|
||||
@@ -389,7 +412,7 @@ public static class Quiz
|
||||
yield break;
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(3f);
|
||||
yield return new WaitForSeconds(2f);
|
||||
|
||||
var correctRequirement = settings.CorrectRequirement.GetInt();
|
||||
List<byte> dyingPlayers = NumCorrectAnswers.Where(x => x.Value[CurrentDifficulty][Round] < correctRequirement).Select(x => x.Key).ToList();
|
||||
@@ -412,7 +435,7 @@ public static class Quiz
|
||||
NumCorrectAnswers.Values.Do(d => d[CurrentDifficulty][Round] = 0);
|
||||
goto case 0;
|
||||
default:
|
||||
yield return new WaitForSeconds(3f);
|
||||
yield return new WaitForSeconds(2f);
|
||||
AllowKills = true;
|
||||
FFAEndTS = Utils.TimeStamp + FFAEventLength.GetInt();
|
||||
var spectators = aapc.ExceptBy(dyingPlayers, x => x.PlayerId).ToArray();
|
||||
@@ -439,8 +462,6 @@ public static class Quiz
|
||||
|
||||
var location = RandomSpawn.SpawnMap.GetSpawnMap().Positions.IntersectBy(UsedRooms[Main.CurrentMap].Values, x => x.Key).RandomElement().Value;
|
||||
sender = CustomRpcSender.Create("Quiz.FFA-Event-TP", SendOption.Reliable);
|
||||
spectators.Do(x => sender.TP(x, location));
|
||||
sender.SendMessage();
|
||||
|
||||
switch (stillLiving.Count)
|
||||
{
|
||||
@@ -448,16 +469,26 @@ public static class Quiz
|
||||
break;
|
||||
case 1:
|
||||
stillLiving[0].RpcChangeRoleBasis(CustomRoles.QuizPlayer);
|
||||
if (!Chat) sender.TP(stillLiving[0], location);
|
||||
break;
|
||||
default:
|
||||
stillLiving.ForEach(x => x.Suicide());
|
||||
break;
|
||||
}
|
||||
|
||||
Main.AllPlayerSpeed.SetAllValues(Main.RealOptionsData.GetFloat(FloatOptionNames.PlayerSpeedMod));
|
||||
Utils.MarkEveryoneDirtySettings();
|
||||
yield return new WaitForSeconds(1f);
|
||||
|
||||
yield return new WaitForSeconds(3f);
|
||||
if (Chat)
|
||||
{
|
||||
Utils.SetChatVisibleForAll();
|
||||
yield return new WaitForSeconds(11f);
|
||||
sender.TP(stillLiving[0], location);
|
||||
}
|
||||
|
||||
spectators.Do(x => sender.TP(x, location));
|
||||
sender.SendMessage();
|
||||
|
||||
yield return new WaitForSeconds(2f);
|
||||
if (GameStates.IsMeeting || ExileController.Instance || !GameStates.InGame || GameStates.IsLobby) yield break;
|
||||
|
||||
FFAEndTS = 0;
|
||||
@@ -466,6 +497,12 @@ public static class Quiz
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetTaskBarText()
|
||||
{
|
||||
var correctAnswers = string.Join('\n', NumCorrectAnswers.Select(x => $"{x.Key.ColoredPlayerName()}: {x.Value.Select(k => $"{k.Key.ToString()[0]}-{k.Value.Sum()}")}"));
|
||||
return string.Format(GetString("Quiz.TaskBarText"), CurrentDifficulty, Round + 1, QuestionsAsked + 1, correctAnswers);
|
||||
}
|
||||
|
||||
enum Difficulty
|
||||
{
|
||||
Test,
|
||||
|
||||
@@ -74,6 +74,7 @@ public class Main : BasePlugin
|
||||
public static Dictionary<byte, List<CustomRoles>> SetAddOns = [];
|
||||
public static readonly Dictionary<int, Dictionary<CustomRoles, List<CustomRoles>>> AlwaysSpawnTogetherCombos = [];
|
||||
public static readonly Dictionary<int, Dictionary<CustomRoles, List<CustomRoles>>> NeverSpawnTogetherCombos = [];
|
||||
public static readonly List<(CustomRoles, CustomRoles)> XORRoles = [];
|
||||
public static Dictionary<byte, string> LastAddOns = [];
|
||||
public static List<RoleBase> AllRoleClasses;
|
||||
public static float RefixCooldownDelay;
|
||||
|
||||
@@ -93,10 +93,20 @@ internal static class CustomRoleSelector
|
||||
(bool Spawning, bool OneIsImp) LoversData = (Lovers.LegacyLovers.GetBool(), rd.Next(100) < Lovers.LovingImpostorSpawnChance.GetInt());
|
||||
LoversData.Spawning &= rd.Next(100) < Options.CustomAdtRoleSpawnRate[CustomRoles.Lovers].GetInt();
|
||||
|
||||
HashSet<CustomRoles> xorBannedRoles = [];
|
||||
|
||||
foreach ((CustomRoles, CustomRoles) xor in Main.XORRoles)
|
||||
{
|
||||
bool first = rd.Next(2) == 0;
|
||||
xorBannedRoles.Add(first ? xor.Item1 : xor.Item2);
|
||||
}
|
||||
|
||||
if (Main.XORRoles.Count > 0) Logger.Info($"Roles banned by XOR combinations: {string.Join(", ", xorBannedRoles)}", "CustomRoleSelector");
|
||||
|
||||
foreach (CustomRoles role in Enum.GetValues<CustomRoles>())
|
||||
{
|
||||
int chance = role.GetMode();
|
||||
if (role.IsVanilla() || chance == 0 || role.IsAdditionRole() || (role.OnlySpawnsWithPets() && !Options.UsePets.GetBool()) || (role != CustomRoles.Randomizer && role.IsCrewmate() && Options.AprilFoolsMode.GetBool()) || CustomHnS.AllHnSRoles.Contains(role)) continue;
|
||||
if (role.IsVanilla() || chance == 0 || role.IsAdditionRole() || (role.OnlySpawnsWithPets() && !Options.UsePets.GetBool()) || (role != CustomRoles.Randomizer && role.IsCrewmate() && Options.AprilFoolsMode.GetBool()) || CustomHnS.AllHnSRoles.Contains(role) || xorBannedRoles.Contains(role)) continue;
|
||||
|
||||
switch (role)
|
||||
{
|
||||
|
||||
@@ -466,7 +466,7 @@ public static class CustomRpcSenderExtensions
|
||||
|
||||
if (!player.CanUseKillButton() && !AntiBlackout.SkipTasks) return false;
|
||||
|
||||
player.AddKillTimerToDict(CD: time);
|
||||
player.AddKillTimerToDict(cd: time);
|
||||
if (target == null) target = player;
|
||||
|
||||
if (time >= 0f)
|
||||
|
||||
@@ -25,32 +25,6 @@ internal static class ExtendedPlayerControl
|
||||
{
|
||||
public const MurderResultFlags ResultFlags = MurderResultFlags.Succeeded;
|
||||
|
||||
/*
|
||||
public static void ResetPlayerCam(this PlayerControl pc, float delay = 0f)
|
||||
{
|
||||
if (pc == null || !AmongUsClient.Instance.AmHost || pc.AmOwner) return;
|
||||
|
||||
SystemTypes systemtypes = (MapNames)Main.NormalOptions.MapId switch
|
||||
{
|
||||
MapNames.Polus => SystemTypes.Laboratory,
|
||||
MapNames.Airship => SystemTypes.HeliSabotage,
|
||||
_ => SystemTypes.Reactor
|
||||
};
|
||||
|
||||
LateTask.New(() => pc.RpcDesyncRepairSystem(systemtypes, 128), 0f + delay, "Reactor Desync");
|
||||
|
||||
LateTask.New(() => pc.RpcSpecificMurderPlayer(), 0.2f + delay, "Murder To Reset Cam");
|
||||
|
||||
LateTask.New(() =>
|
||||
{
|
||||
pc.RpcDesyncRepairSystem(systemtypes, 16);
|
||||
|
||||
if (Main.NormalOptions.MapId == 4) // Airship only
|
||||
pc.RpcDesyncRepairSystem(systemtypes, 17);
|
||||
}, 0.4f + delay, "Fix Desync Reactor");
|
||||
}
|
||||
*/
|
||||
|
||||
private static readonly HashSet<byte> BlackScreenWaitingPlayers = [];
|
||||
|
||||
public static void SetRole(this PlayerControl player, RoleTypes role, bool canOverride = true)
|
||||
@@ -79,12 +53,12 @@ internal static class ExtendedPlayerControl
|
||||
}
|
||||
}
|
||||
|
||||
public static void RpcSetCustomRole(byte PlayerId, CustomRoles role)
|
||||
public static void RpcSetCustomRole(byte playerId, CustomRoles role)
|
||||
{
|
||||
if (AmongUsClient.Instance.AmHost)
|
||||
{
|
||||
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetCustomRole, SendOption.Reliable);
|
||||
writer.Write(PlayerId);
|
||||
writer.Write(playerId);
|
||||
writer.WritePacked((int)role);
|
||||
AmongUsClient.Instance.FinishRpcImmediately(writer);
|
||||
}
|
||||
@@ -109,7 +83,7 @@ internal static class ExtendedPlayerControl
|
||||
return (player.inVent && player.GetClosestVent()?.Id == ventId) || ((player.CanUseImpostorVentButton() || player.GetRoleTypes() == RoleTypes.Engineer) && Main.PlayerStates.Values.All(x => x.Role.CanUseVent(player, ventId)));
|
||||
}
|
||||
|
||||
// Next 3: https://github.com/Rabek009/MoreGamemodes/blob/master/Modules/ExtendedPlayerControl.cs
|
||||
// Next 2: https://github.com/Rabek009/MoreGamemodes/blob/master/Modules/ExtendedPlayerControl.cs
|
||||
public static Vent GetClosestVent(this PlayerControl player)
|
||||
{
|
||||
Vector2 pos = player.Pos();
|
||||
@@ -133,13 +107,6 @@ internal static class ExtendedPlayerControl
|
||||
return vents;
|
||||
}
|
||||
|
||||
/*
|
||||
public static void RpcSetVentInteraction(this PlayerControl player)
|
||||
{
|
||||
var ventilationSystem = ShipStatus.Instance.Systems[SystemTypes.Ventilation].CastFast<VentilationSystem>();
|
||||
if (ventilationSystem != null) VentilationSystemDeterioratePatch.SerializeV2(ventilationSystem, player);
|
||||
}
|
||||
*/
|
||||
// From: https://github.com/Rabek009/MoreGamemodes/blob/master/Modules/ExtendedPlayerControl.cs - coded by Rabek009
|
||||
public static void SetChatVisible(this PlayerControl player, bool visible)
|
||||
{
|
||||
@@ -189,12 +156,6 @@ internal static class ExtendedPlayerControl
|
||||
writer.Recycle();
|
||||
}
|
||||
|
||||
/*
|
||||
public static void RpcExile(this PlayerControl player)
|
||||
{
|
||||
RPC.ExileAsync(player);
|
||||
}
|
||||
*/
|
||||
public static ClientData GetClient(this PlayerControl player)
|
||||
{
|
||||
try { return AmongUsClient.Instance.allClients.ToArray().FirstOrDefault(cd => cd.Character.PlayerId == player.PlayerId); }
|
||||
@@ -227,7 +188,7 @@ internal static class ExtendedPlayerControl
|
||||
return CustomRoles.Crewmate;
|
||||
}
|
||||
|
||||
return Main.PlayerStates.TryGetValue(player.PlayerId, out PlayerState State) ? State.MainRole : CustomRoles.Crewmate;
|
||||
return Main.PlayerStates.TryGetValue(player.PlayerId, out PlayerState state) ? state.MainRole : CustomRoles.Crewmate;
|
||||
}
|
||||
|
||||
public static List<CustomRoles> GetCustomSubRoles(this PlayerControl player)
|
||||
@@ -262,53 +223,6 @@ internal static class ExtendedPlayerControl
|
||||
return state.countTypes;
|
||||
}
|
||||
|
||||
/*
|
||||
public static void RpcSetNameEx(this PlayerControl player, string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (player == null)
|
||||
{
|
||||
Logger.Warn("The player is null", "RpcSetNameEx");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (PlayerControl seer in Main.AllPlayerControls)
|
||||
{
|
||||
try { Main.LastNotifyNames[(player.PlayerId, seer.PlayerId)] = name; }
|
||||
catch { }
|
||||
}
|
||||
|
||||
if (player.Data != null) Logger.Info($"Set: {player.Data.PlayerName} => {name} for Everyone", "RpcSetNameEx");
|
||||
|
||||
player.RpcSetName(name);
|
||||
}
|
||||
catch (Exception e) { ThrowException(e); }
|
||||
}
|
||||
|
||||
public static void RpcSetNamePrivate(this PlayerControl player, string name, PlayerControl seer = null, bool force = false)
|
||||
{
|
||||
if (player == null || name == null || !AmongUsClient.Instance.AmHost) return;
|
||||
|
||||
if (seer == null) seer = player;
|
||||
|
||||
if (!force && Main.LastNotifyNames[(player.PlayerId, seer.PlayerId)] == name) return;
|
||||
|
||||
Main.LastNotifyNames[(player.PlayerId, seer.PlayerId)] = name;
|
||||
Logger.Info($"Set: {player.Data?.PlayerName} => {name} for {seer.GetNameWithRole().RemoveHtmlTags()}", "RpcSetNamePrivate");
|
||||
|
||||
if (seer == null || player == null) return;
|
||||
|
||||
int clientId = seer.GetClientId();
|
||||
if (clientId == -1) return;
|
||||
|
||||
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(player.NetId, (byte)RpcCalls.SetName, SendOption.Reliable, clientId);
|
||||
writer.Write(seer.Data.NetId);
|
||||
writer.Write(name);
|
||||
AmongUsClient.Instance.FinishRpcImmediately(writer);
|
||||
}
|
||||
*/
|
||||
|
||||
// By TommyXL
|
||||
public static void RpcSetPetDesync(this PlayerControl player, string petId, PlayerControl seer)
|
||||
{
|
||||
@@ -671,10 +585,10 @@ internal static class ExtendedPlayerControl
|
||||
_ => SystemTypes.Reactor
|
||||
};
|
||||
|
||||
bool ReactorCheck = IsActive(systemtypes); // Checking whether the reactor sabotage is active
|
||||
bool reactorCheck = IsActive(systemtypes); // Checking whether the reactor sabotage is active
|
||||
|
||||
float Duration = Options.KillFlashDuration.GetFloat();
|
||||
if (ReactorCheck) Duration += 0.2f; // Extend blackout during reactor
|
||||
float duration = Options.KillFlashDuration.GetFloat();
|
||||
if (reactorCheck) duration += 0.2f; // Extend blackout during reactor
|
||||
|
||||
// Execution
|
||||
Main.PlayerStates[player.PlayerId].IsBlackOut = true; // Blackout
|
||||
@@ -689,7 +603,7 @@ internal static class ExtendedPlayerControl
|
||||
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.KillFlash, SendOption.Reliable, player.GetClientId());
|
||||
AmongUsClient.Instance.FinishRpcImmediately(writer);
|
||||
}
|
||||
else if (!ReactorCheck) player.ReactorFlash(); // Reactor flash
|
||||
else if (!reactorCheck) player.ReactorFlash(); // Reactor flash
|
||||
|
||||
player.MarkDirtySettings();
|
||||
|
||||
@@ -697,7 +611,7 @@ internal static class ExtendedPlayerControl
|
||||
{
|
||||
Main.PlayerStates[player.PlayerId].IsBlackOut = false; // Cancel blackout
|
||||
player.MarkDirtySettings();
|
||||
}, Duration, "RemoveKillFlash");
|
||||
}, duration, "RemoveKillFlash");
|
||||
}
|
||||
|
||||
public static void RpcGuardAndKill(this PlayerControl killer, PlayerControl target = null, bool forObserver = false, bool fromSetKCD = false)
|
||||
@@ -739,7 +653,7 @@ internal static class ExtendedPlayerControl
|
||||
|
||||
public static void AddKCDAsAbilityCD(this PlayerControl pc)
|
||||
{
|
||||
AddAbilityCD(pc, (int)Math.Round(Main.AllPlayerKillCooldown.TryGetValue(pc.PlayerId, out float KCD) ? KCD : Options.DefaultKillCooldown));
|
||||
AddAbilityCD(pc, (int)Math.Round(Main.AllPlayerKillCooldown.TryGetValue(pc.PlayerId, out float kcd) ? kcd : Options.DefaultKillCooldown));
|
||||
}
|
||||
|
||||
public static void AddAbilityCD(this PlayerControl pc, bool includeDuration = true)
|
||||
@@ -747,10 +661,10 @@ internal static class ExtendedPlayerControl
|
||||
Utils.AddAbilityCD(pc.GetCustomRole(), pc.PlayerId, includeDuration);
|
||||
}
|
||||
|
||||
public static void AddAbilityCD(this PlayerControl pc, int CD)
|
||||
public static void AddAbilityCD(this PlayerControl pc, int cd)
|
||||
{
|
||||
Main.AbilityCD[pc.PlayerId] = (TimeStamp, CD);
|
||||
SendRPC(CustomRPC.SyncAbilityCD, 1, pc.PlayerId, CD);
|
||||
Main.AbilityCD[pc.PlayerId] = (TimeStamp, cd);
|
||||
SendRPC(CustomRPC.SyncAbilityCD, 1, pc.PlayerId, cd);
|
||||
}
|
||||
|
||||
public static void RemoveAbilityCD(this PlayerControl pc)
|
||||
@@ -861,7 +775,7 @@ internal static class ExtendedPlayerControl
|
||||
|
||||
if (!player.CanUseKillButton() && !AntiBlackout.SkipTasks) return;
|
||||
|
||||
player.AddKillTimerToDict(CD: time);
|
||||
player.AddKillTimerToDict(cd: time);
|
||||
if (target == null) target = player;
|
||||
|
||||
if (time >= 0f)
|
||||
@@ -877,7 +791,7 @@ internal static class ExtendedPlayerControl
|
||||
else if (forceAnime || !player.IsModdedClient() || !Options.DisableShieldAnimations.GetBool())
|
||||
{
|
||||
player.SyncSettings();
|
||||
player.RpcGuardAndKill(target, fromSetKCD: true);
|
||||
LateTask.New(() => player.RpcGuardAndKill(target, fromSetKCD: true), 0.1f, log: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -895,25 +809,10 @@ internal static class ExtendedPlayerControl
|
||||
Main.AllPlayerControls.Where(x => x.Is(CustomRoles.Observer) && target.PlayerId != x.PlayerId).Do(x => x.RpcGuardAndKill(target, true, true));
|
||||
}
|
||||
|
||||
if (player.GetCustomRole() is not CustomRoles.Inhibitor and not CustomRoles.Saboteur) player.ResetKillCooldown();
|
||||
if (player.GetCustomRole() is not CustomRoles.Inhibitor and not CustomRoles.Saboteur)
|
||||
LateTask.New(() => player.ResetKillCooldown(), 0.3f, log: false);
|
||||
}
|
||||
|
||||
/*
|
||||
public static void RpcSpecificMurderPlayer(this PlayerControl killer, PlayerControl target = null)
|
||||
{
|
||||
if (target == null) target = killer;
|
||||
|
||||
if (killer.AmOwner)
|
||||
killer.MurderPlayer(target, ResultFlags);
|
||||
else
|
||||
{
|
||||
MessageWriter messageWriter = AmongUsClient.Instance.StartRpcImmediately(killer.NetId, (byte)RpcCalls.MurderPlayer, SendOption.Reliable, killer.GetClientId());
|
||||
messageWriter.WriteNetObject(target);
|
||||
messageWriter.Write((byte)ResultFlags);
|
||||
AmongUsClient.Instance.FinishRpcImmediately(messageWriter);
|
||||
}
|
||||
}
|
||||
*/
|
||||
public static void RpcResetAbilityCooldown(this PlayerControl target)
|
||||
{
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
@@ -985,12 +884,12 @@ internal static class ExtendedPlayerControl
|
||||
|
||||
public static string GetSubRoleNames(this PlayerControl player, bool forUser = false)
|
||||
{
|
||||
List<CustomRoles> SubRoles = Main.PlayerStates[player.PlayerId].SubRoles;
|
||||
if (SubRoles.Count == 0) return string.Empty;
|
||||
List<CustomRoles> subRoles = Main.PlayerStates[player.PlayerId].SubRoles;
|
||||
if (subRoles.Count == 0) return string.Empty;
|
||||
|
||||
StringBuilder sb = new();
|
||||
|
||||
foreach (CustomRoles role in SubRoles)
|
||||
foreach (CustomRoles role in subRoles)
|
||||
{
|
||||
if (role == CustomRoles.NotAssigned) continue;
|
||||
|
||||
@@ -1049,6 +948,15 @@ internal static class ExtendedPlayerControl
|
||||
yield break;
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(1f);
|
||||
|
||||
if (!GameStates.InGame || GameStates.IsEnded)
|
||||
{
|
||||
Logger.Msg($"During the waiting, the game ended, so the black screen fix will not be executed for {pc.GetNameWithRole()}", "FixBlackScreen");
|
||||
BlackScreenWaitingPlayers.Remove(pc.PlayerId);
|
||||
yield break;
|
||||
}
|
||||
|
||||
Logger.Msg($"Now that the conditions are met, fixing black screen for {pc.GetNameWithRole()}", "FixBlackScreen");
|
||||
BlackScreenWaitingPlayers.Remove(pc.PlayerId);
|
||||
pc.FixBlackScreen();
|
||||
@@ -1336,18 +1244,18 @@ internal static class ExtendedPlayerControl
|
||||
return new(pc.transform.position.x, pc.transform.position.y);
|
||||
}
|
||||
|
||||
public static void AddKillTimerToDict(this PlayerControl pc, bool half = false, float CD = -1f)
|
||||
public static void AddKillTimerToDict(this PlayerControl pc, bool half = false, float cd = -1f)
|
||||
{
|
||||
float resultKCD;
|
||||
|
||||
if (Math.Abs(CD - -1f) < 0.5f)
|
||||
if (Math.Abs(cd - -1f) < 0.5f)
|
||||
{
|
||||
resultKCD = Main.AllPlayerKillCooldown.GetValueOrDefault(pc.PlayerId, 0f);
|
||||
|
||||
if (half) resultKCD /= 2f;
|
||||
}
|
||||
else
|
||||
resultKCD = CD;
|
||||
resultKCD = cd;
|
||||
|
||||
if (pc.GetCustomRole().UsesPetInsteadOfKill() && resultKCD > 0f)
|
||||
pc.AddAbilityCD((int)Math.Round(resultKCD));
|
||||
@@ -1754,29 +1662,29 @@ internal static class ExtendedPlayerControl
|
||||
&& target.Data.IsDead;
|
||||
}
|
||||
|
||||
public static string GetRoleInfo(this PlayerControl player, bool InfoLong = false)
|
||||
public static string GetRoleInfo(this PlayerControl player, bool infoLong = false)
|
||||
{
|
||||
CustomRoles role = player.GetCustomRole();
|
||||
if (role is CustomRoles.Crewmate or CustomRoles.Impostor) InfoLong = false;
|
||||
if (role is CustomRoles.Crewmate or CustomRoles.Impostor) infoLong = false;
|
||||
|
||||
var text = role.ToString();
|
||||
|
||||
var Prefix = string.Empty;
|
||||
var prefix = string.Empty;
|
||||
|
||||
if (!InfoLong)
|
||||
if (!infoLong)
|
||||
{
|
||||
Prefix = role switch
|
||||
prefix = role switch
|
||||
{
|
||||
CustomRoles.Mafia => CanMafiaKill() ? "After" : "Before",
|
||||
_ => Prefix
|
||||
_ => prefix
|
||||
};
|
||||
}
|
||||
|
||||
string Info = (role.IsVanilla() ? "Blurb" : "Info") + (InfoLong ? "Long" : string.Empty);
|
||||
return GetString($"{Prefix}{text}{Info}");
|
||||
string info = (role.IsVanilla() ? "Blurb" : "Info") + (infoLong ? "Long" : string.Empty);
|
||||
return GetString($"{prefix}{text}{info}");
|
||||
}
|
||||
|
||||
public static void SetRealKiller(this PlayerControl target, PlayerControl killer, bool NotOverRide = false)
|
||||
public static void SetRealKiller(this PlayerControl target, PlayerControl killer, bool notOverRide = false)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
@@ -1784,8 +1692,8 @@ internal static class ExtendedPlayerControl
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerState State = Main.PlayerStates[target.PlayerId];
|
||||
if (State.RealKiller.TimeStamp != DateTime.MinValue && NotOverRide) return; // Do not overwrite if value already exists
|
||||
PlayerState state = Main.PlayerStates[target.PlayerId];
|
||||
if (state.RealKiller.TimeStamp != DateTime.MinValue && notOverRide) return; // Do not overwrite if value already exists
|
||||
|
||||
byte killerId = killer == null ? byte.MaxValue : killer.PlayerId;
|
||||
RPC.SetRealKiller(target.PlayerId, killerId);
|
||||
@@ -1801,8 +1709,8 @@ internal static class ExtendedPlayerControl
|
||||
{
|
||||
if (!pc.IsAlive() || Pelican.IsEaten(pc.PlayerId)) return null;
|
||||
|
||||
Il2CppReferenceArray<PlainShipRoom> Rooms = ShipStatus.Instance.AllRooms;
|
||||
return Rooms.Where(room => room.roomArea).FirstOrDefault(room => pc.Collider.IsTouching(room.roomArea));
|
||||
Il2CppReferenceArray<PlainShipRoom> rooms = ShipStatus.Instance.AllRooms;
|
||||
return rooms.Where(room => room.roomArea).FirstOrDefault(room => pc.Collider.IsTouching(room.roomArea));
|
||||
}
|
||||
|
||||
public static bool IsImpostor(this PlayerControl pc)
|
||||
|
||||
@@ -198,6 +198,7 @@ internal static class ChatCommands
|
||||
new(["deletetag", "удалитьтег", "删除标签"], "{id}", GetString("CommandDescription.DeleteTag"), Command.UsageLevels.Host, Command.UsageTimes.InLobby, DeleteTagCommand, true, false, [GetString("CommandArgs.DeleteTag.Id")]),
|
||||
new(["daybreak", "db", "дейбрейк", "破晓"], "", GetString("CommandDescription.DayBreak"), Command.UsageLevels.Everyone, Command.UsageTimes.InMeeting, DayBreakCommand, true, true),
|
||||
new(["fix", "blackscreenfix", "fixblackscreen", "ф", "исправить", "修复"], "{id}", GetString("CommandDescription.Fix"), Command.UsageLevels.HostOrModerator, Command.UsageTimes.InGame, FixCommand, true, false, [GetString("CommandArgs.Fix.Id")]),
|
||||
new(["xor", "异或命令"], "{role} {role}", GetString("CommandDescription.XOR"), Command.UsageLevels.Host, Command.UsageTimes.InLobby, XORCommand, true, false, [GetString("CommandArgs.XOR.Role"), GetString("CommandArgs.XOR.Role")]),
|
||||
|
||||
// Commands with action handled elsewhere
|
||||
new(["shoot", "guess", "bet", "bt", "st", "угадать", "бт", "猜测", "赌", "adivinhar"], "{id} {role}", GetString("CommandDescription.Guess"), Command.UsageLevels.Everyone, Command.UsageTimes.InMeeting, (_, _, _) => { }, true, false, [GetString("CommandArgs.Guess.Id"), GetString("CommandArgs.Guess.Role")]),
|
||||
@@ -382,6 +383,32 @@ internal static class ChatCommands
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
private static void XORCommand(PlayerControl player, string text, string[] args)
|
||||
{
|
||||
if (args.Length < 3 || !GetRoleByName(args[1], out CustomRoles role1) || !GetRoleByName(args[2], out CustomRoles role2)) return;
|
||||
|
||||
if (Main.XORRoles.Remove((role1, role2)) || Main.XORRoles.Remove((role2, role1)))
|
||||
{
|
||||
Utils.SendMessage("\n", player.PlayerId, string.Format(GetString("XORRemoved"), role1.ToColoredString(), role2.ToColoredString()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (role1 == role2)
|
||||
{
|
||||
Utils.SendMessage("\n", player.PlayerId, GetString("XORSameRole"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (role1.IsAdditionRole() || role2.IsAdditionRole())
|
||||
{
|
||||
Utils.SendMessage("\n", player.PlayerId, GetString("XORAdditionRole"));
|
||||
return;
|
||||
}
|
||||
|
||||
Main.XORRoles.Add((role1, role2));
|
||||
Utils.SendMessage("\n", player.PlayerId, string.Format(GetString("XORAdded"), role1.ToColoredString(), role2.ToColoredString()));
|
||||
}
|
||||
|
||||
private static void FixCommand(PlayerControl player, string text, string[] args)
|
||||
{
|
||||
if (!AmongUsClient.Instance.AmHost)
|
||||
|
||||
@@ -97,6 +97,9 @@ internal static class ControllerManagerUpdatePatch
|
||||
GameEndChecker.Prefix();
|
||||
}
|
||||
|
||||
if (KeysDown(KeyCode.Return, KeyCode.C, KeyCode.LeftShift, KeyCode.LeftControl) && GameStates.IsInGame)
|
||||
Utils.SetChatVisibleForAll();
|
||||
|
||||
if (KeysDown(KeyCode.Return, KeyCode.M, KeyCode.LeftShift) && GameStates.IsInGame)
|
||||
{
|
||||
if (GameStates.IsMeeting)
|
||||
|
||||
@@ -835,6 +835,13 @@ internal static class TaskPanelBehaviourPatch
|
||||
|
||||
finalText += "</size>";
|
||||
break;
|
||||
|
||||
case CustomGameMode.Quiz when AmongUsClient.Instance.AmHost:
|
||||
|
||||
finalText += "\r\n\r\n\r\n<size=70%>";
|
||||
finalText += Quiz.GetTaskBarText();
|
||||
finalText += "</size>";
|
||||
break;
|
||||
}
|
||||
|
||||
__instance.taskText.text = finalText;
|
||||
|
||||
@@ -893,6 +893,7 @@ internal static class IntroCutsceneDestroyPatch
|
||||
switch (Options.CurrentGameMode)
|
||||
{
|
||||
case CustomGameMode.FFA when FreeForAll.FFAChatDuringGame.GetBool():
|
||||
case CustomGameMode.Quiz when Quiz.Chat:
|
||||
Utils.SetChatVisibleForAll();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ internal static class TextBoxTMPSetTextPatch
|
||||
{
|
||||
"{id}" or "{id1}" or "{id2}" => byte.TryParse(arg, out byte id) && Main.AllPlayerControls.Any(x => x.PlayerId == id),
|
||||
"{team}" => arg is "crew" or "imp",
|
||||
"{role}" => ChatCommands.GetRoleByName(arg, out _),
|
||||
"{role}" or "[role]" => ChatCommands.GetRoleByName(arg, out _),
|
||||
"{addon}" => ChatCommands.GetRoleByName(arg, out CustomRoles role) && role.IsAdditionRole(),
|
||||
"{chance}" => int.TryParse(arg, out int chance) && chance is >= 0 and <= 100 && chance % 5 == 0,
|
||||
"{color}" => arg.Length == 6 && arg.All(x => char.IsDigit(x) || x is >= 'a' and <= 'f') && ColorUtility.TryParseHtmlString($"#{arg}", out _),
|
||||
@@ -230,7 +230,7 @@ internal static class TextBoxTMPSetTextPatch
|
||||
: argName switch
|
||||
{
|
||||
"{id}" or "{id1}" or "{id2}" => $" ({byte.Parse(arg).ColoredPlayerName()})",
|
||||
"{role}" or "{addon}" when ChatCommands.GetRoleByName(arg, out CustomRoles role) => $" ({role.ToColoredString()})",
|
||||
"{role}" or "{addon}" or "[role]" when ChatCommands.GetRoleByName(arg, out CustomRoles role) => $" ({role.ToColoredString()})",
|
||||
"{color}" when ColorUtility.TryParseHtmlString($"#{arg}", out Color color) => $" ({Utils.ColorString(color, "COLOR")})",
|
||||
_ => string.Empty
|
||||
};
|
||||
|
||||
@@ -2431,6 +2431,7 @@
|
||||
"CommandDescription.DayBreak": "Call daybreak for the current meeting as the Starspawn.",
|
||||
"CommandDescription.DraftDescription": "View the description of one of the roles you got in the draft.",
|
||||
"CommandDescription.Fix": "Fixes the black screen bug for a specific player.",
|
||||
"CommandDescription.XOR": "Specify 2 roles that will never spawn in the same game.",
|
||||
"CommandArgs.ChangeSetting.Name": "The setting's name to change (leave blank to view all settings)",
|
||||
"CommandArgs.ChangeSetting.UnknownValue": "(leave blank to view what to put here)",
|
||||
"CommandArgs.Rename.Name": "Your new name",
|
||||
@@ -2508,6 +2509,7 @@
|
||||
"CommandArgs.DeleteTag.Id": "The player's ID to delete the tag from",
|
||||
"CommandArgs.DraftDescription.Index": "The number in the drafting message of the role to view the description of",
|
||||
"CommandArgs.Fix.Id": "The player's ID to fix the black screen bug for",
|
||||
"CommandArgs.XOR.Role": "A main role that will never spawn in the same game with the other role",
|
||||
"Commands.ChangeSettingHelp": "<b><u>Arguments:</u></b><size=70%>\\n- map (theskeld/mirahq/polus/dlekseht/airship/thefungle/custom)\\n- impostors (number)\\n- players (number)\\n- recommended (on/off)\\n- confirmejects (on/off)\\n- emergencymeetings (number)\\n- anonymousvotes (on/off)\\n- emergencycooldown (number)\\n- discussiontime (number)\\n- votingtime (number)\\n- playerspeed (float)\\n- crewmatevision (float)\\n- impostorvision (float)\\n- killcooldown (float)\\n- killdistance (short/medium/long/custom)\\n- taskbarupdates (always/meetings/never)\\n- visualtasks (on/off)\\n- commontasks (number)\\n- longtasks (number)\\n- shorttasks (number)\\n- scientistcount (number)\\n- scientistchance (number)\\n- vitalsdisplaycooldown (float)\\n- batteryduration (float)\\n- engineercount (number)\\n- engineerchance (number)\\n- ventusecooldown (float)\\n- maxtimeinvents (float)\\n- guardianangelcount (number)\\n- guardianangelchance (number)\\n- protectcooldown (float)\\n- protectduration (float)\\n- protectvisibletoimpostors (on/off)\\n- shapeshiftercount (number)\\n- shapeshifterchance (number)\\n- shapeshiftduration (float)\\n- shapeshiftcooldown (float)\\n- leaveshapeshiftevidence (on/off)\\n- phantomcount (number)\\n- phantomchance (number)\\n- inviscooldown (float)\\n- invisduration (float)\\n- noisemakercount (number)\\n- noisemakerchance (number)\\n- noisemakerimpostoralert (on/off)\\n- noisemakeralertduration (number)\\n- trackercount (number)\\n- trackerchance (number)\\n- trackduration (float)\\n- trackcooldown (float)\\n- trackdelay (float)\\n- ghostdotasks (on/off)\\n\\n<u><b>Notes:</b></u>\\n1. Upper and lowercase matters\\n2. Where it says custom, you obviously put a number argument after it\\n3. A float is a single precision floating number, like 1.7\\n4. \"ghostdotasks\" causes issues if you set it\\n5. Example uses:\\n - \"/cs map polus\"\\n - \"/cs killdistance custom 4\"\\n - \"/cs trackdelay 1,7\"\\n - \"/cs confirmejects on\"",
|
||||
"AddTagSuccess": "<#00ffa5>✓</color> Suceessfully created the tag {0} for {1}. If you want to change it, just use this command again and it will override the current tag. To delete it, simply type <#00a5ff>/deletetag {2}</color>!",
|
||||
"DeleteTagSuccess": "<#00ffa5>✓</color> Successfully deleted {0}'s tag.",
|
||||
@@ -2562,6 +2564,10 @@
|
||||
"Anagram.CorrectGuess": "<#00ffa5>✓</color> {0} has guessed the anagram correctly (<b>{1}</b>)!",
|
||||
"Anagram": "The scrambled word is <b>{0}</b>! Guess the original word! (Hint: It starts with the letter <b>{1}</b>!)",
|
||||
"AnagramTitle": "<#888888>➡ ANAGRAM ⬅</color>",
|
||||
"XORRemoved": "<#00ffa5>✓</color> XOR combination removed successfully.",
|
||||
"XORSameRole": "<#ff0000>X</color> XOR combinations must have 2 different roles.",
|
||||
"XORAdditionRole": "<#ff0000>X</color> XOR combinations don't support add-ons. Use <#ffff00>/combo</color> for that.",
|
||||
"XORAdded": "<#00ffa5>✓</color> XOR combination added successfully.",
|
||||
"ThankYouForUsingEHR": "Thank you for using EHR!",
|
||||
"GMRoles": "<color=#ff5b70>【 ★ Roles ★ 】</color>",
|
||||
"ImpostorRoles": "【 ★ Impostor Roles ★ 】",
|
||||
@@ -4934,6 +4940,7 @@
|
||||
"Quiz.Settings.QuestionsAsked.Hard": "Number of Questions Asked in Each Hard Round",
|
||||
"Quiz.Settings.CorrectRequirement.Hard": "Number of Correct Answers Required in Each Hard Round to Survive",
|
||||
"Quiz.Settings.TimeLimit.Hard": "Time Limit to Answer Each Question in Hard Rounds",
|
||||
"Quiz.Settings.ChatDuringGame": "Allow Chat During Game",
|
||||
"Quiz.Tutorial.Basics": "The current game mode is <#CF2472>Quiz</color>.\\n<size=90%>You'll get questions, each with 5 choices: A, B, C, D, E.\\nYou must answer the questions correctly within the time limit\\nby entering the room corresponding to the correct answer.\\nThe rooms on this map are:\\n{0}</size>",
|
||||
"Quiz.Tutorial.TestRound": "<size=90%>We'll play a test round to show you how it works.</size>",
|
||||
"Quiz.Tutorial.OnWrongAnswer": "<size=90%>If you answer <#ff0000>incorrectly</color>, you will most likely die.</size>",
|
||||
@@ -4944,6 +4951,7 @@
|
||||
"Quiz.Notify.AllCorrect": "<#00ffa5>Everyone found enough correct answers!</color>",
|
||||
"Quiz.Notify.AllDie": "<#ffff00><u>Everyone</u> would die, so no one will die!\\nInstead, we'll redo this round.</color>",
|
||||
"Quiz.Notify.AllWrong": "<#ffff00><u>Everyone</u> got this question wrong, so this won't\\ncount as an incorrect answer for anyone.\\nInstead, we'll redo this question.</color>",
|
||||
"Quiz.Notify.AllWrongShort": "<#ffff00><u>Everyone</u> was wrong, doesn't count, redo.</color>",
|
||||
"Quiz.Notify.OnlyYouWrong": "<#ff0000>Only you failed this round. You will die now.</color>",
|
||||
"Quiz.Notify.OneWrong": "<#00a5ff>1 player failed this round. They will simply die.</color>",
|
||||
"Quiz.Notify.IncorrectFFA": "<#ff4444>Luckily, you're not alone to failed this round!\\nYou will participate in a Free For All (FFA) event against the others who failed.\\nKill everyone else and be the last one alive to get a second chance!\\nBe sure to do this within the time limit, or all of you will die!</color>",
|
||||
@@ -4951,6 +4959,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.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?",
|
||||
"Quiz.Questions.Test.0.Answer.A": "The Skeld / dlekS ehT",
|
||||
|
||||
@@ -103,20 +103,50 @@ public class PotionMaster : Coven
|
||||
long now = Utils.TimeStamp;
|
||||
List<byte> toRemove = ShieldedPlayers.Where(x => now >= x.Value).Select(x => x.Key).ToList();
|
||||
|
||||
var sender = CustomRpcSender.Create("PotionMaster.OnFixedUpdate", SendOption.Reliable);
|
||||
var hasValue = false;
|
||||
|
||||
toRemove.ForEach(x =>
|
||||
{
|
||||
ShieldedPlayers.Remove(x);
|
||||
PlayerControl player = x.GetPlayer();
|
||||
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: player);
|
||||
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
|
||||
|
||||
sender.NotifyRolesSpecific(pc, player);
|
||||
sender = RestartMessageIfTooLong();
|
||||
|
||||
sender.NotifyRolesSpecific(player, player);
|
||||
hasValue = true;
|
||||
sender = RestartMessageIfTooLong();
|
||||
|
||||
Utils.SendRPC(CustomRPC.SyncRoleData, PotionMasterId, 2, x);
|
||||
});
|
||||
|
||||
foreach (byte shieldedId in ShieldedPlayers.Keys)
|
||||
{
|
||||
PlayerControl player = shieldedId.GetPlayer();
|
||||
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: player);
|
||||
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
|
||||
|
||||
sender.NotifyRolesSpecific(pc, player);
|
||||
hasValue = true;
|
||||
sender = RestartMessageIfTooLong();
|
||||
|
||||
sender.NotifyRolesSpecific(player, player);
|
||||
hasValue = true;
|
||||
sender = RestartMessageIfTooLong();
|
||||
}
|
||||
|
||||
sender.SendMessage(dispose: !hasValue);
|
||||
return;
|
||||
|
||||
CustomRpcSender RestartMessageIfTooLong()
|
||||
{
|
||||
if (sender.stream.Length > 800)
|
||||
{
|
||||
sender.SendMessage();
|
||||
sender = CustomRpcSender.Create("PotionMaster.OnFixedUpdate", SendOption.Reliable);
|
||||
hasValue = false;
|
||||
}
|
||||
|
||||
return sender;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -318,4 +318,9 @@ public class SabotageMaster : RoleBase
|
||||
sm.UsedSkillCount += UsesUsedWhenFixingLightsOrComms.GetFloat();
|
||||
sm.SendRPC();
|
||||
}
|
||||
|
||||
public override bool CanUseVent(PlayerControl pc, int ventId)
|
||||
{
|
||||
return !IsThisRole(pc) || pc.Is(CustomRoles.Nimble) || CanVent.GetBool();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user