mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-20 01:46:25 +00:00
Snowdown game mode + bug fixes
This commit is contained in:
1 parent
13e184be32
commit
1e6cbd62c0
29 files changed
+735
-81
No files matched your search
@@ -478,6 +478,9 @@ public enum CustomRoles
|
||||
|
||||
// Mingle
|
||||
MinglePlayer,
|
||||
|
||||
// Snowdown
|
||||
SnowdownPlayer,
|
||||
|
||||
// GM
|
||||
GM,
|
||||
|
||||
@@ -478,6 +478,9 @@ public enum CustomRoles
|
||||
|
||||
// Mingle
|
||||
MinglePlayer,
|
||||
|
||||
// Snowdown
|
||||
SnowdownPlayer,
|
||||
|
||||
// GM
|
||||
GM,
|
||||
|
||||
@@ -0,0 +1,481 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AmongUs.GameOptions;
|
||||
using UnityEngine;
|
||||
|
||||
namespace EHR;
|
||||
|
||||
public static class Snowdown
|
||||
{
|
||||
// Kill: Give the target a snowball
|
||||
// Vanish: Throw snowball in movement direction / Cycle to next powerup while in shop
|
||||
// Sabotage: Enter/Exit shop
|
||||
// Pet: Buy the selected powerup in the shop
|
||||
|
||||
public static float SnowballThrowSpeed = 4f;
|
||||
private static int SnowballGainFrequency = 5;
|
||||
private static int MaxSnowballsInHand = 5;
|
||||
private static int MaxCoinsInHand = 10;
|
||||
private static bool GameEndsAfterTime = true;
|
||||
private static int GameEndTime = 300;
|
||||
private static bool GameEndsWhenPointsReached = true;
|
||||
private static int PointsToReach = 5;
|
||||
private static Dictionary<PowerUp, int> PowerUpPrices = new()
|
||||
{
|
||||
[PowerUp.FillUp] = 3,
|
||||
[PowerUp.IncreaseCapacity] = 1,
|
||||
[PowerUp.FasterPickup] = 2
|
||||
};
|
||||
|
||||
private static OptionItem SnowballThrowSpeedOption;
|
||||
private static OptionItem SnowballGainFrequencyOption;
|
||||
private static OptionItem MaxSnowballsInHandOption;
|
||||
private static OptionItem MaxCoinsInHandOption;
|
||||
private static OptionItem GameEndsAfterTimeOption;
|
||||
private static OptionItem GameEndTimeOption;
|
||||
private static OptionItem GameEndsWhenPointsReachedOption;
|
||||
private static OptionItem PointsToReachOption;
|
||||
private static Dictionary<PowerUp, OptionItem> PowerUpPriceOptions = [];
|
||||
|
||||
public static Dictionary<byte, PlayerData> Data = [];
|
||||
private static List<Snowball> Snowballs = [];
|
||||
public static ((float Left, float Right) X, (float Bottom, float Top) Y) MapBounds;
|
||||
private static long GameStartTS;
|
||||
|
||||
private static readonly char[] Nums1 = "⓿❶❷❸❹❺❻❼❽❾❿".ToCharArray();
|
||||
private static readonly char[] Nums2 = "⓪①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳".ToCharArray();
|
||||
private static readonly char[] Nums3 = "⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽⑾⑿⒀⒁⒂⒃⒄⒅⒆⒇".ToCharArray();
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
var id = 69_225_001;
|
||||
Color color = Utils.GetRoleColor(CustomRoles.SnowdownPlayer);
|
||||
const CustomGameMode gameMode = CustomGameMode.Snowdown;
|
||||
const TabGroup tab = TabGroup.GameSettings;
|
||||
|
||||
SnowballThrowSpeedOption = new FloatOptionItem(id++, "Snowdown.SnowballThrowSpeedOption", new(0.25f, 10f, 0.25f), 4f, tab)
|
||||
.SetHeader(true)
|
||||
.SetColor(color)
|
||||
.SetGameMode(gameMode)
|
||||
.SetValueFormat(OptionFormat.Multiplier);
|
||||
|
||||
SnowballGainFrequencyOption = new IntegerOptionItem(id++, "Snowdown.SnowballGainFrequencyOption", new(1, 30, 1), 5, tab)
|
||||
.SetColor(color)
|
||||
.SetGameMode(gameMode)
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
|
||||
MaxSnowballsInHandOption = new IntegerOptionItem(id++, "Snowdown.MaxSnowballsInHandOption", new(1, 10, 1), 5, tab)
|
||||
.SetColor(color)
|
||||
.SetGameMode(gameMode)
|
||||
.SetValueFormat(OptionFormat.Pieces);
|
||||
|
||||
MaxCoinsInHandOption = new IntegerOptionItem(id++, "Snowdown.MaxCoinsInHandOption", new(1, 20, 1), 10, tab)
|
||||
.SetColor(color)
|
||||
.SetGameMode(gameMode)
|
||||
.SetValueFormat(OptionFormat.Pieces);
|
||||
|
||||
GameEndsAfterTimeOption = new BooleanOptionItem(id++, "Snowdown.GameEndsAfterTimeOption", true, tab)
|
||||
.SetColor(color)
|
||||
.SetGameMode(gameMode);
|
||||
|
||||
GameEndTimeOption = new IntegerOptionItem(id++, "Snowdown.GameEndTimeOption", new(15, 1800, 15), 300, tab)
|
||||
.SetColor(color)
|
||||
.SetGameMode(gameMode)
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
|
||||
GameEndsWhenPointsReachedOption = new BooleanOptionItem(id++, "Snowdown.GameEndsWhenPointsReachedOption", true, tab)
|
||||
.SetColor(color)
|
||||
.SetGameMode(gameMode);
|
||||
|
||||
PointsToReachOption = new IntegerOptionItem(id++, "Snowdown.PointsToReachOption", new(1, 100, 1), 5, tab)
|
||||
.SetColor(color)
|
||||
.SetGameMode(gameMode)
|
||||
.SetValueFormat(OptionFormat.Pieces);
|
||||
|
||||
PowerUpPriceOptions = Enum.GetValues<PowerUp>().ToDictionary(x => x, x => new IntegerOptionItem(id++, "Snowdown.PowerUpPriceOption", new(1, 20, 1), PowerUpPrices[x], tab)
|
||||
.SetColor(color)
|
||||
.SetGameMode(gameMode)
|
||||
.SetValueFormat(OptionFormat.Pieces)
|
||||
.AddReplacement(("{powerup}", Translator.GetString($"Snowdown.PowerUp.{x}"))));
|
||||
}
|
||||
|
||||
public static void ApplyGameOptions(IGameOptions opt, PlayerControl player)
|
||||
{
|
||||
AURoleOptions.PhantomCooldown = 0.1f;
|
||||
AURoleOptions.PhantomDuration = 0.1f;
|
||||
}
|
||||
|
||||
public static string GetSuffix(PlayerControl seer, PlayerControl target)
|
||||
{
|
||||
if (!Data.TryGetValue(seer.PlayerId, out PlayerData seerData) || !Data.TryGetValue(target.PlayerId, out PlayerData targetData)) return string.Empty;
|
||||
|
||||
if (seer.PlayerId == target.PlayerId)
|
||||
return seerData.GetSelfSuffix();
|
||||
|
||||
StringBuilder sb = new("<#ffffff>");
|
||||
AddStats(sb, targetData);
|
||||
sb.Append("</color>");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static void AddStats(StringBuilder sb, PlayerData targetData)
|
||||
{
|
||||
sb.Append("<#e4fdff>");
|
||||
sb.Append(Nums1[targetData.SnowballsReady]);
|
||||
sb.Append("</color>");
|
||||
|
||||
sb.Append(' ');
|
||||
|
||||
sb.Append("<#dfc57b>");
|
||||
sb.Append(Nums2[targetData.Coins]);
|
||||
sb.Append("</color>");
|
||||
|
||||
if (targetData.Points > 0)
|
||||
{
|
||||
sb.Append(' ');
|
||||
|
||||
sb.Append("<#e5acff>");
|
||||
sb.Append(Nums3[targetData.Points - 1]);
|
||||
sb.Append("</color>");
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetStatistics(byte id)
|
||||
{
|
||||
if (!Data.TryGetValue(id, out PlayerData data)) return string.Empty;
|
||||
StringBuilder sb = new("<#ffffff>");
|
||||
AddStats(sb, data);
|
||||
sb.Append("</color>");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string GetHudText()
|
||||
{
|
||||
if (!GameEndsAfterTime) return string.Empty;
|
||||
long timeLeft = GameEndTime - (Utils.TimeStamp - GameStartTS);
|
||||
return $"{timeLeft / 60:00}:{timeLeft % 60:00}";
|
||||
}
|
||||
|
||||
public static bool CheckGameEnd(out GameOverReason reason)
|
||||
{
|
||||
reason = GameOverReason.ImpostorsByKill;
|
||||
if (GameStates.IsEnded || !Main.IntroDestroyed) return false;
|
||||
PlayerControl[] aapc = Main.AllAlivePlayerControls;
|
||||
|
||||
switch (aapc.Length)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
PlayerControl winner = aapc[0];
|
||||
Logger.Info($"Winner: {winner.GetRealName().RemoveHtmlTags()}", "Snowdown");
|
||||
CustomWinnerHolder.WinnerIds = [winner.PlayerId];
|
||||
Main.DoBlockNameChange = true;
|
||||
return true;
|
||||
}
|
||||
case 0:
|
||||
{
|
||||
CustomWinnerHolder.ResetAndSetWinner(CustomWinner.None);
|
||||
Logger.Warn("No players alive. Force ending the game", "Snowdown");
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (GameEndsAfterTime && Utils.TimeStamp - GameStartTS >= GameEndTime)
|
||||
{
|
||||
int max = Data.Values.Max(x => x.Points);
|
||||
CustomWinnerHolder.WinnerIds = Data.Where(x => x.Value.Points == max && x.Key.GetPlayer() != null).Select(x => x.Key).ToHashSet();
|
||||
Logger.Info($"Winners: {(string.Join(", ", CustomWinnerHolder.WinnerIds.Select(x => Main.AllPlayerNames.GetValueOrDefault(x, "[Unknown player]"))))}", "Snowdown");
|
||||
Main.DoBlockNameChange = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GameEndsWhenPointsReached && Data.IntersectBy(Main.AllAlivePlayerControls.Select(p => p.PlayerId), x => x.Key).FindFirst(x => x.Value.Points >= PointsToReach, out var winnerData))
|
||||
{
|
||||
CustomWinnerHolder.WinnerIds = [winnerData.Key];
|
||||
Logger.Info($"Winners: {Main.AllPlayerNames.GetValueOrDefault(winnerData.Key, "[Unknown player]")}", "Snowdown");
|
||||
Main.DoBlockNameChange = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
SnowballThrowSpeed = SnowballThrowSpeedOption.GetFloat();
|
||||
SnowballGainFrequency = SnowballGainFrequencyOption.GetInt();
|
||||
MaxSnowballsInHand = MaxSnowballsInHandOption.GetInt();
|
||||
MaxCoinsInHand = MaxCoinsInHandOption.GetInt();
|
||||
GameEndsAfterTime = GameEndsAfterTimeOption.GetBool();
|
||||
GameEndTime = GameEndTimeOption.GetInt();
|
||||
GameEndsWhenPointsReached = GameEndsWhenPointsReachedOption.GetBool();
|
||||
PointsToReach = PointsToReachOption.GetInt();
|
||||
PowerUpPrices = PowerUpPriceOptions.ToDictionary(x => x.Key, x => x.Value.GetInt());
|
||||
|
||||
Data = Main.AllPlayerControls.ToDictionary(x => x.PlayerId, _ => new PlayerData());
|
||||
Snowballs = [];
|
||||
|
||||
Dictionary<SystemTypes, Vector2>.ValueCollection rooms = RandomSpawn.SpawnMap.GetSpawnMap().Positions?.Values;
|
||||
if (rooms == null) return;
|
||||
|
||||
float[] x = rooms.Select(r => r.x).ToArray();
|
||||
float[] y = rooms.Select(r => r.y).ToArray();
|
||||
|
||||
const float extend = 5f;
|
||||
MapBounds = ((x.Min() - extend, x.Max() + extend), (y.Min() - extend, y.Max() + extend));
|
||||
}
|
||||
|
||||
public static void GameStart() // Called as non-host client too!
|
||||
{
|
||||
GameStartTS = Utils.TimeStamp;
|
||||
}
|
||||
|
||||
public static void OnCheckMurder(PlayerControl killer, PlayerControl target)
|
||||
{
|
||||
if (!Data.TryGetValue(killer.PlayerId, out PlayerData killerData) || !Data.TryGetValue(target.PlayerId, out PlayerData targetData) || killerData.SnowballsReady < 1 || targetData.SnowballsReady >= targetData.MaxSnowballsReady) return;
|
||||
killerData.SnowballsReady--;
|
||||
targetData.SnowballsReady++;
|
||||
}
|
||||
|
||||
//[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.FixedUpdate))]
|
||||
public static class FixedUpdatePatch
|
||||
{
|
||||
public static void Postfix(PlayerControl __instance)
|
||||
{
|
||||
if (!AmongUsClient.Instance.AmHost || !GameStates.IsInTask || ExileController.Instance || AntiBlackout.SkipTasks || Options.CurrentGameMode != CustomGameMode.Snowdown || !Main.IntroDestroyed) return;
|
||||
if (!__instance.IsAlive() || !Data.TryGetValue(__instance.PlayerId, out PlayerData data)) return;
|
||||
|
||||
var now = Utils.TimeStamp;
|
||||
var pos = __instance.Pos();
|
||||
var touchingSnowball = Snowballs.Find(x => x.Thrower != __instance && Vector2.Distance(x.Position, pos) < 1.5f);
|
||||
|
||||
if (touchingSnowball != null)
|
||||
{
|
||||
touchingSnowball.Despawn();
|
||||
|
||||
if (touchingSnowball.Thrower != null && Data.TryGetValue(touchingSnowball.Thrower.PlayerId, out PlayerData throwerData) && throwerData.Coins < throwerData.MaxCoins)
|
||||
throwerData.Coins++;
|
||||
}
|
||||
|
||||
if (data.SnowballsReady < data.MaxSnowballsReady && now - data.LastSnowballGainTS >= data.SnowballGainInterval)
|
||||
{
|
||||
data.SnowballsReady++;
|
||||
data.LastSnowballGainTS = now;
|
||||
}
|
||||
|
||||
if (Vector2.Distance(pos, data.LastPosition) > 0.01f)
|
||||
{
|
||||
data.LastLastPosition = data.LastPosition;
|
||||
data.LastPosition = pos;
|
||||
}
|
||||
|
||||
foreach (PlayerControl target in Main.AllAlivePlayerControls)
|
||||
{
|
||||
string suffix = GetSuffix(__instance, target);
|
||||
|
||||
if (!data.LastSuffix.TryGetValue(target.PlayerId, out string lastSuffix))
|
||||
goto Skip;
|
||||
|
||||
if (lastSuffix != suffix)
|
||||
Utils.NotifyRoles(SpecifySeer: __instance, SpecifyTarget: target);
|
||||
|
||||
Skip:
|
||||
|
||||
data.LastSuffix[target.PlayerId] = suffix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PlayerData
|
||||
{
|
||||
public Vector2 LastPosition = new(0f, 0f);
|
||||
public Vector2 LastLastPosition = new(0f, 0f);
|
||||
public int SnowballsReady;
|
||||
public int MaxSnowballsReady = MaxSnowballsInHand;
|
||||
public long LastSnowballGainTS;
|
||||
public int SnowballGainInterval = SnowballGainFrequency;
|
||||
public int Coins;
|
||||
public int MaxCoins = MaxCoinsInHand;
|
||||
public bool InShop;
|
||||
private int ShopSelectedIndex;
|
||||
public int Points;
|
||||
private bool ShowHelp;
|
||||
public readonly Dictionary<byte, string> LastSuffix = [];
|
||||
|
||||
public void OnSabotage(PlayerControl pc)
|
||||
{
|
||||
InShop = (SnowballsReady != MaxSnowballsReady || MaxSnowballsReady < 20 || MaxCoins < 10 || SnowballGainInterval > 1) && !InShop;
|
||||
ShowHelp = !Main.HasPlayedGM[CustomGameMode.Snowdown].Contains(pc.FriendCode);
|
||||
if (pc.AmOwner) HudSpritePatch.ForceUpdate = true;
|
||||
}
|
||||
|
||||
public void OnPet(PlayerControl pc)
|
||||
{
|
||||
if (!InShop)
|
||||
{
|
||||
if (Coins >= 20)
|
||||
{
|
||||
Points++;
|
||||
Coins -= 20;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
PowerUp powerUp = Enum.GetValues<PowerUp>()[ShopSelectedIndex];
|
||||
int cost = PowerUpPrices[powerUp];
|
||||
if (Coins < cost) return;
|
||||
|
||||
switch (powerUp)
|
||||
{
|
||||
case PowerUp.FillUp:
|
||||
{
|
||||
if (SnowballsReady == MaxSnowballsReady) return;
|
||||
SnowballsReady = MaxSnowballsReady;
|
||||
break;
|
||||
}
|
||||
case PowerUp.IncreaseCapacity:
|
||||
{
|
||||
switch (MaxSnowballsReady, MaxCoins)
|
||||
{
|
||||
case (>= 10, >= 20):
|
||||
return;
|
||||
case (>= 10, < 20):
|
||||
MaxCoins++;
|
||||
break;
|
||||
case (< 10, >= 20):
|
||||
MaxSnowballsReady++;
|
||||
break;
|
||||
case (< 10, < 20):
|
||||
MaxSnowballsReady++;
|
||||
MaxCoins++;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PowerUp.FasterPickup:
|
||||
{
|
||||
if (SnowballGainInterval <= 1) return;
|
||||
SnowballGainInterval--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Coins -= cost;
|
||||
|
||||
if (SnowballsReady == MaxSnowballsReady && MaxSnowballsReady >= 20 && MaxCoins >= 10 && SnowballGainInterval <= 1)
|
||||
InShop = false;
|
||||
}
|
||||
|
||||
public void OnVanish(PlayerControl pc)
|
||||
{
|
||||
if (InShop)
|
||||
{
|
||||
ShopSelectedIndex++;
|
||||
|
||||
if (ShopSelectedIndex >= Enum.GetValues<PowerUp>().Length)
|
||||
ShopSelectedIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SnowballsReady <= 0) return;
|
||||
SnowballsReady--;
|
||||
Snowballs.Add(new Snowball(pc.Pos(), (LastPosition - LastLastPosition).normalized, pc));
|
||||
}
|
||||
}
|
||||
|
||||
public string GetSelfSuffix()
|
||||
{
|
||||
StringBuilder sb = new("<#ffffff><size=140%>");
|
||||
|
||||
AddStats(sb, this);
|
||||
|
||||
sb.Append("</size>");
|
||||
|
||||
if (InShop)
|
||||
{
|
||||
PowerUp powerUp = Enum.GetValues<PowerUp>()[ShopSelectedIndex];
|
||||
sb.Append('\n');
|
||||
sb.Append('\n');
|
||||
sb.Append(Translator.GetString($"Snowdown.PowerUp.{powerUp}"));
|
||||
sb.Append(' ');
|
||||
sb.Append("<#dfc57b>");
|
||||
sb.Append(Nums2[PowerUpPrices[powerUp]]);
|
||||
sb.Append("</color>");
|
||||
sb.Append('\n');
|
||||
sb.Append("<size=90%>");
|
||||
sb.Append(Translator.GetString($"Snowdown.PowerUp.{powerUp}.Description"));
|
||||
sb.Append("</size>");
|
||||
|
||||
if (ShowHelp)
|
||||
{
|
||||
sb.Append('\n');
|
||||
sb.Append('\n');
|
||||
sb.Append("<size=80%>");
|
||||
sb.Append(Translator.GetString("Snowdown.ShopHelp"));
|
||||
sb.Append("</size>");
|
||||
}
|
||||
}
|
||||
|
||||
sb.Append("</color>");
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public enum PowerUp
|
||||
{
|
||||
FillUp,
|
||||
IncreaseCapacity,
|
||||
FasterPickup
|
||||
}
|
||||
}
|
||||
|
||||
internal class SnowdownPlayer : RoleBase
|
||||
{
|
||||
public static bool On;
|
||||
|
||||
public override bool IsEnable => On;
|
||||
|
||||
public override void SetupCustomOption() { }
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
On = false;
|
||||
}
|
||||
|
||||
public override void Add(byte playerId)
|
||||
{
|
||||
On = true;
|
||||
}
|
||||
|
||||
public override bool CanUseSabotage(PlayerControl pc)
|
||||
{
|
||||
return pc.IsAlive();
|
||||
}
|
||||
|
||||
public override bool OnSabotage(PlayerControl pc)
|
||||
{
|
||||
if (Snowdown.Data.TryGetValue(pc.PlayerId, out Snowdown.PlayerData data))
|
||||
data.OnSabotage(pc);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool OnVanish(PlayerControl pc)
|
||||
{
|
||||
if (Snowdown.Data.TryGetValue(pc.PlayerId, out Snowdown.PlayerData data))
|
||||
data.OnVanish(pc);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void OnPet(PlayerControl pc)
|
||||
{
|
||||
if (Snowdown.Data.TryGetValue(pc.PlayerId, out Snowdown.PlayerData data))
|
||||
data.OnPet(pc);
|
||||
}
|
||||
}
|
||||
@@ -137,7 +137,8 @@ public class Main : BasePlugin
|
||||
[CustomGameMode.HideAndSeek] = [],
|
||||
[CustomGameMode.Speedrun] = [],
|
||||
[CustomGameMode.CaptureTheFlag] = [],
|
||||
[CustomGameMode.NaturalDisasters] = []
|
||||
[CustomGameMode.NaturalDisasters] = [],
|
||||
[CustomGameMode.Snowdown] = []
|
||||
};
|
||||
|
||||
public static Dictionary<CustomGameMode, Color> GameModeColors = [];
|
||||
@@ -258,7 +259,7 @@ public class Main : BasePlugin
|
||||
|
||||
foreach (PlayerControl pc in PlayerControl.AllPlayerControls)
|
||||
{
|
||||
if (pc == null || pc.PlayerId >= 254 || !pc.IsAlive() || pc.Data == null || (pc.Data.Disconnected && IntroDestroyed) || Pelican.IsEaten(pc.PlayerId)) continue;
|
||||
if (pc == null || pc.PlayerId >= 254 || !pc.IsAlive() || pc.Data == null || (pc.Data.Disconnected && IntroDestroyed) || Pelican.IsEaten(pc.PlayerId) || pc.Is(CustomRoles.GM)) continue;
|
||||
|
||||
result[i++] = pc;
|
||||
}
|
||||
@@ -776,6 +777,8 @@ public class Main : BasePlugin
|
||||
{ CustomRoles.Racer, "#AFAFAF" },
|
||||
// Mingle
|
||||
{ CustomRoles.MinglePlayer, "#FE9900" },
|
||||
// Snowdown
|
||||
{ CustomRoles.SnowdownPlayer, "#e4fdff" },
|
||||
// Hide And Seek
|
||||
{ CustomRoles.Seeker, "#ff1919" },
|
||||
{ CustomRoles.Hider, "#345eeb" },
|
||||
@@ -858,7 +861,8 @@ public class Main : BasePlugin
|
||||
[CustomGameMode.TheMindGame] = Color.yellow,
|
||||
[CustomGameMode.BedWars] = Utils.GetRoleColor(CustomRoles.BedWarsPlayer),
|
||||
[CustomGameMode.Deathrace] = Utils.GetRoleColor(CustomRoles.Racer),
|
||||
[CustomGameMode.Mingle] = Utils.GetRoleColor(CustomRoles.MinglePlayer)
|
||||
[CustomGameMode.Mingle] = Utils.GetRoleColor(CustomRoles.MinglePlayer),
|
||||
[CustomGameMode.Snowdown] = Utils.GetRoleColor(CustomRoles.SnowdownPlayer)
|
||||
};
|
||||
|
||||
IL2CPPChainloader.Instance.Finished += () =>
|
||||
|
||||
@@ -26,6 +26,7 @@ public static class AutoHaunt
|
||||
CustomGameMode.RoomRush => RoomRush.PointsSystem ? validPCs.MaxBy(x => RoomRush.GetPoints(x.PlayerId)) : validPCs.RandomElement(),
|
||||
CustomGameMode.KingOfTheZones => validPCs.MaxBy(x => KingOfTheZones.GetZoneTime(x.PlayerId)),
|
||||
CustomGameMode.Deathrace => validPCs.MaxBy(x => Deathrace.Data.TryGetValue(x.PlayerId, out var drData) ? drData.Lap : 0),
|
||||
CustomGameMode.Snowdown => validPCs.Where(x => Snowdown.Data.ContainsKey(x.PlayerId)).Select(x => (pc: x, data: Snowdown.Data[x.PlayerId])).OrderByDescending(x => x.data.Points).ThenBy(x => x.data.SnowballGainInterval).ThenByDescending(x => x.data.Coins).ThenByDescending(x => x.data.SnowballsReady).Select(x => x.pc).FirstOrDefault(),
|
||||
_ => validPCs.RandomElement()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -239,7 +239,9 @@ namespace EHR
|
||||
catch (Exception exception) { Utils.ThrowException(exception); }
|
||||
}
|
||||
|
||||
playerControl.RawSetName(sprite);
|
||||
try { playerControl.RawSetName("<size=14><br></size>" + sprite); }
|
||||
catch (Exception e) { Utils.ThrowException(e); }
|
||||
|
||||
string name = PlayerControl.LocalPlayer.Data.Outfits[PlayerOutfitType.Default].PlayerName;
|
||||
int colorId = PlayerControl.LocalPlayer.Data.Outfits[PlayerOutfitType.Default].ColorId;
|
||||
string hatId = PlayerControl.LocalPlayer.Data.Outfits[PlayerOutfitType.Default].HatId;
|
||||
@@ -285,6 +287,8 @@ namespace EHR
|
||||
}, 0.6f);
|
||||
}
|
||||
|
||||
playerControl.cosmetics.currentBodySprite.BodySprite.color = Color.clear;
|
||||
playerControl.cosmetics.colorBlindText.color = Color.clear;
|
||||
Position = position;
|
||||
Sprite = sprite;
|
||||
++MaxId;
|
||||
@@ -868,7 +872,7 @@ namespace EHR
|
||||
|
||||
public sealed class DeathracePowerUp : CustomNetObject
|
||||
{
|
||||
public Deathrace.PowerUp PowerUp;
|
||||
public readonly Deathrace.PowerUp PowerUp;
|
||||
|
||||
public DeathracePowerUp(Vector2 position, Deathrace.PowerUp powerUp)
|
||||
{
|
||||
@@ -897,6 +901,33 @@ namespace EHR
|
||||
CreateNetObject(Utils.ColorString(color, $"{icon}\n<size=80%>{Translator.GetString($"Deathrace.PowerUpDisplay.{powerUp}").ToUpper()}</size>"), position);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class Snowball : CustomNetObject
|
||||
{
|
||||
public PlayerControl Thrower;
|
||||
public Vector2 Direction;
|
||||
|
||||
public Snowball(Vector2 from, Vector2 direction, PlayerControl thrower)
|
||||
{
|
||||
Thrower = thrower;
|
||||
Direction = direction;
|
||||
CreateNetObject("<line-height=97%><cspace=0.16em><#0000>W</color><mark=#e4fdff>WWWW</mark><#0000>W</color>\n<mark=#e4fdff>WWWWWW</mark>\n<mark=#e4fdff>WWWWWW</mark>\n<mark=#e4fdff>WWWWWW</mark>\n<mark=#e4fdff>WWWWWW</mark>\n<#0000>W</color><mark=#e4fdff>WWWW</mark><#0000>W", from);
|
||||
}
|
||||
|
||||
protected override void OnFixedUpdate()
|
||||
{
|
||||
Vector2 newPos = Position + Direction * Time.fixedDeltaTime * Snowdown.SnowballThrowSpeed;
|
||||
|
||||
if ((PhysicsHelpers.AnythingBetween(Position, newPos, Constants.ShipOnlyMask, false)) ||
|
||||
newPos.x < Snowdown.MapBounds.X.Left || newPos.x > Snowdown.MapBounds.X.Right || newPos.y < Snowdown.MapBounds.Y.Bottom || newPos.y > Snowdown.MapBounds.Y.Top)
|
||||
{
|
||||
Despawn();
|
||||
return;
|
||||
}
|
||||
|
||||
TP(newPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.RawSetName))]
|
||||
|
||||
@@ -36,7 +36,8 @@ internal static class CustomRoleSelector
|
||||
{ CustomGameMode.TheMindGame, CustomRoles.TMGPlayer },
|
||||
{ CustomGameMode.BedWars, CustomRoles.BedWarsPlayer },
|
||||
{ CustomGameMode.Deathrace, CustomRoles.Racer },
|
||||
{ CustomGameMode.Mingle, CustomRoles.MinglePlayer }
|
||||
{ CustomGameMode.Mingle, CustomRoles.MinglePlayer },
|
||||
{ CustomGameMode.Snowdown, CustomRoles.SnowdownPlayer }
|
||||
};
|
||||
|
||||
public static void SelectCustomRoles()
|
||||
|
||||
@@ -73,7 +73,8 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.TMGPlayer or
|
||||
CustomRoles.BedWarsPlayer or
|
||||
CustomRoles.Racer or
|
||||
CustomRoles.MinglePlayer;
|
||||
CustomRoles.MinglePlayer or
|
||||
CustomRoles.SnowdownPlayer;
|
||||
}
|
||||
|
||||
public static RoleBase GetRoleClass(this CustomRoles role)
|
||||
@@ -470,6 +471,8 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.BedWarsPlayer => RoleTypes.Phantom,
|
||||
// Deathrace
|
||||
CustomRoles.Racer => RoleTypes.Phantom,
|
||||
// Snowdown
|
||||
CustomRoles.SnowdownPlayer => RoleTypes.Phantom,
|
||||
// Standard
|
||||
CustomRoles.Sheriff => UsePets && Sheriff.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Crusader => UsePets && Crusader.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
@@ -1052,6 +1055,7 @@ internal static class CustomRolesHelper
|
||||
or CustomRoles.CTFPlayer
|
||||
or CustomRoles.BedWarsPlayer
|
||||
or CustomRoles.Racer
|
||||
or CustomRoles.SnowdownPlayer
|
||||
or CustomRoles.Wizard
|
||||
or CustomRoles.AntiAdminer
|
||||
or CustomRoles.Stasis
|
||||
|
||||
@@ -355,7 +355,7 @@ internal static class ExtendedPlayerControl
|
||||
|
||||
RoleTypes newRoleType = state.MainRole.GetRoleTypes();
|
||||
|
||||
if (Options.CurrentGameMode is CustomGameMode.SoloPVP or CustomGameMode.FFA or CustomGameMode.CaptureTheFlag or CustomGameMode.KingOfTheZones or CustomGameMode.BedWars)
|
||||
if (Options.CurrentGameMode is CustomGameMode.SoloPVP or CustomGameMode.FFA or CustomGameMode.CaptureTheFlag or CustomGameMode.KingOfTheZones or CustomGameMode.BedWars or CustomGameMode.Snowdown)
|
||||
hasValue |= sender.RpcSetRole(player, newRoleType, player.OwnerId);
|
||||
|
||||
player.ResetKillCooldown();
|
||||
@@ -1081,7 +1081,7 @@ internal static class ExtendedPlayerControl
|
||||
{
|
||||
try
|
||||
{
|
||||
bool addRoleName = GameStates.IsInGame && Options.CurrentGameMode is not CustomGameMode.FFA and not CustomGameMode.StopAndGo and not CustomGameMode.HotPotato and not CustomGameMode.Speedrun and not CustomGameMode.CaptureTheFlag and not CustomGameMode.NaturalDisasters and not CustomGameMode.RoomRush and not CustomGameMode.Quiz and not CustomGameMode.TheMindGame and not CustomGameMode.BedWars and not CustomGameMode.Deathrace and not CustomGameMode.Mingle;
|
||||
bool addRoleName = GameStates.IsInGame && Options.CurrentGameMode is not CustomGameMode.FFA and not CustomGameMode.StopAndGo and not CustomGameMode.HotPotato and not CustomGameMode.Speedrun and not CustomGameMode.CaptureTheFlag and not CustomGameMode.NaturalDisasters and not CustomGameMode.RoomRush and not CustomGameMode.Quiz and not CustomGameMode.TheMindGame and not CustomGameMode.BedWars and not CustomGameMode.Deathrace and not CustomGameMode.Mingle and not CustomGameMode.Snowdown;
|
||||
return $"{player?.Data?.PlayerName}" + (addRoleName ? $" ({player?.GetAllRoleName(forUser).RemoveHtmlTags().Replace('\n', ' ')})" : string.Empty);
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -1365,6 +1365,7 @@ internal static class ExtendedPlayerControl
|
||||
case CustomGameMode.CaptureTheFlag:
|
||||
case CustomGameMode.BedWars:
|
||||
case CustomGameMode.Deathrace:
|
||||
case CustomGameMode.Snowdown:
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1425,6 +1426,7 @@ internal static class ExtendedPlayerControl
|
||||
CustomGameMode.Quiz => false,
|
||||
CustomGameMode.TheMindGame => false,
|
||||
CustomGameMode.Mingle => false,
|
||||
CustomGameMode.Snowdown => true,
|
||||
CustomGameMode.Deathrace => Deathrace.CanUseVent(pc, pc.GetClosestVent().Id),
|
||||
|
||||
CustomGameMode.Standard when CopyCat.Instances.Any(x => x.CopyCatPC.PlayerId == pc.PlayerId) => true,
|
||||
@@ -1735,6 +1737,7 @@ internal static class ExtendedPlayerControl
|
||||
CustomRoles.QuizPlayer => 3f,
|
||||
CustomRoles.BedWarsPlayer => 1f,
|
||||
CustomRoles.Racer => 3f,
|
||||
CustomRoles.SnowdownPlayer => 1f,
|
||||
_ when player.Is(CustomRoles.Underdog) => Main.AllAlivePlayerControls.Length <= Underdog.UnderdogMaximumPlayersNeededToKill.GetInt() ? Underdog.UnderdogKillCooldownWithLessPlayersAlive.GetInt() : Underdog.UnderdogKillCooldownWithMorePlayersAlive.GetInt(),
|
||||
_ => Main.AllPlayerKillCooldown[player.PlayerId]
|
||||
};
|
||||
|
||||
@@ -175,6 +175,9 @@ public static class FixedUpdateCaller
|
||||
case CustomGameMode.BedWars:
|
||||
BedWars.FixedUpdatePatch.Postfix(pc);
|
||||
break;
|
||||
case CustomGameMode.Snowdown:
|
||||
Snowdown.FixedUpdatePatch.Postfix(pc);
|
||||
break;
|
||||
}
|
||||
|
||||
CheckInvalidMovementPatch.Postfix(pc);
|
||||
|
||||
@@ -171,6 +171,11 @@ public sealed class PlayerGameOptionsSender(PlayerControl player) : GameOptionsS
|
||||
CaptureTheFlag.ApplyGameOptions();
|
||||
goto case CustomGameMode.RoomRush;
|
||||
}
|
||||
case CustomGameMode.Snowdown:
|
||||
{
|
||||
Snowdown.ApplyGameOptions(opt, player);
|
||||
goto case CustomGameMode.RoomRush;
|
||||
}
|
||||
case CustomGameMode.NaturalDisasters:
|
||||
{
|
||||
SetMaxVision();
|
||||
|
||||
@@ -46,6 +46,7 @@ public static class NameColorManager
|
||||
if (FreeForAll.PlayerTeams.TryGetValue(target.PlayerId, out int team))
|
||||
color = FreeForAll.TeamColors.GetValueOrDefault(team, "#00ffff");
|
||||
return true;
|
||||
case CustomGameMode.Snowdown:
|
||||
case CustomGameMode.Mingle:
|
||||
case CustomGameMode.RoomRush:
|
||||
case CustomGameMode.NaturalDisasters:
|
||||
|
||||
+10
-3
@@ -35,6 +35,7 @@ public enum CustomGameMode
|
||||
BedWars = 0x0E,
|
||||
Deathrace = 0x0F,
|
||||
Mingle = 0x10,
|
||||
Snowdown = 0x11,
|
||||
All = int.MaxValue
|
||||
}
|
||||
|
||||
@@ -88,7 +89,8 @@ public static class Options
|
||||
"TheMindGame",
|
||||
"BedWars",
|
||||
"Deathrace",
|
||||
"Mingle"
|
||||
"Mingle",
|
||||
"Snowdown"
|
||||
];
|
||||
|
||||
private static Dictionary<CustomRoles, int> roleCounts;
|
||||
@@ -919,6 +921,7 @@ public static class Options
|
||||
13 => CustomGameMode.BedWars,
|
||||
14 => CustomGameMode.Deathrace,
|
||||
15 => CustomGameMode.Mingle,
|
||||
16 => CustomGameMode.Snowdown,
|
||||
_ => CustomGameMode.Standard
|
||||
};
|
||||
|
||||
@@ -1841,6 +1844,8 @@ public static class Options
|
||||
Deathrace.SetupCustomOption();
|
||||
// Mingle
|
||||
Mingle.SetupCustomOption();
|
||||
// Snowdown
|
||||
Snowdown.SetupCustomOption();
|
||||
|
||||
yield return null;
|
||||
|
||||
@@ -3205,10 +3210,11 @@ public static class Options
|
||||
|
||||
foreach (CustomGameMode customGameMode in Enum.GetValues<CustomGameMode>()[..^1])
|
||||
{
|
||||
OptionItem chanceToSelectGMInGroup = new IntegerOptionItem(id++, $"AGMR.RandomGroup.GMChance.{customGameMode}", new(0, 100, 5), 50, TabGroup.SystemSettings)
|
||||
OptionItem chanceToSelectGMInGroup = new IntegerOptionItem(id++, $"AGMR.RandomGroup.GMChance", new(0, 100, 5), 50, TabGroup.SystemSettings)
|
||||
.SetParent(EnableAutoGMRotation)
|
||||
.SetValueFormat(OptionFormat.Percent)
|
||||
.SetColor(Main.GameModeColors[customGameMode]);
|
||||
.SetColor(Main.GameModeColors[customGameMode])
|
||||
.AddReplacement(("{gm}", Translator.GetString($"{customGameMode}")));
|
||||
|
||||
dict[customGameMode] = chanceToSelectGMInGroup;
|
||||
}
|
||||
@@ -3291,6 +3297,7 @@ public static class Options
|
||||
13 => CustomGameMode.BedWars,
|
||||
14 => CustomGameMode.Deathrace,
|
||||
15 => CustomGameMode.Mingle,
|
||||
16 => CustomGameMode.Snowdown,
|
||||
_ => CustomGameMode.Standard
|
||||
};
|
||||
AutoGMRotationCompiled.AddRange(Enumerable.Repeat(gm, times));
|
||||
|
||||
+20
-8
@@ -822,6 +822,7 @@ public static class Utils
|
||||
case CustomGameMode.BedWars:
|
||||
case CustomGameMode.Deathrace:
|
||||
case CustomGameMode.Mingle:
|
||||
case CustomGameMode.Snowdown:
|
||||
return false;
|
||||
case CustomGameMode.HideAndSeek:
|
||||
return CustomHnS.HasTasks(p);
|
||||
@@ -1046,7 +1047,7 @@ public static class Utils
|
||||
{
|
||||
switch (Options.CurrentGameMode)
|
||||
{
|
||||
case CustomGameMode.CaptureTheFlag or CustomGameMode.NaturalDisasters or CustomGameMode.RoomRush or CustomGameMode.KingOfTheZones or CustomGameMode.Quiz or CustomGameMode.TheMindGame or CustomGameMode.BedWars or CustomGameMode.Deathrace or CustomGameMode.Mingle:
|
||||
case CustomGameMode.CaptureTheFlag or CustomGameMode.NaturalDisasters or CustomGameMode.RoomRush or CustomGameMode.KingOfTheZones or CustomGameMode.Quiz or CustomGameMode.TheMindGame or CustomGameMode.BedWars or CustomGameMode.Deathrace or CustomGameMode.Mingle or CustomGameMode.Snowdown:
|
||||
case CustomGameMode.Standard when IsRevivingRoleAlive() && Main.DiedThisRound.Contains(PlayerControl.LocalPlayer.PlayerId):
|
||||
return PlayerControl.LocalPlayer.Is(CustomRoles.GM);
|
||||
case CustomGameMode.FFA or CustomGameMode.SoloPVP or CustomGameMode.StopAndGo or CustomGameMode.HotPotato or CustomGameMode.Speedrun:
|
||||
@@ -1551,6 +1552,7 @@ public static class Utils
|
||||
}
|
||||
|
||||
break;
|
||||
case CustomGameMode.Snowdown:
|
||||
case CustomGameMode.Mingle:
|
||||
case CustomGameMode.Deathrace:
|
||||
case CustomGameMode.BedWars:
|
||||
@@ -2176,6 +2178,7 @@ public static class Utils
|
||||
CustomGameMode.BedWars => ColorString(GetRoleColor(CustomRoles.BedWarsPlayer), $"{modeText}\r\n") + name,
|
||||
CustomGameMode.Deathrace => ColorString(GetRoleColor(CustomRoles.Racer), $"{modeText}\r\n") + name,
|
||||
CustomGameMode.Mingle => ColorString(GetRoleColor(CustomRoles.MinglePlayer), $"{modeText}\r\n") + name,
|
||||
CustomGameMode.Snowdown => ColorString(GetRoleColor(CustomRoles.SnowdownPlayer), $"{modeText}\r\n") + name,
|
||||
_ => name
|
||||
};
|
||||
}
|
||||
@@ -2641,13 +2644,16 @@ public static class Utils
|
||||
case CustomGameMode.Mingle:
|
||||
additionalSuffixes.Add(Mingle.GetSuffix(seer));
|
||||
break;
|
||||
case CustomGameMode.Snowdown:
|
||||
additionalSuffixes.Add(Snowdown.GetSuffix(seer, seer));
|
||||
break;
|
||||
}
|
||||
|
||||
List<string> addSuff = additionalSuffixes.ConvertAll(x => x.Trim()).FindAll(x => !string.IsNullOrEmpty(x));
|
||||
|
||||
if (addSuff.Count > 0)
|
||||
{
|
||||
if (SelfSuffix.Length > 0 && SelfSuffix[^1] != '\n')
|
||||
if (SelfSuffix.ToString().RemoveHtmlTags().Length > 0 && SelfSuffix[^1] != '\n')
|
||||
SelfSuffix.Append('\n');
|
||||
|
||||
SelfSuffix.Append(string.Join('\n', addSuff));
|
||||
@@ -2664,7 +2670,7 @@ public static class Utils
|
||||
if ((Options.CurrentGameMode == CustomGameMode.FFA && FreeForAll.FFATeamMode.GetBool()) || Options.CurrentGameMode == CustomGameMode.HotPotato)
|
||||
seerRealName = seerRealName.ApplyNameColorData(seer, seer, forMeeting);
|
||||
|
||||
if (!forMeeting && MeetingStates.FirstMeeting && Options.ChangeNameToRoleInfo.GetBool() && Options.CurrentGameMode is not CustomGameMode.FFA and not CustomGameMode.StopAndGo and not CustomGameMode.HotPotato and not CustomGameMode.Speedrun and not CustomGameMode.CaptureTheFlag and not CustomGameMode.NaturalDisasters and not CustomGameMode.RoomRush and not CustomGameMode.KingOfTheZones and not CustomGameMode.Quiz and not CustomGameMode.TheMindGame and not CustomGameMode.BedWars and not CustomGameMode.Deathrace and not CustomGameMode.Mingle)
|
||||
if (!forMeeting && MeetingStates.FirstMeeting && Options.ChangeNameToRoleInfo.GetBool() && Options.CurrentGameMode is not CustomGameMode.FFA and not CustomGameMode.StopAndGo and not CustomGameMode.HotPotato and not CustomGameMode.Speedrun and not CustomGameMode.CaptureTheFlag and not CustomGameMode.NaturalDisasters and not CustomGameMode.RoomRush and not CustomGameMode.KingOfTheZones and not CustomGameMode.Quiz and not CustomGameMode.TheMindGame and not CustomGameMode.BedWars and not CustomGameMode.Deathrace and not CustomGameMode.Mingle and not CustomGameMode.Snowdown)
|
||||
{
|
||||
CustomTeamManager.CustomTeam team = CustomTeamManager.GetCustomTeam(seer.PlayerId);
|
||||
|
||||
@@ -2702,7 +2708,7 @@ public static class Utils
|
||||
SelfSuffix.Append($"\n\n<#ffffff>{GetString($"GameModeTutorial.{Options.CurrentGameMode}")}</color>\n");
|
||||
}
|
||||
|
||||
bool noRoleText = GameStates.IsLobby || Options.CurrentGameMode is CustomGameMode.CaptureTheFlag or CustomGameMode.NaturalDisasters or CustomGameMode.RoomRush or CustomGameMode.KingOfTheZones or CustomGameMode.Quiz or CustomGameMode.TheMindGame or CustomGameMode.BedWars or CustomGameMode.Deathrace or CustomGameMode.Mingle;
|
||||
bool noRoleText = GameStates.IsLobby || Options.CurrentGameMode is CustomGameMode.CaptureTheFlag or CustomGameMode.NaturalDisasters or CustomGameMode.RoomRush or CustomGameMode.KingOfTheZones or CustomGameMode.Quiz or CustomGameMode.TheMindGame or CustomGameMode.BedWars or CustomGameMode.Deathrace or CustomGameMode.Mingle or CustomGameMode.Snowdown;
|
||||
|
||||
// Combine the seer's job title and SelfTaskText with the seer's player name and SelfMark
|
||||
string selfRoleName = noRoleText ? string.Empty : $"<size={fontSize}>{seer.GetDisplayRoleName()}{selfTaskText}</size>";
|
||||
@@ -2756,7 +2762,7 @@ public static class Utils
|
||||
break;
|
||||
}
|
||||
|
||||
selfName += SelfSuffix.ToString() == string.Empty ? string.Empty : $"\r\n{SelfSuffix}";
|
||||
selfName += SelfSuffix.ToString() == string.Empty ? string.Empty : $"\r\n{SelfSuffix.ToString().Trim()}";
|
||||
if (!forMeeting) selfName += "\r\n";
|
||||
}
|
||||
|
||||
@@ -2879,7 +2885,7 @@ public static class Utils
|
||||
if (IsRevivingRoleAlive() && Main.DiedThisRound.Contains(seer.PlayerId))
|
||||
targetRoleText = string.Empty;
|
||||
|
||||
if (Options.CurrentGameMode is CustomGameMode.CaptureTheFlag or CustomGameMode.NaturalDisasters or CustomGameMode.RoomRush or CustomGameMode.KingOfTheZones or CustomGameMode.Quiz or CustomGameMode.TheMindGame or CustomGameMode.BedWars or CustomGameMode.Deathrace or CustomGameMode.Mingle)
|
||||
if (Options.CurrentGameMode is CustomGameMode.CaptureTheFlag or CustomGameMode.NaturalDisasters or CustomGameMode.RoomRush or CustomGameMode.KingOfTheZones or CustomGameMode.Quiz or CustomGameMode.TheMindGame or CustomGameMode.BedWars or CustomGameMode.Deathrace or CustomGameMode.Mingle or CustomGameMode.Snowdown)
|
||||
targetRoleText = string.Empty;
|
||||
|
||||
if (!GameStates.IsLobby)
|
||||
@@ -2991,6 +2997,9 @@ public static class Utils
|
||||
case CustomGameMode.Deathrace:
|
||||
additionalSuffixes.Add(Deathrace.GetSuffix(seer, target, false));
|
||||
break;
|
||||
case CustomGameMode.Snowdown:
|
||||
additionalSuffixes.Add(Snowdown.GetSuffix(seer, target));
|
||||
break;
|
||||
}
|
||||
|
||||
if (MeetingStates.FirstMeeting && Main.ShieldPlayer == target.FriendCode && !string.IsNullOrEmpty(target.FriendCode) && Options.CurrentGameMode is CustomGameMode.Standard or CustomGameMode.FFA or CustomGameMode.Speedrun)
|
||||
@@ -3008,7 +3017,7 @@ public static class Utils
|
||||
|
||||
if (addSuff.Count > 0)
|
||||
{
|
||||
if (TargetSuffix.Length > 0 && TargetSuffix[^1] != '\n')
|
||||
if (TargetSuffix.ToString().RemoveHtmlTags().Length > 0 && TargetSuffix[^1] != '\n')
|
||||
TargetSuffix.Append('\n');
|
||||
|
||||
TargetSuffix.Append(string.Join('\n', addSuff));
|
||||
@@ -3027,7 +3036,7 @@ public static class Utils
|
||||
targetPlayerName = EmptyMessage;
|
||||
|
||||
var targetName = $"{targetRoleText}{targetPlayerName}{targetDeathReason}{TargetMark}";
|
||||
targetName += GameStates.IsLobby || TargetSuffix.ToString() == string.Empty ? string.Empty : $"{newLineBeforeSuffix}{TargetSuffix}";
|
||||
targetName += GameStates.IsLobby || TargetSuffix.ToString() == string.Empty ? string.Empty : $"{newLineBeforeSuffix}{TargetSuffix.ToString().Trim()}";
|
||||
|
||||
// Camouflage
|
||||
if (Camouflage.IsCamouflage && !camouflageIsForMeeting) targetName = $"<size=0>{targetName}</size>";
|
||||
@@ -3989,6 +3998,9 @@ public static class Utils
|
||||
int time3 = Mingle.GetSurvivalTime(id);
|
||||
summary = $"{ColorString(Main.PlayerColors[id], name)} - <#e8cd46>{GetString("SurvivedTimePrefix")}: <#ffffff>{(time3 == 0 ? $"{GetString("SurvivedUntilTheEnd")}</color>" : $"{time3}</color>s")}</color> ({GetVitalText(id, true)})";
|
||||
break;
|
||||
case CustomGameMode.Snowdown:
|
||||
summary = $"{ColorString(Main.PlayerColors[id], name)} - {Snowdown.GetStatistics(id)}";
|
||||
break;
|
||||
}
|
||||
|
||||
return check && GetDisplayRoleName(id, true).RemoveHtmlTags().Contains("INVALID:NotAssigned")
|
||||
|
||||
@@ -560,6 +560,11 @@ internal static class GameEndChecker
|
||||
Predicate = new MingleGameEndPredicate();
|
||||
}
|
||||
|
||||
public static void SetPredicateToSnowdown()
|
||||
{
|
||||
Predicate = new SnowdownGameEndPredicate();
|
||||
}
|
||||
|
||||
private class NormalGameEndPredicate : GameEndPredicate
|
||||
{
|
||||
public override bool CheckForGameEnd(out GameOverReason reason)
|
||||
@@ -1133,6 +1138,20 @@ internal static class GameEndChecker
|
||||
return Mingle.CheckGameEnd(out reason);
|
||||
}
|
||||
}
|
||||
|
||||
private class SnowdownGameEndPredicate : GameEndPredicate
|
||||
{
|
||||
public override bool CheckForGameEnd(out GameOverReason reason)
|
||||
{
|
||||
reason = GameOverReason.ImpostorsByKill;
|
||||
return WinnerIds.Count <= 0 && CheckGameEndByLivingPlayers(out reason);
|
||||
}
|
||||
|
||||
private static bool CheckGameEndByLivingPlayers(out GameOverReason reason)
|
||||
{
|
||||
return Snowdown.CheckGameEnd(out reason);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class GameEndPredicate
|
||||
{
|
||||
|
||||
@@ -1167,6 +1167,7 @@ public static class GameSettingMenuPatch
|
||||
Vector3 gameSettingsLabelPos = gameSettingsLabel.transform.localPosition;
|
||||
|
||||
CustomGameMode[] gms = Enum.GetValues<CustomGameMode>()[..^1];
|
||||
gms = gms.Without(CustomGameMode.TheMindGame).ToArray();
|
||||
if (SubmergedCompatibility.Loaded && Main.NormalOptions.MapId == 6) gms = gms.Where(SubmergedCompatibility.IsSupported).ToArray();
|
||||
int totalCols = Mathf.Max(1, Mathf.CeilToInt(gms.Length / 7f));
|
||||
|
||||
|
||||
@@ -250,6 +250,9 @@ internal static class HudManagerPatch
|
||||
case CustomRoles.RRPlayer when __instance.AbilityButton != null && RoomRush.VentLimit.TryGetValue(PlayerControl.LocalPlayer.PlayerId, out int ventLimit):
|
||||
__instance.AbilityButton.SetUsesRemaining(ventLimit);
|
||||
break;
|
||||
case CustomRoles.SnowdownPlayer:
|
||||
__instance.AbilityButton?.OverrideText(GetString("SnowdownButtonText"));
|
||||
break;
|
||||
}
|
||||
|
||||
if (role.PetActivatedAbility() && Options.CurrentGameMode == CustomGameMode.Standard && player.GetRoleTypes() != RoleTypes.Engineer && !role.OnlySpawnsWithPets() && !role.AlwaysUsesPhantomBase() && !player.GetCustomSubRoles().Any(StartGameHostPatch.BasisChangingAddons.ContainsKey) && role is not CustomRoles.Changeling and not CustomRoles.Ninja and not CustomRoles.Duality && (!role.SimpleAbilityTrigger() || !Options.UsePhantomBasis.GetBool() || !(player.IsNeutralKiller() && Options.UsePhantomBasisForNKs.GetBool())) && !(Options.UseMeetingShapeshift.GetBool() && player.UsesMeetingShapeshift()))
|
||||
@@ -275,6 +278,7 @@ internal static class HudManagerPatch
|
||||
CustomGameMode.HideAndSeek when player.IsHost() => CustomHnS.GetSuffixText(player, player, true),
|
||||
CustomGameMode.NaturalDisasters => NaturalDisasters.SuffixText(),
|
||||
CustomGameMode.Deathrace => Deathrace.GetSuffix(player, player, true),
|
||||
CustomGameMode.Snowdown => Snowdown.GetHudText(),
|
||||
CustomGameMode.Standard => state.Role.GetSuffix(player, player, true, GameStates.IsMeeting) + GetAddonSuffixes(),
|
||||
_ => string.Empty
|
||||
};
|
||||
@@ -575,6 +579,14 @@ internal static class SetHudActivePatch
|
||||
|
||||
switch (Options.CurrentGameMode)
|
||||
{
|
||||
case CustomGameMode.Snowdown:
|
||||
__instance.AbilityButton?.ToggleVisible(true);
|
||||
__instance.ReportButton?.ToggleVisible(false);
|
||||
__instance.KillButton?.ToggleVisible(true);
|
||||
__instance.ImpostorVentButton?.ToggleVisible(true);
|
||||
__instance.SabotageButton?.ToggleVisible(true);
|
||||
__instance.PetButton?.ToggleVisible(true);
|
||||
return;
|
||||
case CustomGameMode.BedWars:
|
||||
__instance.AbilityButton?.ToggleVisible(true);
|
||||
__instance.ReportButton?.ToggleVisible(false);
|
||||
|
||||
@@ -49,6 +49,11 @@ public static class HudSpritePatch
|
||||
|
||||
switch (player.GetCustomRole())
|
||||
{
|
||||
case CustomRoles.SnowdownPlayer when Snowdown.Data.TryGetValue(player.PlayerId, out Snowdown.PlayerData snowdownData) && !snowdownData.InShop:
|
||||
{
|
||||
newAbilityButton = CustomButton.Get("Snowdown");
|
||||
break;
|
||||
}
|
||||
case CustomRoles.CTFPlayer:
|
||||
{
|
||||
newAbilityButton = CustomButton.Get("Tag");
|
||||
|
||||
+36
-12
@@ -301,6 +301,16 @@ internal static class SetUpRoleTextPatch
|
||||
__instance.RoleBlurbText.text = GetString("MinglePlayerInfo");
|
||||
break;
|
||||
}
|
||||
case CustomGameMode.Snowdown:
|
||||
{
|
||||
Color color = Utils.GetRoleColor(CustomRoles.SnowdownPlayer);
|
||||
__instance.YouAreText.transform.gameObject.SetActive(false);
|
||||
__instance.RoleText.text = GetString("SnowdownPlayer");
|
||||
__instance.RoleText.color = color;
|
||||
__instance.RoleBlurbText.color = color;
|
||||
__instance.RoleBlurbText.text = GetString("SnowdownPlayerInfo");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
CustomRoles role = lp.GetCustomRole();
|
||||
@@ -992,6 +1002,15 @@ internal static class BeginCrewmatePatch
|
||||
__instance.ImpostorText.text = GetString("MinglePlayerInfo");
|
||||
break;
|
||||
}
|
||||
case CustomGameMode.Snowdown:
|
||||
{
|
||||
__instance.TeamTitle.text = GetString("SnowdownPlayer");
|
||||
__instance.TeamTitle.color = __instance.BackgroundBar.material.color = Utils.GetRoleColor(CustomRoles.SnowdownPlayer);
|
||||
PlayerControl.LocalPlayer.Data.Role.IntroSound = GetIntroSound(RoleTypes.Detective);
|
||||
__instance.ImpostorText.gameObject.SetActive(true);
|
||||
__instance.ImpostorText.text = GetString("SnowdownPlayerInfo");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -1116,16 +1135,6 @@ internal static class IntroCutsceneDestroyPatch
|
||||
|
||||
if (Main.NormalOptions.MapId != 4)
|
||||
{
|
||||
foreach (PlayerControl pc in aapc)
|
||||
{
|
||||
pc.RpcResetAbilityCooldown();
|
||||
|
||||
if (pc.GetCustomRole().UsesPetInsteadOfKill())
|
||||
pc.AddAbilityCD(10);
|
||||
else
|
||||
pc.AddAbilityCD(false);
|
||||
}
|
||||
|
||||
if (Options.CurrentGameMode == CustomGameMode.Standard)
|
||||
{
|
||||
if (Options.FixFirstKillCooldown.GetBool())
|
||||
@@ -1167,8 +1176,17 @@ internal static class IntroCutsceneDestroyPatch
|
||||
|
||||
LateTask.New(() =>
|
||||
{
|
||||
lp.RpcResetAbilityCooldown();
|
||||
lp.SetKillCooldown(10f);
|
||||
|
||||
foreach (PlayerControl pc in aapc)
|
||||
{
|
||||
pc.RpcResetAbilityCooldown();
|
||||
|
||||
if (pc.GetCustomRole().UsesPetInsteadOfKill())
|
||||
pc.AddAbilityCD(10);
|
||||
else
|
||||
pc.AddAbilityCD(false);
|
||||
}
|
||||
}, 0.8f, log: false);
|
||||
|
||||
StartGameHostPatch.RpcSetRoleReplacer.SetActualSelfRolesAfterOverride();
|
||||
@@ -1186,7 +1204,7 @@ internal static class IntroCutsceneDestroyPatch
|
||||
}
|
||||
}, 0.1f, log: false);
|
||||
|
||||
if (Options.UsePets.GetBool() && Options.CurrentGameMode is CustomGameMode.Standard or CustomGameMode.HideAndSeek or CustomGameMode.CaptureTheFlag or CustomGameMode.BedWars)
|
||||
if (Options.UsePets.GetBool() && Options.CurrentGameMode is CustomGameMode.Standard or CustomGameMode.HideAndSeek or CustomGameMode.CaptureTheFlag or CustomGameMode.BedWars or CustomGameMode.Snowdown)
|
||||
{
|
||||
void GrantPetForEveryone()
|
||||
{
|
||||
@@ -1309,6 +1327,9 @@ internal static class IntroCutsceneDestroyPatch
|
||||
case CustomGameMode.Mingle:
|
||||
Main.Instance.StartCoroutine(Mingle.GameStart());
|
||||
break;
|
||||
case CustomGameMode.Snowdown:
|
||||
Snowdown.GameStart();
|
||||
break;
|
||||
}
|
||||
|
||||
Utils.CheckAndSetVentInteractions();
|
||||
@@ -1322,6 +1343,9 @@ internal static class IntroCutsceneDestroyPatch
|
||||
{
|
||||
foreach (PlayerControl player in Main.AllPlayerControls)
|
||||
Main.PlayerStates[player.PlayerId].InitTask(player);
|
||||
|
||||
if (Options.CurrentGameMode == CustomGameMode.Snowdown)
|
||||
Snowdown.GameStart();
|
||||
}
|
||||
|
||||
Logger.Info("OnDestroy", "IntroCutscene");
|
||||
|
||||
@@ -1047,6 +1047,9 @@ internal static class StartGameHostPatch
|
||||
case CustomGameMode.Deathrace:
|
||||
Deathrace.Init();
|
||||
goto default;
|
||||
case CustomGameMode.Snowdown:
|
||||
Snowdown.Init();
|
||||
goto default;
|
||||
default:
|
||||
if (Options.IntegrateNaturalDisasters.GetBool()) goto case CustomGameMode.NaturalDisasters;
|
||||
break;
|
||||
@@ -1116,6 +1119,9 @@ internal static class StartGameHostPatch
|
||||
case CustomGameMode.Mingle:
|
||||
GameEndChecker.SetPredicateToMingle();
|
||||
break;
|
||||
case CustomGameMode.Snowdown:
|
||||
GameEndChecker.SetPredicateToSnowdown();
|
||||
break;
|
||||
}
|
||||
|
||||
// Add players with unclassified roles to the list of players who require ResetCam.
|
||||
|
||||
+10
-1
@@ -66,7 +66,7 @@ internal static class EndGamePatch
|
||||
|
||||
byte killerId = value.GetRealKiller();
|
||||
bool gmIsFm = Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.StopAndGo;
|
||||
bool gmIsFmhh = gmIsFm || Options.CurrentGameMode is CustomGameMode.HotPotato or CustomGameMode.HideAndSeek or CustomGameMode.Speedrun or CustomGameMode.CaptureTheFlag or CustomGameMode.NaturalDisasters or CustomGameMode.RoomRush or CustomGameMode.KingOfTheZones or CustomGameMode.Quiz or CustomGameMode.TheMindGame or CustomGameMode.BedWars or CustomGameMode.Deathrace or CustomGameMode.Mingle;
|
||||
bool gmIsFmhh = gmIsFm || Options.CurrentGameMode is CustomGameMode.HotPotato or CustomGameMode.HideAndSeek or CustomGameMode.Speedrun or CustomGameMode.CaptureTheFlag or CustomGameMode.NaturalDisasters or CustomGameMode.RoomRush or CustomGameMode.KingOfTheZones or CustomGameMode.Quiz or CustomGameMode.TheMindGame or CustomGameMode.BedWars or CustomGameMode.Deathrace or CustomGameMode.Mingle or CustomGameMode.Snowdown;
|
||||
sb.Append($"\n{date:T} {Main.AllPlayerNames[key]} ({(gmIsFmhh ? string.Empty : Utils.GetDisplayRoleName(key, true))}{(gmIsFm ? string.Empty : Utils.GetSubRolesText(key, summary: true))}) [{Utils.GetVitalText(key)}]");
|
||||
if (killerId != byte.MaxValue && killerId != key) sb.Append($"\n\t⇐ {Main.AllPlayerNames[killerId]} ({(gmIsFmhh ? string.Empty : Utils.GetDisplayRoleName(killerId, true))}{(gmIsFm ? string.Empty : Utils.GetSubRolesText(killerId, summary: true))})");
|
||||
}
|
||||
@@ -342,6 +342,14 @@ internal static class SetEverythingUpPatch
|
||||
|
||||
goto EndOfText;
|
||||
}
|
||||
case CustomGameMode.Snowdown:
|
||||
{
|
||||
Color color = Utils.GetRoleColor(CustomRoles.SnowdownPlayer);
|
||||
__instance.BackgroundBar.material.color = color;
|
||||
winnerText.text = (CustomWinnerHolder.WinnerIds.Count <= 1 ? CustomWinnerHolder.WinnerIds.FirstOrDefault().ColoredPlayerName() : CustomWinnerHolder.WinnerIds.Select(x => x.ColoredPlayerName()).Join()) + GetString("Win");
|
||||
winnerText.color = color;
|
||||
goto EndOfText;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -550,6 +558,7 @@ internal static class SetEverythingUpPatch
|
||||
|
||||
break;
|
||||
}
|
||||
case CustomGameMode.Snowdown:
|
||||
case CustomGameMode.Mingle:
|
||||
case CustomGameMode.Deathrace:
|
||||
case CustomGameMode.BedWars:
|
||||
|
||||
@@ -259,6 +259,9 @@ internal static class CheckMurderPatch
|
||||
case CustomGameMode.Deathrace:
|
||||
Deathrace.OnCheckMurder(killer, target);
|
||||
return false;
|
||||
case CustomGameMode.Snowdown:
|
||||
Snowdown.OnCheckMurder(killer, target);
|
||||
return false;
|
||||
}
|
||||
|
||||
PlagueBearer.CheckAndSpreadInfection(killer, target);
|
||||
@@ -1514,7 +1517,7 @@ internal static class FixedUpdatePatch
|
||||
{
|
||||
Camouflage.OnFixedUpdate(player);
|
||||
|
||||
if (localPlayer && Options.CurrentGameMode is CustomGameMode.Standard or CustomGameMode.FFA or CustomGameMode.CaptureTheFlag or CustomGameMode.NaturalDisasters && GameStartTimeStamp + 44 == TimeStamp)
|
||||
if (localPlayer && Options.CurrentGameMode is CustomGameMode.Standard or CustomGameMode.FFA or CustomGameMode.CaptureTheFlag or CustomGameMode.NaturalDisasters or CustomGameMode.Snowdown && GameStartTimeStamp + 44 == TimeStamp)
|
||||
NotifyRoles();
|
||||
}
|
||||
}
|
||||
@@ -1975,6 +1978,9 @@ internal static class FixedUpdatePatch
|
||||
case CustomGameMode.Mingle when self:
|
||||
additionalSuffixes.Add(Mingle.GetSuffix(seer));
|
||||
break;
|
||||
case CustomGameMode.Snowdown:
|
||||
additionalSuffixes.Add(Snowdown.GetSuffix(seer, target));
|
||||
break;
|
||||
}
|
||||
|
||||
if (MeetingStates.FirstMeeting && Main.ShieldPlayer == target.FriendCode && !string.IsNullOrEmpty(target.FriendCode) && !self && Options.CurrentGameMode is CustomGameMode.Standard or CustomGameMode.SoloPVP or CustomGameMode.FFA)
|
||||
@@ -1984,7 +1990,7 @@ internal static class FixedUpdatePatch
|
||||
|
||||
if (addSuff.Count > 0)
|
||||
{
|
||||
if (Suffix.Length > 0 && Suffix[^1] != '\n')
|
||||
if (Suffix.ToString().RemoveHtmlTags().Length > 0 && Suffix[^1] != '\n')
|
||||
Suffix.Append('\n');
|
||||
|
||||
Suffix.Append(string.Join('\n', addSuff));
|
||||
@@ -2010,10 +2016,11 @@ internal static class FixedUpdatePatch
|
||||
else
|
||||
roleText = string.Empty;
|
||||
|
||||
string newLineBeforeSuffix = !(Options.CurrentGameMode == CustomGameMode.BedWars && !self && GameStates.InGame) ? "\r\n" : " - ";
|
||||
string suffix = Suffix.ToString().Trim();
|
||||
string newLineBeforeSuffix = !(Options.CurrentGameMode == CustomGameMode.BedWars && !self && GameStates.InGame) ? "\n" : " - ";
|
||||
string deathReason = !seer.IsAlive() && seer.KnowDeathReason(target) ? $"{newLineBeforeSuffix}<size=1.5>『{ColorString(GetRoleColor(CustomRoles.Doctor), GetVitalText(target.PlayerId))}』</size>" : string.Empty;
|
||||
|
||||
target.cosmetics.nameText.text = $"{roleText}{realName}{deathReason}{Mark}{newLineBeforeSuffix}{Suffix}";
|
||||
target.cosmetics.nameText.text = $"{roleText}{realName}{deathReason}{Mark}{newLineBeforeSuffix}{suffix}";
|
||||
|
||||
// Camouflage
|
||||
if (Camouflage.IsCamouflage) target.cosmetics.nameText.text = $"<size=0>{target.cosmetics.nameText.text}</size>";
|
||||
|
||||
@@ -372,7 +372,7 @@ public static class SabotageSystemTypeRepairDamagePatch
|
||||
public static bool Prefix(SabotageSystemType __instance, [HarmonyArgument(0)] PlayerControl player, [HarmonyArgument(1)] MessageReader msgReader)
|
||||
{
|
||||
Instance = __instance;
|
||||
if (Options.CurrentGameMode != CustomGameMode.Standard || __instance.Timer > 0f) return false;
|
||||
if (Options.CurrentGameMode is not (CustomGameMode.Standard or CustomGameMode.Snowdown) || __instance.Timer > 0f) return false;
|
||||
|
||||
SystemTypes systemTypes;
|
||||
{
|
||||
|
||||
@@ -91,7 +91,7 @@ internal static class RepairSystemPatch
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return true; // Execute the following only on the host
|
||||
|
||||
if ((Options.CurrentGameMode != CustomGameMode.Standard || Options.DisableSabotage.GetBool()) && systemType == SystemTypes.Sabotage) return false;
|
||||
if ((Options.CurrentGameMode is not (CustomGameMode.Standard or CustomGameMode.Snowdown) || 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;
|
||||
@@ -253,7 +253,7 @@ internal static class CloseDoorsPatch
|
||||
{
|
||||
public static bool Prefix([HarmonyArgument(0)] SystemTypes room)
|
||||
{
|
||||
bool allow = !Options.DisableSabotage.GetBool() && !AntiBlackout.SkipTasks && Options.CurrentGameMode is not CustomGameMode.SoloPVP and not CustomGameMode.FFA and not CustomGameMode.StopAndGo and not CustomGameMode.HotPotato and not CustomGameMode.Speedrun and not CustomGameMode.CaptureTheFlag and not CustomGameMode.NaturalDisasters and not CustomGameMode.RoomRush and not CustomGameMode.KingOfTheZones and not CustomGameMode.Quiz and not CustomGameMode.TheMindGame and not CustomGameMode.BedWars and not CustomGameMode.Deathrace and not CustomGameMode.Mingle;
|
||||
bool allow = !Options.DisableSabotage.GetBool() && !AntiBlackout.SkipTasks && Options.CurrentGameMode is not CustomGameMode.SoloPVP and not CustomGameMode.FFA and not CustomGameMode.StopAndGo and not CustomGameMode.HotPotato and not CustomGameMode.Speedrun and not CustomGameMode.CaptureTheFlag and not CustomGameMode.NaturalDisasters and not CustomGameMode.RoomRush and not CustomGameMode.KingOfTheZones and not CustomGameMode.Quiz and not CustomGameMode.TheMindGame and not CustomGameMode.BedWars and not CustomGameMode.Deathrace and not CustomGameMode.Mingle and not CustomGameMode.Snowdown;
|
||||
|
||||
if (Doorjammer.JammedRooms.Contains(room)) allow = false;
|
||||
if (SecurityGuard.BlockSabo.Count > 0) allow = false;
|
||||
|
||||
@@ -177,7 +177,7 @@ internal static class RpcSetTasksPatch
|
||||
}
|
||||
|
||||
// GM and Lazy Guy have no tasks
|
||||
if (pc.Is(CustomRoles.GM) || pc.Is(CustomRoles.LazyGuy) || Options.CurrentGameMode is CustomGameMode.SoloPVP or CustomGameMode.FFA or CustomGameMode.HotPotato or CustomGameMode.NaturalDisasters or CustomGameMode.RoomRush or CustomGameMode.Quiz or CustomGameMode.CaptureTheFlag or CustomGameMode.KingOfTheZones or CustomGameMode.TheMindGame or CustomGameMode.BedWars or CustomGameMode.Deathrace or CustomGameMode.Mingle)
|
||||
if (pc.Is(CustomRoles.GM) || pc.Is(CustomRoles.LazyGuy) || Options.CurrentGameMode is CustomGameMode.SoloPVP or CustomGameMode.FFA or CustomGameMode.HotPotato or CustomGameMode.NaturalDisasters or CustomGameMode.RoomRush or CustomGameMode.Quiz or CustomGameMode.CaptureTheFlag or CustomGameMode.KingOfTheZones or CustomGameMode.TheMindGame or CustomGameMode.BedWars or CustomGameMode.Deathrace or CustomGameMode.Mingle or CustomGameMode.Snowdown)
|
||||
{
|
||||
hasCommonTasks = false;
|
||||
numShortTasks = 0;
|
||||
|
||||
+25
-16
@@ -4943,6 +4943,7 @@
|
||||
"GameModeTutorial.Speedrun": "<size=90%>The current game mode is <#800080>Speedrun</color>.</size>\\n<size=80%>Complete all tasks to gain the kill button, then kill everyone to win.\\nYou must do a task or kill within your time limit, else you suicide.</size>",
|
||||
"GameModeTutorial.CaptureTheFlag": "<size=90%>The current game mode is <#1313c2>Capture The Flag</color>.</size>\\n<size=80%>Get to the base of the enemy team and press Vanish to pick up their flag.\\nBring it back to your own base for your team to win.\\nPress Kill on someone to tag them, this will get rid of that player temporarily or permanently.</size>",
|
||||
"GameModeTutorial.NaturalDisasters": "<size=90%>The current game mode is <#03fc4a>Natural Disasters</color>.</size>\\n<size=80%>Various disasters will constantly spawn on the map.\\nSome kill you instantly, some just debuff you temporarily.\\nBe the last player alive to win!</size>",
|
||||
"GameModeTutorial.Snowdown": "<size=90%>The current game mode is <#e4fdff>Snowdown</color>.</size>\\n<size=80%>Vanish to throw a snowball in your movement direction.\\nIf it hits someone, you get a coin. Pet to turn 20 coins into 1 point.\\nCall a critical sabotage to enter/exit the shop. Highest points wins!</size>",
|
||||
"GameModeListTitle": "Game Modes",
|
||||
"ModeStandard": "Gamemode: Standard",
|
||||
"FFA": "FREE FOR ALL",
|
||||
@@ -5484,6 +5485,29 @@
|
||||
"MinglePlayer": "MINGLE",
|
||||
"MinglePlayerInfo": "SURVIVE BY BEING IN THE RIGHT ROOMS",
|
||||
"MinglePlayerInfoLong": "SURVIVE BY BEING IN THE RIGHT ROOMS",
|
||||
"Snowdown": "SNOWDOWN",
|
||||
"ModeSnowdown": "Gamemode: Snowdown",
|
||||
"ModeDescribe.Snowdown": "In the Snowdown gamemode, the player that successfully throws the most snowballs at other players wins! You get 1 coin for every hit. You can spend coins on powerups in the shop, or turn pet to turn 20 coins into 1 point. Highest <u>points</u> (not coins) wins! Triggers:\\n- Vanish: Throw a snowball in your movement direction / Cycle between powerups while in shop\\n- Calling a ciritical Sabotage: Enter/Exit shop\\n- Pet: Turn 20 coins into 1 point / Buy selected powerup in shop\\n- Kill: Give the target one of your snowballs",
|
||||
"Snowdown.SnowballThrowSpeedOption": "Snowball Throwing Speed",
|
||||
"Snowdown.SnowballGainFrequencyOption": "Initial Snowball Gaining Frequency",
|
||||
"Snowdown.MaxSnowballsInHandOption": "Max Snowballs Everyone Can Hold Initially",
|
||||
"Snowdown.MaxCoinsInHandOption": "Max Coins Everyone Can Hold Initially",
|
||||
"Snowdown.GameEndsAfterTimeOption": "Game Ends After a Certain Time",
|
||||
"Snowdown.GameEndTimeOption": "Game Ends After",
|
||||
"Snowdown.GameEndsWhenPointsReachedOption": "Game Ends When Someone Reached a Specific Number of Points",
|
||||
"Snowdown.PointsToReachOption": "Points to Reach to Win",
|
||||
"Snowdown.PowerUpPriceOption": "{powerup} Powerup Price (Coins)",
|
||||
"Snowdown.PowerUp.FillUp": "Fill-Up",
|
||||
"Snowdown.PowerUp.FillUp.Description": "Sets your snowball counter to its max",
|
||||
"Snowdown.PowerUp.IncreaseCapacity": "Capacity Increment",
|
||||
"Snowdown.PowerUp.IncreaseCapacity.Description": "Increases how many snowballs and coins you can hold",
|
||||
"Snowdown.PowerUp.FasterPickup": "Pickup Boost",
|
||||
"Snowdown.PowerUp.FasterPickup.Description": "Increases your rate of getting snowballs",
|
||||
"Snowdown.ShopHelp": "Vanish: Cycle between powerups | Pet: Buy selected powerup | Sabotage: Exit shop",
|
||||
"SnowdownButtonText": "THROW",
|
||||
"SnowdownPlayer": "SNOWDOWN",
|
||||
"SnowdownPlayerInfo": "THROW SNOWBALLS AT PLAYERS",
|
||||
"SnowdownPlayerInfoLong": "THROW SNOWBALLS AT PLAYERS",
|
||||
"Quiz": "QUIZ",
|
||||
"ModeQuiz": "Gamemode: Quiz",
|
||||
"ModeDescribe.Quiz": "In the Quiz game mode, you must answer questions correctly to survive. There are various difficulties with varying time limits. Each question has 5 answer choices: A, B, C, D, E. Each choice has a room name next to the answer. To pick an answer, you must enter the room corresponding to the answer. If you answer correctly, you survive. If you don't answer enough questions correctly, you eventually die or compete in a Free For All (FFA) match with the other players who got the questions wrong.",
|
||||
@@ -10195,22 +10219,7 @@
|
||||
"AGMR.Slot.RandomGroupId": "Number/ID of the random group to use for choosing the game mode for this slot/game",
|
||||
"AGMR.Slot.Count": "How many times should we repeat this?",
|
||||
"MenuTitle.AGMR.RandomGroup": "Random Group {index}",
|
||||
"AGMR.RandomGroup.GMChance.Standard": "Chance of selecting Standard",
|
||||
"AGMR.RandomGroup.GMChance.SoloPVP": "Chance of selecting Solo PVP",
|
||||
"AGMR.RandomGroup.GMChance.FFA": "Chance of selecting FFA",
|
||||
"AGMR.RandomGroup.GMChance.StopAndGo": "Chance of selecting Stop And Go",
|
||||
"AGMR.RandomGroup.GMChance.HotPotato": "Chance of selecting Hot Potato",
|
||||
"AGMR.RandomGroup.GMChance.HideAndSeek": "Chance of selecting (Custom) Hide And Seek",
|
||||
"AGMR.RandomGroup.GMChance.Speedrun": "Chance of selecting Speedrun",
|
||||
"AGMR.RandomGroup.GMChance.CaptureTheFlag": "Chance of selecting Capture The Flag",
|
||||
"AGMR.RandomGroup.GMChance.NaturalDisasters": "Chance of selecting Natural Disasters",
|
||||
"AGMR.RandomGroup.GMChance.RoomRush": "Chance of selecting Room Rush",
|
||||
"AGMR.RandomGroup.GMChance.KingOfTheZones": "Chance of selecting King Of The Zones",
|
||||
"AGMR.RandomGroup.GMChance.Quiz": "Chance of selecting Quiz",
|
||||
"AGMR.RandomGroup.GMChance.TheMindGame": "Chance of selecting The Mind Game",
|
||||
"AGMR.RandomGroup.GMChance.BedWars": "Chance of selecting Bed Wars",
|
||||
"AGMR.RandomGroup.GMChance.Deathrace": "Chance of selecting Deathrace",
|
||||
"AGMR.RandomGroup.GMChance.Mingle": "Chance of selecting Mingle",
|
||||
"AGMR.RandomGroup.GMChance": "Chance of selecting {gm}",
|
||||
"AutoGMRotationStatusText": "<u>AUTOMATIC GAME MODE ROTATION IS ENABLED!</u>",
|
||||
"AutoGMRotationStatusText.NextGM": "Next",
|
||||
"AutoGMRotationStatusText.GMPoll": "Player Vote (/gmpoll)",
|
||||
|
||||
@@ -122,10 +122,10 @@ public class Swooper : RoleBase
|
||||
try
|
||||
{
|
||||
if (UsedRole == CustomRoles.Chameleon)
|
||||
AURoleOptions.EngineerCooldown = Cooldown + 1f;
|
||||
AURoleOptions.EngineerCooldown = Cooldown + 2f;
|
||||
else if (UsePhantomBasis.GetBool() && (UsedRole == CustomRoles.Swooper || UsePhantomBasisForNKs.GetBool()))
|
||||
{
|
||||
AURoleOptions.PhantomCooldown = Cooldown + 1f;
|
||||
AURoleOptions.PhantomCooldown = Cooldown + 2f;
|
||||
AURoleOptions.PhantomDuration = 0.1f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,29 +62,32 @@ public class Executioner : RoleBase
|
||||
{
|
||||
PlayerIdList.Add(playerId);
|
||||
|
||||
LateTask.New(() =>
|
||||
if (AmongUsClient.Instance.AmHost)
|
||||
{
|
||||
try
|
||||
LateTask.New(() =>
|
||||
{
|
||||
List<PlayerControl> targetList = [];
|
||||
targetList.AddRange(from target in Main.AllPlayerControls where playerId != target.PlayerId where CanTargetImpostor.GetBool() || !target.Is(CustomRoleTypes.Impostor) where CanTargetNeutralKiller.GetBool() || !target.IsNeutralKiller() where CanTargetNeutralBenign.GetBool() || !target.IsNeutralBenign() where CanTargetNeutralEvil.GetBool() || (!target.IsNeutralEvil() && !target.IsNeutralPariah()) where CanTargetCoven.GetBool() || !target.Is(CustomRoleTypes.Coven) where target.GetCustomRole() is not (CustomRoles.GM or CustomRoles.SuperStar) where Main.LoversPlayers.TrueForAll(x => x.PlayerId != playerId) select target);
|
||||
targetList.AddRange(Main.AllPlayerControls.Where(x => x.IsCrewmate() && x.GetCustomRole() is not (CustomRoles.Swapper or CustomRoles.Mayor or CustomRoles.NiceGuesser or CustomRoles.Dictator)));
|
||||
targetList.RemoveAll(x => x.GetCustomRole() is CustomRoles.Swapper or CustomRoles.Mayor or CustomRoles.NiceGuesser or CustomRoles.Dictator or CustomRoles.Executioner or CustomRoles.Terrorist or CustomRoles.GM);
|
||||
if (!CanTargetNeutralBenign.GetBool() && !CanTargetNeutralEvil.GetBool() && !CanTargetNeutralKiller.GetBool()) targetList.RemoveAll(x => x.GetCustomRole().IsNeutral() || x.Is(CustomRoles.Bloodlust));
|
||||
|
||||
if (targetList.Count == 0)
|
||||
try
|
||||
{
|
||||
LateTask.New(() => ChangeRole(Utils.GetPlayerById(playerId)), 8f, log: false);
|
||||
return;
|
||||
}
|
||||
List<PlayerControl> targetList = [];
|
||||
targetList.AddRange(from target in Main.AllPlayerControls where playerId != target.PlayerId where CanTargetImpostor.GetBool() || !target.Is(CustomRoleTypes.Impostor) where CanTargetNeutralKiller.GetBool() || !target.IsNeutralKiller() where CanTargetNeutralBenign.GetBool() || !target.IsNeutralBenign() where CanTargetNeutralEvil.GetBool() || (!target.IsNeutralEvil() && !target.IsNeutralPariah()) where CanTargetCoven.GetBool() || !target.Is(CustomRoleTypes.Coven) where target.GetCustomRole() is not (CustomRoles.GM or CustomRoles.SuperStar) where Main.LoversPlayers.TrueForAll(x => x.PlayerId != playerId) select target);
|
||||
targetList.AddRange(Main.AllPlayerControls.Where(x => x.IsCrewmate() && x.GetCustomRole() is not (CustomRoles.Swapper or CustomRoles.Mayor or CustomRoles.NiceGuesser or CustomRoles.Dictator)));
|
||||
targetList.RemoveAll(x => x.GetCustomRole() is CustomRoles.Swapper or CustomRoles.Mayor or CustomRoles.NiceGuesser or CustomRoles.Dictator or CustomRoles.Executioner or CustomRoles.Terrorist or CustomRoles.GM);
|
||||
if (!CanTargetNeutralBenign.GetBool() && !CanTargetNeutralEvil.GetBool() && !CanTargetNeutralKiller.GetBool()) targetList.RemoveAll(x => x.GetCustomRole().IsNeutral() || x.Is(CustomRoles.Bloodlust));
|
||||
|
||||
PlayerControl selectedTarget = targetList.RandomElement();
|
||||
Target[playerId] = selectedTarget.PlayerId;
|
||||
SendRPC(playerId, selectedTarget.PlayerId, "SetTarget");
|
||||
Logger.Info($"{Utils.GetPlayerById(playerId)?.GetNameWithRole().RemoveHtmlTags()}'s target: {selectedTarget.GetNameWithRole().RemoveHtmlTags()}", "Executioner");
|
||||
}
|
||||
catch (Exception ex) { Logger.Error(ex.ToString(), "Executioner.Add"); }
|
||||
}, 0.5f, log: false);
|
||||
if (targetList.Count == 0)
|
||||
{
|
||||
LateTask.New(() => ChangeRole(Utils.GetPlayerById(playerId)), 8f, log: false);
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerControl selectedTarget = targetList.RandomElement();
|
||||
Target[playerId] = selectedTarget.PlayerId;
|
||||
SendRPC(playerId, selectedTarget.PlayerId, "SetTarget");
|
||||
Logger.Info($"{Utils.GetPlayerById(playerId)?.GetNameWithRole().RemoveHtmlTags()}'s target: {selectedTarget.GetNameWithRole().RemoveHtmlTags()}", "Executioner");
|
||||
}
|
||||
catch (Exception ex) { Logger.Error(ex.ToString(), "Executioner.Add"); }
|
||||
}, 0.5f, log: false);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Remove(byte playerId)
|
||||
@@ -95,7 +98,7 @@ public class Executioner : RoleBase
|
||||
|
||||
public static void SendRPC(byte executionerId, byte targetId = 0x73, string Progress = "")
|
||||
{
|
||||
if (!AmongUsClient.Instance.AmHost || !Utils.DoRPC) return;
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
|
||||
MessageWriter writer;
|
||||
|
||||
|
||||
@@ -123,10 +123,10 @@ public class Hater : RoleBase
|
||||
target.SetRealKiller(killer);
|
||||
killer.Kill(target);
|
||||
target.Data.IsDead = true;
|
||||
Main.PlayerStates[target.PlayerId].deathReason = PlayerState.DeathReason.Misfire;
|
||||
Main.PlayerStates[target.PlayerId].deathReason = PlayerState.DeathReason.Sacrifice;
|
||||
}
|
||||
|
||||
killer.Suicide(PlayerState.DeathReason.Sacrifice);
|
||||
killer.Suicide(PlayerState.DeathReason.Misfire);
|
||||
Logger.Info($"{killer.GetRealName()} killed incorrect target => misfire", "Hater");
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user