mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-28 09:39:20 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91e2748156 | ||
|
|
dbb5c39dea | ||
|
|
a13cbd9f88 | ||
|
|
333dfbee6f | ||
|
|
0431d18127 | ||
|
|
2db423411f | ||
|
|
3d120a5924 | ||
|
|
f91f0cd09c |
No files matched your search
@@ -114,6 +114,7 @@ public enum CustomRoles
|
||||
// Crewmate
|
||||
|
||||
Addict,
|
||||
Adventurer,
|
||||
Aid,
|
||||
Alchemist,
|
||||
Altruist,
|
||||
|
||||
@@ -114,6 +114,7 @@ public enum CustomRoles
|
||||
// Crewmate
|
||||
|
||||
Addict,
|
||||
Adventurer,
|
||||
Aid,
|
||||
Alchemist,
|
||||
Altruist,
|
||||
|
||||
@@ -15,8 +15,10 @@
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=NE/@EntryIndexedValue">NE</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=NK/@EntryIndexedValue">NK</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=NNK/@EntryIndexedValue">NNK</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RNG/@EntryIndexedValue">RNG</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RPC/@EntryIndexedValue">RPC</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SK/@EntryIndexedValue">SK</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TMP/@EntryIndexedValue">TMP</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=EHR/@EntryIndexedValue">EHR</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></wpf:ResourceDictionary>
|
||||
+142
-91
@@ -22,6 +22,20 @@ internal static class FFAManager
|
||||
|
||||
public static string LatestChatMessage = string.Empty;
|
||||
|
||||
public static Dictionary<byte, int> PlayerTeams = [];
|
||||
|
||||
public static readonly Dictionary<int, string> TeamColors = new()
|
||||
{
|
||||
{ 0, "#00ffff" },
|
||||
{ 1, "#ffff00" },
|
||||
{ 2, "#ff00ff" },
|
||||
{ 3, "#ff0000" },
|
||||
{ 4, "#00ff00" },
|
||||
{ 5, "#0000ff" },
|
||||
{ 6, "#ffffff" },
|
||||
{ 7, "#000000" }
|
||||
};
|
||||
|
||||
public static OptionItem FFAGameTime;
|
||||
public static OptionItem FFAKcd;
|
||||
public static OptionItem FFALowerVision;
|
||||
@@ -36,6 +50,8 @@ internal static class FFAManager
|
||||
public static OptionItem FFAEnableRandomTwists;
|
||||
public static OptionItem FFAShieldIsOneTimeUse;
|
||||
public static OptionItem FFAChatDuringGame;
|
||||
public static OptionItem FFATeamMode;
|
||||
public static OptionItem FFATeamNumber;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
@@ -84,6 +100,14 @@ internal static class FFAManager
|
||||
FFAChatDuringGame = BooleanOptionItem.Create(67_223_014, "FFA_ChatDuringGame", false, TabGroup.GameSettings, false)
|
||||
.SetGameMode(CustomGameMode.FFA)
|
||||
.SetColor(new Color32(0, 255, 165, byte.MaxValue));
|
||||
FFATeamMode = BooleanOptionItem.Create(67_223_015, "FFA_TeamMode", false, TabGroup.GameSettings, false)
|
||||
.SetGameMode(CustomGameMode.FFA)
|
||||
.SetHeader(true)
|
||||
.SetColor(new Color32(0, 255, 165, byte.MaxValue));
|
||||
FFATeamNumber = IntegerOptionItem.Create(67_223_016, "FFA_TeamNumber", new(2, 7, 1), 2, TabGroup.GameSettings, false)
|
||||
.SetParent(FFATeamMode)
|
||||
.SetGameMode(CustomGameMode.FFA)
|
||||
.SetColor(new Color32(0, 255, 165, byte.MaxValue));
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
@@ -99,10 +123,32 @@ internal static class FFAManager
|
||||
KillCount = [];
|
||||
RoundTime = FFAGameTime.GetInt() + 8;
|
||||
|
||||
foreach (PlayerControl pc in Main.AllAlivePlayerControls)
|
||||
PlayerTeams = [];
|
||||
|
||||
var allPlayers = Main.AllAlivePlayerControls;
|
||||
|
||||
foreach (PlayerControl pc in allPlayers)
|
||||
{
|
||||
KillCount[pc.PlayerId] = 0;
|
||||
}
|
||||
|
||||
if (FFATeamMode.GetBool())
|
||||
{
|
||||
var teamNum = FFATeamNumber.GetInt();
|
||||
var playerNum = allPlayers.Length;
|
||||
int memberNum = (teamNum > 5 && playerNum == 15) || playerNum % teamNum == 0 ? playerNum / teamNum : playerNum / teamNum + 1;
|
||||
var teamMembers = allPlayers.Select(x => x.PlayerId).Shuffle(IRandom.Instance).Chunk(memberNum).ToList();
|
||||
|
||||
for (int i = 0; i < teamMembers.Count; i++)
|
||||
{
|
||||
foreach (var id in teamMembers[i])
|
||||
{
|
||||
PlayerTeams.Add(id, i);
|
||||
}
|
||||
}
|
||||
|
||||
_ = new LateTask(() => { Utils.NotifyRoles(NoCache: true, ForceLoop: true); }, 10f, log: false);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SendRPCSyncFFAPlayer(byte playerId)
|
||||
@@ -146,15 +192,6 @@ internal static class FFAManager
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetDisplayScore(byte playerId)
|
||||
{
|
||||
int rank = GetRankOfScore(playerId);
|
||||
string score = KillCount.TryGetValue(playerId, out var s) ? $"{s}" : "Invalid";
|
||||
string text = string.Format(GetString("KBDisplayScore"), rank.ToString(), score);
|
||||
Color color = Utils.GetRoleColor(CustomRoles.Killer);
|
||||
return Utils.ColorString(color, text);
|
||||
}
|
||||
|
||||
public static int GetRankOfScore(byte playerId)
|
||||
{
|
||||
try
|
||||
@@ -184,6 +221,12 @@ internal static class FFAManager
|
||||
return;
|
||||
}
|
||||
|
||||
if (FFATeamMode.GetBool() && PlayerTeams[killer.PlayerId] == PlayerTeams[target.PlayerId])
|
||||
{
|
||||
Logger.Info("Killer and Target are in the same team, attack blocked", "FFA");
|
||||
return;
|
||||
}
|
||||
|
||||
var totalalive = Main.AllAlivePlayerControls.Length;
|
||||
if (FFAShieldedList.TryGetValue(target.PlayerId, out var dur))
|
||||
{
|
||||
@@ -206,7 +249,7 @@ internal static class FFAManager
|
||||
if (totalalive == 3)
|
||||
{
|
||||
PlayerControl otherPC = null;
|
||||
foreach (var pc in Main.AllAlivePlayerControls.Where(a => a.PlayerId != killer.PlayerId && a.PlayerId != target.PlayerId && a.IsAlive()).ToArray())
|
||||
foreach (var pc in Main.AllAlivePlayerControls.Where(a => a.PlayerId != killer.PlayerId && a.PlayerId != target.PlayerId && a.IsAlive()))
|
||||
{
|
||||
TargetArrow.Add(killer.PlayerId, pc.PlayerId);
|
||||
TargetArrow.Add(pc.PlayerId, killer.PlayerId);
|
||||
@@ -222,90 +265,99 @@ internal static class FFAManager
|
||||
bool mark = false;
|
||||
var nowKCD = Main.AllPlayerKillCooldown[killer.PlayerId];
|
||||
byte EffectType;
|
||||
if (Main.NormalOptions.MapId != 4) EffectType = (byte)HashRandom.Next(0, 10);
|
||||
else EffectType = (byte)HashRandom.Next(4, 10);
|
||||
if (EffectType <= 7) // Buff
|
||||
if (Main.NormalOptions.MapId != 4) EffectType = (byte)IRandom.Instance.Next(0, 10);
|
||||
else EffectType = (byte)IRandom.Instance.Next(4, 10);
|
||||
switch (EffectType)
|
||||
{
|
||||
byte EffectID = (byte)HashRandom.Next(0, 3);
|
||||
if (Main.NormalOptions.MapId == 4) EffectID = 2;
|
||||
switch (EffectID)
|
||||
// Buff
|
||||
case <= 7:
|
||||
{
|
||||
case 0:
|
||||
FFAShieldedList.TryAdd(killer.PlayerId, Utils.TimeStamp);
|
||||
killer.Notify(GetString("FFA-Event-GetShield"), FFAShieldDuration.GetFloat());
|
||||
Main.AllPlayerKillCooldown[killer.PlayerId] = FFAKcd.GetFloat();
|
||||
break;
|
||||
case 1:
|
||||
if (FFAIncreasedSpeedList.ContainsKey(killer.PlayerId))
|
||||
{
|
||||
FFAIncreasedSpeedList.Remove(killer.PlayerId);
|
||||
FFAIncreasedSpeedList.Add(killer.PlayerId, Utils.TimeStamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
FFAIncreasedSpeedList.TryAdd(killer.PlayerId, Utils.TimeStamp);
|
||||
originalSpeed.TryAdd(killer.PlayerId, Main.AllPlayerSpeed[killer.PlayerId]);
|
||||
Main.AllPlayerSpeed[killer.PlayerId] = FFAIncreasedSpeed.GetFloat();
|
||||
}
|
||||
byte EffectID = (byte)IRandom.Instance.Next(0, 3);
|
||||
if (Main.NormalOptions.MapId == 4) EffectID = 2;
|
||||
switch (EffectID)
|
||||
{
|
||||
case 0:
|
||||
FFAShieldedList.TryAdd(killer.PlayerId, Utils.TimeStamp);
|
||||
killer.Notify(GetString("FFA-Event-GetShield"), FFAShieldDuration.GetFloat());
|
||||
Main.AllPlayerKillCooldown[killer.PlayerId] = FFAKcd.GetFloat();
|
||||
break;
|
||||
case 1:
|
||||
if (FFAIncreasedSpeedList.ContainsKey(killer.PlayerId))
|
||||
{
|
||||
FFAIncreasedSpeedList.Remove(killer.PlayerId);
|
||||
FFAIncreasedSpeedList.Add(killer.PlayerId, Utils.TimeStamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
FFAIncreasedSpeedList.TryAdd(killer.PlayerId, Utils.TimeStamp);
|
||||
originalSpeed.TryAdd(killer.PlayerId, Main.AllPlayerSpeed[killer.PlayerId]);
|
||||
Main.AllPlayerSpeed[killer.PlayerId] = FFAIncreasedSpeed.GetFloat();
|
||||
}
|
||||
|
||||
killer.Notify(GetString("FFA-Event-GetIncreasedSpeed"), FFAModifiedSpeedDuration.GetFloat());
|
||||
Main.AllPlayerKillCooldown[killer.PlayerId] = FFAKcd.GetFloat();
|
||||
mark = true;
|
||||
break;
|
||||
case 2:
|
||||
Main.AllPlayerKillCooldown[killer.PlayerId] = Math.Clamp(FFAKcd.GetFloat() - 3f, 1f, 60f);
|
||||
killer.Notify(GetString("FFA-Event-GetLowKCD"));
|
||||
sync = true;
|
||||
break;
|
||||
default:
|
||||
Main.AllPlayerKillCooldown[killer.PlayerId] = FFAKcd.GetFloat();
|
||||
break;
|
||||
killer.Notify(GetString("FFA-Event-GetIncreasedSpeed"), FFAModifiedSpeedDuration.GetFloat());
|
||||
Main.AllPlayerKillCooldown[killer.PlayerId] = FFAKcd.GetFloat();
|
||||
mark = true;
|
||||
break;
|
||||
case 2:
|
||||
Main.AllPlayerKillCooldown[killer.PlayerId] = Math.Clamp(FFAKcd.GetFloat() - 3f, 1f, 60f);
|
||||
killer.Notify(GetString("FFA-Event-GetLowKCD"));
|
||||
sync = true;
|
||||
break;
|
||||
default:
|
||||
Main.AllPlayerKillCooldown[killer.PlayerId] = FFAKcd.GetFloat();
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (EffectType == 8) // De-Buff
|
||||
{
|
||||
byte EffectID = (byte)HashRandom.Next(0, 3);
|
||||
if (Main.NormalOptions.MapId == 4) EffectID = 1;
|
||||
switch (EffectID)
|
||||
// De-Buff
|
||||
case 8:
|
||||
{
|
||||
case 0:
|
||||
if (FFADecreasedSpeedList.ContainsKey(killer.PlayerId))
|
||||
{
|
||||
FFADecreasedSpeedList.Remove(killer.PlayerId);
|
||||
FFADecreasedSpeedList.Add(killer.PlayerId, Utils.TimeStamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
FFADecreasedSpeedList.TryAdd(killer.PlayerId, Utils.TimeStamp);
|
||||
originalSpeed.TryAdd(killer.PlayerId, Main.AllPlayerSpeed[killer.PlayerId]);
|
||||
Main.AllPlayerSpeed[killer.PlayerId] = FFADecreasedSpeed.GetFloat();
|
||||
}
|
||||
byte EffectID = (byte)IRandom.Instance.Next(0, 3);
|
||||
if (Main.NormalOptions.MapId == 4) EffectID = 1;
|
||||
switch (EffectID)
|
||||
{
|
||||
case 0:
|
||||
if (FFADecreasedSpeedList.ContainsKey(killer.PlayerId))
|
||||
{
|
||||
FFADecreasedSpeedList.Remove(killer.PlayerId);
|
||||
FFADecreasedSpeedList.Add(killer.PlayerId, Utils.TimeStamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
FFADecreasedSpeedList.TryAdd(killer.PlayerId, Utils.TimeStamp);
|
||||
originalSpeed.TryAdd(killer.PlayerId, Main.AllPlayerSpeed[killer.PlayerId]);
|
||||
Main.AllPlayerSpeed[killer.PlayerId] = FFADecreasedSpeed.GetFloat();
|
||||
}
|
||||
|
||||
killer.Notify(GetString("FFA-Event-GetDecreasedSpeed"), FFAModifiedSpeedDuration.GetFloat());
|
||||
Main.AllPlayerKillCooldown[killer.PlayerId] = FFAKcd.GetFloat();
|
||||
mark = true;
|
||||
break;
|
||||
case 1:
|
||||
Main.AllPlayerKillCooldown[killer.PlayerId] = Math.Clamp(FFAKcd.GetFloat() + 3f, 1f, 60f);
|
||||
killer.Notify(GetString("FFA-Event-GetHighKCD"));
|
||||
sync = true;
|
||||
break;
|
||||
case 2:
|
||||
FFALowerVisionList.TryAdd(killer.PlayerId, Utils.TimeStamp);
|
||||
Main.AllPlayerKillCooldown[killer.PlayerId] = FFAKcd.GetFloat();
|
||||
killer.Notify(GetString("FFA-Event-GetLowVision"));
|
||||
mark = true;
|
||||
break;
|
||||
default:
|
||||
Main.AllPlayerKillCooldown[killer.PlayerId] = FFAKcd.GetFloat();
|
||||
break;
|
||||
killer.Notify(GetString("FFA-Event-GetDecreasedSpeed"), FFAModifiedSpeedDuration.GetFloat());
|
||||
Main.AllPlayerKillCooldown[killer.PlayerId] = FFAKcd.GetFloat();
|
||||
mark = true;
|
||||
break;
|
||||
case 1:
|
||||
Main.AllPlayerKillCooldown[killer.PlayerId] = Math.Clamp(FFAKcd.GetFloat() + 3f, 1f, 60f);
|
||||
killer.Notify(GetString("FFA-Event-GetHighKCD"));
|
||||
sync = true;
|
||||
break;
|
||||
case 2:
|
||||
FFALowerVisionList.TryAdd(killer.PlayerId, Utils.TimeStamp);
|
||||
Main.AllPlayerKillCooldown[killer.PlayerId] = FFAKcd.GetFloat();
|
||||
killer.Notify(GetString("FFA-Event-GetLowVision"));
|
||||
mark = true;
|
||||
break;
|
||||
default:
|
||||
Main.AllPlayerKillCooldown[killer.PlayerId] = FFAKcd.GetFloat();
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else // Mixed
|
||||
{
|
||||
_ = new LateTask(() => { killer.TPtoRndVent(); }, 0.5f, "FFA-Event-TP");
|
||||
killer.Notify(GetString("FFA-Event-GetTP"));
|
||||
Main.AllPlayerKillCooldown[killer.PlayerId] = FFAKcd.GetFloat();
|
||||
// Mixed
|
||||
default:
|
||||
_ = new LateTask(() => { killer.TPtoRndVent(); }, 0.5f, "FFA-Event-TP");
|
||||
killer.Notify(GetString("FFA-Event-GetTP"));
|
||||
Main.AllPlayerKillCooldown[killer.PlayerId] = FFAKcd.GetFloat();
|
||||
break;
|
||||
}
|
||||
|
||||
if (sync || Math.Abs(nowKCD - Main.AllPlayerKillCooldown[killer.PlayerId]) > 0.1f)
|
||||
@@ -353,7 +405,7 @@ internal static class FFAManager
|
||||
LatestChatMessage = string.Format(GetString("FFAChatMessageNotify"), playerName, message);
|
||||
foreach (var pc in Main.AllAlivePlayerControls)
|
||||
{
|
||||
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
||||
pc.Notify(LatestChatMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,8 +436,7 @@ internal static class FFAManager
|
||||
|
||||
var rd = IRandom.Instance;
|
||||
byte FFAdoTPdecider = (byte)rd.Next(0, 100);
|
||||
bool FFAdoTP = false;
|
||||
if (FFAdoTPdecider == 0) FFAdoTP = true;
|
||||
bool FFAdoTP = FFAdoTPdecider == 0;
|
||||
|
||||
if (FFAEnableRandomTwists.GetBool() && FFAdoTP)
|
||||
{
|
||||
|
||||
@@ -62,7 +62,15 @@ public class Counter(int totalGreenTime, int totalRedTime, long startTimeStamp,
|
||||
|
||||
public string ColoredTimerString
|
||||
{
|
||||
get => IsYellow ? Utils.ColorString(Color.clear, "00") : Utils.ColorString(IsRed ? Color.red : Color.green, Timer < 10 ? $"0{Timer}" : Timer.ToString());
|
||||
get
|
||||
{
|
||||
string result = IsYellow || (Timer == TotalGreenTime && !IsRed && !IsYellow) || (Timer == TotalRedTime && IsRed) ? Utils.ColorString(Color.clear, "00") : Utils.ColorString(IsRed ? Color.red : Color.green, Timer < 10 ? $"0{Timer}" : Timer.ToString());
|
||||
|
||||
if (Timer is <= 19 and >= 10 && !IsYellow) result = $" {result}";
|
||||
if (Timer % 10 == 1 && !IsYellow) result = result.Insert(result.Length - 9, " ");
|
||||
|
||||
return $"<font=\"DIGITAL-7 SDF\"><size=130%>{result}</size></font>";
|
||||
}
|
||||
}
|
||||
|
||||
public string ColoredArrow
|
||||
@@ -139,10 +147,10 @@ class MoveAndStopPlayerData(Counter leftCounter, Counter middleCounter, Counter
|
||||
var middleTimer = MiddleCounter.ColoredTimerString;
|
||||
var rightTimer = RightCounter.ColoredTimerString;
|
||||
|
||||
var arrowRow = $"{LeftCounter.ColoredArrow.PadRightV2(4)} {MiddleCounter.ColoredArrow.PadRightV2(4)} {RightCounter.ColoredArrow.PadRightV2(4)}";
|
||||
var counterRow = $"{leftTimer.PadRightV2(4)} {middleTimer.PadRightV2(4)} {rightTimer.PadRightV2(4)}";
|
||||
var arrowRow = $"{LeftCounter.ColoredArrow} {MiddleCounter.ColoredArrow} {RightCounter.ColoredArrow}";
|
||||
var counterRow = $"{leftTimer} {middleTimer} {rightTimer}";
|
||||
|
||||
return $"{arrowRow}\n{counterRow}";
|
||||
return $"{counterRow}\n{arrowRow}";
|
||||
}
|
||||
|
||||
public void UpdateCounters()
|
||||
|
||||
@@ -3,6 +3,7 @@ using EHR.Roles.Crewmate;
|
||||
using EHR.Roles.Impostor;
|
||||
using EHR.Roles.Neutral;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
@@ -148,6 +149,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Express => CustomRoles.Crewmate,
|
||||
CustomRoles.NiceEraser => CustomRoles.Crewmate,
|
||||
CustomRoles.TaskManager => CustomRoles.Crewmate,
|
||||
CustomRoles.Adventurer => CustomRoles.Engineer,
|
||||
CustomRoles.Randomizer => CustomRoles.Crewmate,
|
||||
CustomRoles.Beacon => CustomRoles.Crewmate,
|
||||
CustomRoles.Rabbit => CustomRoles.Crewmate,
|
||||
@@ -671,14 +673,15 @@ internal static class CustomRolesHelper
|
||||
_ => false,
|
||||
};
|
||||
|
||||
public static readonly CustomRoles[] OnlySpawnsWithPetsRoleList =
|
||||
public static readonly List<CustomRoles> OnlySpawnsWithPetsRoleList =
|
||||
[
|
||||
CustomRoles.Tunneler,
|
||||
CustomRoles.Tornado,
|
||||
CustomRoles.Swiftclaw,
|
||||
CustomRoles.Adventurer
|
||||
];
|
||||
|
||||
public static bool OnlySpawnsWithPets(this CustomRoles role) => OnlySpawnsWithPetsRoleList.Any(x => x.ToString() == role.ToString());
|
||||
public static bool OnlySpawnsWithPets(this CustomRoles role) => OnlySpawnsWithPetsRoleList.Contains(role);
|
||||
|
||||
public static bool NeedUpdateOnLights(this CustomRoles role) => (!role.UsesPetInsteadOfKill()) && (role.GetDYRole() != RoleTypes.GuardianAngel || role is
|
||||
CustomRoles.Convict or
|
||||
|
||||
@@ -86,14 +86,17 @@ namespace EHR.Modules
|
||||
{
|
||||
if (CustomTeams.Count == 0 || CustomTeamPlayerIds.Count == 0) return false;
|
||||
|
||||
CustomTeamPlayerIds.Values.Do(x => x.RemoveWhere(p =>
|
||||
CustomTeamPlayerIds.Do(x => x.Value.RemoveWhere(p =>
|
||||
{
|
||||
var pc = Utils.GetPlayerById(p);
|
||||
return pc == null || !pc.IsAlive() || pc.Data.Disconnected;
|
||||
return pc == null || pc.Data.Disconnected;
|
||||
}));
|
||||
|
||||
var team = CustomTeamPlayerIds.Keys.First();
|
||||
if (CustomTeamPlayerIds.Count == 1 && Main.AllAlivePlayerControls.All(x =>
|
||||
var aliveTeamPlayers = CustomTeamPlayerIds.ToDictionary(x => x.Key, x => x.Value);
|
||||
aliveTeamPlayers.Do(x => x.Value.RemoveWhere(p => !Utils.GetPlayerById(p).IsAlive()));
|
||||
|
||||
var team = aliveTeamPlayers.Keys.First();
|
||||
if (aliveTeamPlayers.Count == 1 && Main.AllAlivePlayerControls.All(x =>
|
||||
{
|
||||
var customTeam = GetCustomTeam(x.PlayerId);
|
||||
return customTeam != null && customTeam.Equals(team);
|
||||
@@ -101,7 +104,7 @@ namespace EHR.Modules
|
||||
{
|
||||
WinnerTeam = team;
|
||||
CustomWinnerHolder.ResetAndSetWinner(CustomWinner.CustomTeam);
|
||||
CustomWinnerHolder.WinnerIds = CustomTeamPlayerIds.Values.First();
|
||||
CustomWinnerHolder.WinnerIds = aliveTeamPlayers.Values.First();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ public static class DevManager
|
||||
public static void Init()
|
||||
{
|
||||
// Dev
|
||||
DevUserList.Add(new(code: "actorour#0029", color: "#ffc0cb", tag: "EHR/TONX Developer", isUp: true, isDev: true, deBug: true, colorCmd: true, upName: "KARPED1EM"));
|
||||
DevUserList.Add(new(code: "actorour#0029", color: "#ffc0cb", tag: "TOHE/TONX Developer", isUp: true, isDev: true, deBug: true, colorCmd: true, upName: "KARPED1EM"));
|
||||
DevUserList.Add(new(code: "pinklaze#1776", color: "#30548e", tag: "#Dev", isUp: true, isDev: true, deBug: true, colorCmd: false, upName: "NCSIMON"));
|
||||
DevUserList.Add(new(code: "keepchirpy#6354", color: "#1FF3C6", tag: "Переводчик", isUp: true, isDev: false, deBug: false, colorCmd: true, upName: "TommyXL")); //Tommy-XL
|
||||
DevUserList.Add(new(code: "taskunsold#2701", color: "null", tag: "<color=#426798>Tem</color><color=#f6e509>mie</color>", isUp: false, isDev: true, deBug: false, colorCmd: false, upName: null)); //Tem
|
||||
|
||||
+13
-7
@@ -323,15 +323,21 @@ internal class EAC
|
||||
if (amount is not 64 and not 65) goto YesCheat;
|
||||
break;
|
||||
case SystemTypes.Comms:
|
||||
if (amount == 0)
|
||||
switch (amount)
|
||||
{
|
||||
if (Mapid is 1 or 5) goto YesCheat;
|
||||
case 0:
|
||||
{
|
||||
if (Mapid is 1 or 5) goto YesCheat;
|
||||
break;
|
||||
}
|
||||
case 64 or 65 or 32 or 33 or 16 or 17:
|
||||
{
|
||||
if (Mapid is not (1 or 5)) goto YesCheat;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
goto YesCheat;
|
||||
}
|
||||
else if (amount is 64 or 65 or 32 or 33 or 16 or 17)
|
||||
{
|
||||
if (!(Mapid is 1 or 5)) goto YesCheat;
|
||||
}
|
||||
else goto YesCheat;
|
||||
|
||||
break;
|
||||
case SystemTypes.Electrical:
|
||||
|
||||
@@ -631,13 +631,13 @@ static class ExtendedPlayerControl
|
||||
|
||||
return pc.GetCustomRole() switch
|
||||
{
|
||||
//SoloKombat
|
||||
// SoloKombat
|
||||
CustomRoles.KB_Normal => true,
|
||||
//FFA
|
||||
// FFA
|
||||
CustomRoles.Killer => true,
|
||||
//Move And Stop
|
||||
// Move And Stop
|
||||
CustomRoles.Tasker => false,
|
||||
//Hot Potato
|
||||
// Hot Potato
|
||||
CustomRoles.Potato => false,
|
||||
|
||||
_ => Main.PlayerStates.TryGetValue(pc.PlayerId, out var state) && state.Role.CanUseImpostorVentButton(pc),
|
||||
|
||||
@@ -16,41 +16,59 @@ public class PlayerGameOptionsSender(PlayerControl player) : GameOptionsSender
|
||||
{
|
||||
public static void SetDirty(byte playerId)
|
||||
{
|
||||
foreach (var sender in AllSenders.OfType<PlayerGameOptionsSender>().Where(sender => sender.player.PlayerId == playerId))
|
||||
foreach (GameOptionsSender allSender in AllSenders)
|
||||
{
|
||||
sender.SetDirty();
|
||||
if (allSender is PlayerGameOptionsSender sender && sender.player.PlayerId == playerId)
|
||||
{
|
||||
sender.SetDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetDirtyToAll()
|
||||
{
|
||||
foreach (var sender in AllSenders.OfType<PlayerGameOptionsSender>())
|
||||
foreach (GameOptionsSender allSender in AllSenders)
|
||||
{
|
||||
sender.SetDirty();
|
||||
if (allSender is PlayerGameOptionsSender sender)
|
||||
{
|
||||
sender.SetDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For lights call/fix
|
||||
public static void SetDirtyToAllV2()
|
||||
{
|
||||
foreach (var sender in AllSenders.OfType<PlayerGameOptionsSender>().Where(sender => !sender.IsDirty && sender.player.IsAlive() && (sender.player.GetCustomRole().NeedUpdateOnLights() || sender.player.Is(CustomRoles.Torch) || sender.player.Is(CustomRoles.Mare))))
|
||||
foreach (GameOptionsSender allSender in AllSenders)
|
||||
{
|
||||
sender.SetDirty();
|
||||
if (allSender is PlayerGameOptionsSender { IsDirty: false } sender && sender.player.IsAlive() && (sender.player.GetCustomRole().NeedUpdateOnLights() || sender.player.Is(CustomRoles.Torch) || sender.player.Is(CustomRoles.Mare)))
|
||||
{
|
||||
sender.SetDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For Grenadier blidning/restoring
|
||||
public static void SetDirtyToAllV3()
|
||||
{
|
||||
foreach (var sender in AllSenders.OfType<PlayerGameOptionsSender>().Where(sender => !sender.IsDirty && sender.player.IsAlive() && ((Grenadier.GrenadierBlinding.Count > 0 && (sender.player.GetCustomRole().IsImpostor() || (sender.player.GetCustomRole().IsNeutral() && Options.GrenadierCanAffectNeutral.GetBool()))) || (Grenadier.MadGrenadierBlinding.Count > 0 && !sender.player.GetCustomRole().IsImpostorTeam() && !sender.player.Is(CustomRoles.Madmate)))))
|
||||
foreach (GameOptionsSender allSender in AllSenders)
|
||||
{
|
||||
sender.SetDirty();
|
||||
if (allSender is PlayerGameOptionsSender { IsDirty: false } sender && sender.player.IsAlive() && ((Grenadier.GrenadierBlinding.Count > 0 && (sender.player.GetCustomRole().IsImpostor() || (sender.player.GetCustomRole().IsNeutral() && Options.GrenadierCanAffectNeutral.GetBool()))) || (Grenadier.MadGrenadierBlinding.Count > 0 && !sender.player.GetCustomRole().IsImpostorTeam() && !sender.player.Is(CustomRoles.Madmate))))
|
||||
{
|
||||
sender.SetDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For players with kill buttons
|
||||
public static void SetDirtyToAllV4()
|
||||
{
|
||||
foreach (var sender in AllSenders.OfType<PlayerGameOptionsSender>().Where(sender => !sender.IsDirty && sender.player.IsAlive() && sender.player.CanUseKillButton()).ToArray())
|
||||
foreach (GameOptionsSender allSender in AllSenders)
|
||||
{
|
||||
sender.SetDirty();
|
||||
if (allSender is PlayerGameOptionsSender { IsDirty: false } sender && sender.player.IsAlive() && sender.player.CanUseKillButton())
|
||||
{
|
||||
sender.SetDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,6 +342,13 @@ public class PlayerGameOptionsSender(PlayerControl player) : GameOptionsSender
|
||||
opt.SetFloat(FloatOptionNames.ImpostorLightMod, 0);
|
||||
}
|
||||
|
||||
if (player.IsCrewmate() && Main.PlayerStates.Values.Any(s => s.Role is Adventurer { IsEnable: true } av && av.ActiveWeapons.Contains(Adventurer.Weapon.Lantern)))
|
||||
{
|
||||
opt.SetVision(true);
|
||||
opt.SetFloat(FloatOptionNames.CrewLightMod, 1.5f);
|
||||
opt.SetFloat(FloatOptionNames.ImpostorLightMod, 1.5f);
|
||||
}
|
||||
|
||||
if (Changeling.ChangedRole.TryGetValue(player.PlayerId, out var changed) && changed && player.GetRoleTypes() != RoleTypes.Shapeshifter)
|
||||
{
|
||||
AURoleOptions.ShapeshifterCooldown = 300f;
|
||||
|
||||
+13
-20
@@ -106,24 +106,18 @@ public static class GuessManager
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!pc.Is(CustomRoles.NiceGuesser))
|
||||
if (!pc.Is(CustomRoles.NiceGuesser) && pc.IsCrewmate() && !Options.CrewmatesCanGuess.GetBool() && !pc.Is(CustomRoles.Guesser) && !pc.Is(CustomRoles.Judge) && !pc.Is(CustomRoles.NiceSwapper))
|
||||
{
|
||||
if (pc.IsCrewmate() && !Options.CrewmatesCanGuess.GetBool() && !pc.Is(CustomRoles.Guesser) && !pc.Is(CustomRoles.Judge) && !pc.Is(CustomRoles.NiceSwapper))
|
||||
{
|
||||
if (!isUI) Utils.SendMessage(GetString("GuessNotAllowed"), pc.PlayerId);
|
||||
else pc.ShowPopUp(GetString("GuessNotAllowed"));
|
||||
return true;
|
||||
}
|
||||
if (!isUI) Utils.SendMessage(GetString("GuessNotAllowed"), pc.PlayerId);
|
||||
else pc.ShowPopUp(GetString("GuessNotAllowed"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!pc.Is(CustomRoles.EvilGuesser))
|
||||
if (!pc.Is(CustomRoles.EvilGuesser) && pc.GetCustomRole().IsImpostor() && !Options.ImpostorsCanGuess.GetBool() && !pc.Is(CustomRoles.Guesser) && !pc.Is(CustomRoles.Councillor))
|
||||
{
|
||||
if (pc.GetCustomRole().IsImpostor() && !Options.ImpostorsCanGuess.GetBool() && !pc.Is(CustomRoles.Guesser) && !pc.Is(CustomRoles.Councillor))
|
||||
{
|
||||
if (!isUI) Utils.SendMessage(GetString("GuessNotAllowed"), pc.PlayerId);
|
||||
else pc.ShowPopUp(GetString("GuessNotAllowed"));
|
||||
return true;
|
||||
}
|
||||
if (!isUI) Utils.SendMessage(GetString("GuessNotAllowed"), pc.PlayerId);
|
||||
else pc.ShowPopUp(GetString("GuessNotAllowed"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pc.IsNeutralKiller() && !Options.NeutralKillersCanGuess.GetBool() && !pc.Is(CustomRoles.Guesser))
|
||||
@@ -147,12 +141,11 @@ public static class GuessManager
|
||||
return true;
|
||||
case 2:
|
||||
{
|
||||
if (
|
||||
(pc.Is(CustomRoles.NiceGuesser) && Options.GGTryHideMsg.GetBool()) ||
|
||||
if ((pc.Is(CustomRoles.NiceGuesser) && Options.GGTryHideMsg.GetBool()) ||
|
||||
(pc.Is(CustomRoles.EvilGuesser) && Options.EGTryHideMsg.GetBool()) ||
|
||||
(pc.Is(CustomRoles.Doomsayer) && Doomsayer.DoomsayerTryHideMsg.GetBool()) ||
|
||||
(pc.Is(CustomRoles.Guesser) && Options.GTryHideMsg.GetBool()) || (Options.GuesserMode.GetBool() && Options.HideGuesserCommands.GetBool())
|
||||
) /*TryHideMsg();*/ ChatManager.SendPreviousMessagesToAll();
|
||||
(pc.Is(CustomRoles.Guesser) && Options.GTryHideMsg.GetBool()) || (Options.GuesserMode.GetBool() && Options.HideGuesserCommands.GetBool()))
|
||||
ChatManager.SendPreviousMessagesToAll();
|
||||
else if (pc.AmOwner && !isUI) Utils.SendMessage(originMsg, 255, pc.GetRealName());
|
||||
|
||||
if (!MsgToPlayerAndRole(msg, out byte targetId, out CustomRoles role, out string error))
|
||||
@@ -960,7 +953,7 @@ public static class GuessManager
|
||||
CustomRoleTypes.Impostor => new(255, 25, 25, byte.MaxValue),
|
||||
CustomRoleTypes.Neutral => new(255, 171, 27, byte.MaxValue),
|
||||
CustomRoleTypes.Addon => new Color32(255, 154, 206, byte.MaxValue),
|
||||
_ => throw new NotImplementedException(),
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
Logger.Info(Teamlabel.color.ToString(), ((CustomRoleTypes)index).ToString());
|
||||
Teamlabel.text = GetString("Type" + ((CustomRoleTypes)index));
|
||||
@@ -1026,7 +1019,7 @@ public static class GuessManager
|
||||
Pagelabel.transform.localScale *= 1.6f;
|
||||
Pagelabel.autoSizeTextContainer = true;
|
||||
if (!IsNext && Page <= 1) Pagebutton.GetComponent<SpriteRenderer>().color = new(1, 1, 1, 0.1f);
|
||||
Pagebutton.GetComponent<PassiveButton>().OnClick.AddListener((Action)(() => ClickEvent()));
|
||||
Pagebutton.GetComponent<PassiveButton>().OnClick.AddListener((Action)(ClickEvent));
|
||||
|
||||
PageButtons.Add(Pagebutton.GetComponent<SpriteRenderer>());
|
||||
return;
|
||||
|
||||
@@ -83,12 +83,7 @@ static class LocateArrow
|
||||
/// <returns></returns>
|
||||
public static string GetArrows(PlayerControl seer)
|
||||
{
|
||||
var arrows = string.Empty;
|
||||
foreach (var arrowInfo in LocateArrows.Keys.Where(ai => ai.From == seer.PlayerId))
|
||||
{
|
||||
arrows += LocateArrows[arrowInfo];
|
||||
}
|
||||
return arrows;
|
||||
return LocateArrows.Keys.Where(ai => ai.From == seer.PlayerId).Aggregate(string.Empty, (current, arrowInfo) => current + LocateArrows[arrowInfo]);
|
||||
}
|
||||
/// <summary>
|
||||
/// Check target arrow every FixedUpdate
|
||||
|
||||
@@ -39,6 +39,9 @@ public static class NameColorManager
|
||||
|
||||
switch (Options.CurrentGameMode)
|
||||
{
|
||||
case CustomGameMode.FFA when FFAManager.FFATeamMode.GetBool():
|
||||
color = FFAManager.TeamColors[FFAManager.PlayerTeams[target.PlayerId]];
|
||||
return true;
|
||||
case CustomGameMode.MoveAndStop:
|
||||
color = "#ffffff";
|
||||
return true;
|
||||
|
||||
+13
-14
@@ -929,7 +929,6 @@ public static class Options
|
||||
public static OptionItem MinWaitAutoStart;
|
||||
public static OptionItem MaxWaitAutoStart;
|
||||
public static OptionItem PlayerAutoStart;
|
||||
//public static OptionItem SidekickCountMode;
|
||||
|
||||
public static OptionItem DumpLogAfterGameEnd;
|
||||
|
||||
@@ -1185,21 +1184,21 @@ public static class Options
|
||||
|
||||
var tab = roleClasses.Key.GetTabFromOptionType();
|
||||
|
||||
var categorySuffix = roleClasses.Key switch
|
||||
{
|
||||
RoleOptionType.Neutral_Killing => "NK",
|
||||
RoleOptionType.Neutral_NonKilling => "NNK",
|
||||
_ => string.Empty
|
||||
};
|
||||
TextOptionItem.Create(titleId, $"ROT.Basic{categorySuffix}", tab)
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
.SetColor(Color.gray)
|
||||
.SetHeader(true);
|
||||
titleId += 10;
|
||||
|
||||
var key = roleClasses.Key.GetSimpleRoleOptionType();
|
||||
if (simpleRoleClasses.TryGetValue(key, out ISettingHolder[] value))
|
||||
if (simpleRoleClasses.TryGetValue(key, out ISettingHolder[] value) && value.Length > 0)
|
||||
{
|
||||
var categorySuffix = roleClasses.Key switch
|
||||
{
|
||||
RoleOptionType.Neutral_Killing => "NK",
|
||||
RoleOptionType.Neutral_NonKilling => "NNK",
|
||||
_ => string.Empty
|
||||
};
|
||||
TextOptionItem.Create(titleId, $"ROT.Basic{categorySuffix}", tab)
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
.SetColor(Color.gray)
|
||||
.SetHeader(true);
|
||||
titleId += 10;
|
||||
|
||||
foreach (ISettingHolder holder in value)
|
||||
{
|
||||
holder.SetupCustomOption();
|
||||
|
||||
+30
-22
@@ -42,9 +42,9 @@ other: ∟ ⌠ ⌡ ╬ ╨ ▓ ▒ ░ « » █ ▄ ▌▀▐│ ┤ ╡ ╢
|
||||
|
||||
public static class Utils
|
||||
{
|
||||
private static readonly DateTime timeStampStartTime = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
public static long GetTimeStamp(DateTime? dateTime = null) => (long)((dateTime ?? DateTime.Now).ToUniversalTime() - timeStampStartTime).TotalSeconds;
|
||||
public static long TimeStamp => GetTimeStamp();
|
||||
private static readonly DateTime TimeStampStartTime = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
public static long GetTimeStamp(DateTime? dateTime = null) => (long)((dateTime ?? DateTime.Now).ToUniversalTime() - TimeStampStartTime).TotalSeconds;
|
||||
public static long TimeStamp => (long)(DateTime.Now.ToUniversalTime() - TimeStampStartTime).TotalSeconds;
|
||||
|
||||
public static void ErrorEnd(string text)
|
||||
{
|
||||
@@ -704,6 +704,7 @@ public static class Utils
|
||||
__instance.Is(CustomRoleTypes.Impostor) && PlayerControl.LocalPlayer.Is(CustomRoleTypes.Impostor) && Options.ImpKnowAlliesRole.GetBool() ||
|
||||
__instance.Is(CustomRoleTypes.Impostor) && PlayerControl.LocalPlayer.Is(CustomRoles.Madmate) && Options.MadmateKnowWhosImp.GetBool() ||
|
||||
CustomTeamManager.AreInSameCustomTeam(__instance.PlayerId, PlayerControl.LocalPlayer.PlayerId) ||
|
||||
Adventurer.KnowRole(PlayerControl.LocalPlayer, __instance) ||
|
||||
Totocalcio.KnowRole(PlayerControl.LocalPlayer, __instance) ||
|
||||
Romantic.KnowRole(PlayerControl.LocalPlayer, __instance) ||
|
||||
Lawyer.KnowRole(PlayerControl.LocalPlayer, __instance) ||
|
||||
@@ -716,7 +717,6 @@ public static class Utils
|
||||
PlayerControl.LocalPlayer.IsRevealedPlayer(__instance) ||
|
||||
PlayerControl.LocalPlayer.Is(CustomRoles.God) ||
|
||||
PlayerControl.LocalPlayer.Is(CustomRoles.GM) ||
|
||||
Totocalcio.KnowRole(PlayerControl.LocalPlayer, __instance) ||
|
||||
Lawyer.KnowRole(PlayerControl.LocalPlayer, __instance) ||
|
||||
EvilDiviner.IsShowTargetRole(PlayerControl.LocalPlayer, __instance) ||
|
||||
Executioner.KnowRole(PlayerControl.LocalPlayer, __instance) ||
|
||||
@@ -1587,7 +1587,7 @@ public static class Utils
|
||||
public static void ApplySuffix(PlayerControl player)
|
||||
{
|
||||
if (!AmongUsClient.Instance.AmHost || player == null) return;
|
||||
if (!(player.AmOwner || player.FriendCode.GetDevUser().HasTag())) return;
|
||||
if (!player.AmOwner && !player.FriendCode.GetDevUser().HasTag() && !ChatCommands.IsPlayerModerator(player.FriendCode)) return;
|
||||
string name = Main.AllPlayerNames.TryGetValue(player.PlayerId, out var n) ? n : string.Empty;
|
||||
if (Main.NickName != string.Empty && player.AmOwner) name = Main.NickName;
|
||||
if (name == string.Empty) return;
|
||||
@@ -1786,6 +1786,8 @@ public static class Utils
|
||||
|
||||
if (Options.CurrentGameMode != CustomGameMode.Standard) goto GameMode;
|
||||
|
||||
SelfSuffix.Append(Adventurer.GetSuffixAndHUDText(seer, isForMeeting: isForMeeting));
|
||||
|
||||
if (!isForMeeting)
|
||||
{
|
||||
if (Options.UsePets.GetBool() && Main.AbilityCD.TryGetValue(seer.PlayerId, out var time) && !seer.IsModClient())
|
||||
@@ -1913,7 +1915,6 @@ public static class Utils
|
||||
{
|
||||
case CustomGameMode.FFA:
|
||||
SelfSuffix.Append(FFAManager.GetPlayerArrow(seer));
|
||||
if (FFAManager.FFAChatDuringGame.GetBool()) SelfSuffix.Append(SelfSuffix.Length > 0 && FFAManager.LatestChatMessage != string.Empty ? "\n" : string.Empty).Append(FFAManager.LatestChatMessage);
|
||||
break;
|
||||
case CustomGameMode.SoloKombat:
|
||||
SelfSuffix.Append(SoloKombatManager.GetDisplayHealth(seer));
|
||||
@@ -2028,7 +2029,7 @@ public static class Utils
|
||||
seer.RpcSetNamePrivate(SelfName, true, force: NoCache);
|
||||
|
||||
// Run the second loop only when necessary, such as when seer is dead
|
||||
if (seer.Data.IsDead || !seer.IsAlive() || NoCache || CamouflageIsForMeeting || MushroomMixup || IsActive(SystemTypes.MushroomMixupSabotage) || ForceLoop || seerList.Length == 1 || targetList.Length == 1)
|
||||
if (GameStates.IsLobby || seer.Data.IsDead || !seer.IsAlive() || NoCache || CamouflageIsForMeeting || MushroomMixup || IsActive(SystemTypes.MushroomMixupSabotage) || ForceLoop || seerList.Length == 1 || targetList.Length == 1)
|
||||
{
|
||||
foreach (PlayerControl target in targetList)
|
||||
{
|
||||
@@ -2138,6 +2139,7 @@ public static class Utils
|
||||
(seer.Is(CustomRoleTypes.Crewmate) && target.Is(CustomRoles.Marshall) && target.GetTaskState().IsTaskFinished) ||
|
||||
(Main.PlayerStates[target.PlayerId].deathReason == PlayerState.DeathReason.Vote && Options.SeeEjectedRolesInMeeting.GetBool()) ||
|
||||
CustomTeamManager.AreInSameCustomTeam(seer.PlayerId, target.PlayerId) ||
|
||||
Adventurer.KnowRole(seer, target) ||
|
||||
Totocalcio.KnowRole(seer, target) ||
|
||||
Romantic.KnowRole(seer, target) ||
|
||||
Lawyer.KnowRole(seer, target) ||
|
||||
@@ -2412,25 +2414,30 @@ public static class Utils
|
||||
|
||||
public static void AfterMeetingTasks()
|
||||
{
|
||||
foreach (var pc in Main.AllAlivePlayerControls)
|
||||
foreach (var pc in Main.AllPlayerControls)
|
||||
{
|
||||
pc.AddKillTimerToDict();
|
||||
|
||||
if (pc.Is(CustomRoles.Truant))
|
||||
if (pc.IsAlive())
|
||||
{
|
||||
float beforeSpeed = Main.AllPlayerSpeed[pc.PlayerId];
|
||||
Main.AllPlayerSpeed[pc.PlayerId] = Main.MinSpeed;
|
||||
pc.MarkDirtySettings();
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
Main.AllPlayerSpeed[pc.PlayerId] = beforeSpeed;
|
||||
pc.MarkDirtySettings();
|
||||
}, Options.TruantWaitingTime.GetFloat(), $"Truant Waiting: {pc.GetNameWithRole()}");
|
||||
pc.AddKillTimerToDict();
|
||||
|
||||
if (pc.Is(CustomRoles.Truant))
|
||||
{
|
||||
float beforeSpeed = Main.AllPlayerSpeed[pc.PlayerId];
|
||||
Main.AllPlayerSpeed[pc.PlayerId] = Main.MinSpeed;
|
||||
pc.MarkDirtySettings();
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
Main.AllPlayerSpeed[pc.PlayerId] = beforeSpeed;
|
||||
pc.MarkDirtySettings();
|
||||
}, Options.TruantWaitingTime.GetFloat(), $"Truant Waiting: {pc.GetNameWithRole()}");
|
||||
}
|
||||
|
||||
if (Options.UsePets.GetBool()) pc.AddAbilityCD(includeDuration: false);
|
||||
|
||||
Main.PlayerStates[pc.PlayerId].Role.AfterMeetingTasks();
|
||||
}
|
||||
|
||||
if (Options.UsePets.GetBool()) pc.AddAbilityCD(includeDuration: false);
|
||||
|
||||
Main.PlayerStates[pc.PlayerId].Role.AfterMeetingTasks();
|
||||
if (pc.Is(CustomRoles.Specter) || pc.Is(CustomRoles.Haunter)) pc.RpcResetAbilityCooldown();
|
||||
}
|
||||
|
||||
CopyCat.ResetRole();
|
||||
@@ -2555,6 +2562,7 @@ public static class Utils
|
||||
Tracefinder.OnPlayerDead(target);
|
||||
Vulture.OnPlayerDead(target);
|
||||
Tracker.OnPlayerDeath(target);
|
||||
Adventurer.OnAnyoneDead(target);
|
||||
|
||||
FixedUpdatePatch.LoversSuicide(target.PlayerId, onMeeting);
|
||||
}
|
||||
|
||||
@@ -353,7 +353,7 @@ internal class ChatCommands
|
||||
settings.Append("</size>");
|
||||
var txt = sb.ToString();
|
||||
_ = sb.Clear().Append(txt.RemoveHtmlTags());
|
||||
if (role.PetActivatedAbility()) sb.Append("<size=50%>" + GetString("SupportsPetMessage").RemoveHtmlTags() + "</size>");
|
||||
if (role.PetActivatedAbility() && sb.Length < 1000) sb.Append("<size=50%>" + GetString("SupportsPetMessage").RemoveHtmlTags() + "</size>");
|
||||
sb.Append("<size=70%>");
|
||||
foreach (CustomRoles subRole in Main.PlayerStates[localPlayerId].SubRoles.ToArray())
|
||||
{
|
||||
@@ -939,7 +939,7 @@ internal class ChatCommands
|
||||
_ = sb.Clear().Append(txt);
|
||||
}
|
||||
|
||||
if (rl.PetActivatedAbility()) sb.Append($"<size=50%>{GetString("SupportsPetMessage")}</size>");
|
||||
if (rl.PetActivatedAbility() && sb.Length < 1000) sb.Append($"<size=50%>{GetString("SupportsPetMessage")}</size>");
|
||||
Utils.SendMessage(text: "\n", sendTo: playerId, title: settings.ToString());
|
||||
Utils.SendMessage(text: sb.ToString(), sendTo: playerId, title: title);
|
||||
return;
|
||||
@@ -968,8 +968,7 @@ internal class ChatCommands
|
||||
|
||||
if (GuessManager.GuesserMsg(player, text))
|
||||
{
|
||||
if (GuessManager.GuesserMsg(player, text) ||
|
||||
Judge.TrialMsg(player, text) ||
|
||||
if (Judge.TrialMsg(player, text) ||
|
||||
NiceSwapper.SwapMsg(player, text) ||
|
||||
ParityCop.ParityCheckMsg(player, text) ||
|
||||
Councillor.MurderMsg(player, text))
|
||||
@@ -1045,7 +1044,7 @@ internal class ChatCommands
|
||||
settings.Append("</size>");
|
||||
var txt = sb.ToString();
|
||||
_ = sb.Clear().Append(txt.RemoveHtmlTags());
|
||||
if (role.PetActivatedAbility()) sb.Append("<size=50%>" + GetString("SupportsPetMessage").RemoveHtmlTags() + "</size>");
|
||||
if (role.PetActivatedAbility() && sb.Length < 1000) sb.Append("<size=50%>" + GetString("SupportsPetMessage").RemoveHtmlTags() + "</size>");
|
||||
sb.Append("<size=70%>");
|
||||
foreach (CustomRoles subRole in Main.PlayerStates[player.PlayerId].SubRoles.ToArray())
|
||||
{
|
||||
|
||||
@@ -515,21 +515,42 @@ class GameEndChecker
|
||||
|
||||
Logger.Warn($"Winner: {winner.GetRealName().RemoveHtmlTags()}", "FFA");
|
||||
|
||||
WinnerIds =
|
||||
[
|
||||
winnerId
|
||||
];
|
||||
WinnerIds = [winnerId];
|
||||
|
||||
Main.DoBlockNameChange = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (FFAManager.FFATeamMode.GetBool())
|
||||
{
|
||||
var firstTeam = FFAManager.PlayerTeams.GroupBy(x => x.Value, x => x.Key).Select(x => x.Where(p =>
|
||||
{
|
||||
var pc = GetPlayerById(p);
|
||||
return pc != null && !pc.Data.Disconnected;
|
||||
}).ToHashSet()).FirstOrDefault(x => x.Count > 0);
|
||||
|
||||
if (firstTeam == null)
|
||||
{
|
||||
FFAManager.RoundTime = 0;
|
||||
Logger.Warn("No players alive. Force ending the game", "FFA");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Main.AllAlivePlayerControls.All(x => firstTeam.Contains(x.PlayerId)))
|
||||
{
|
||||
WinnerIds = firstTeam;
|
||||
|
||||
Main.DoBlockNameChange = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
switch (Main.AllAlivePlayerControls.Length)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
var winner = Main.AllAlivePlayerControls.First();
|
||||
var winner = Main.AllAlivePlayerControls[0];
|
||||
|
||||
Logger.Info($"Winner: {winner.GetRealName().RemoveHtmlTags()}", "FFA");
|
||||
|
||||
|
||||
+2
-1
@@ -377,6 +377,7 @@ class HudManagerPatch
|
||||
CustomRoles.Swooper or CustomRoles.Wraith or CustomRoles.Chameleon => Swooper.GetHudText(player),
|
||||
CustomRoles.HeadHunter => HeadHunter.GetHudText(player),
|
||||
CustomRoles.Alchemist => Alchemist.GetHudText(player),
|
||||
CustomRoles.Adventurer => Adventurer.GetSuffixAndHUDText(player, hud: true),
|
||||
CustomRoles.Werewolf => Werewolf.GetHudText(player),
|
||||
CustomRoles.Glitch => Glitch.GetHudText(player),
|
||||
CustomRoles.NiceHacker => NiceHacker.GetHudText(player),
|
||||
@@ -773,7 +774,7 @@ class TaskPanelBehaviourPatch
|
||||
List<(int, byte)> list3 = [];
|
||||
foreach (var id in Main.PlayerStates.Keys) list3.Add((MoveAndStopManager.GetRankOfScore(id), id));
|
||||
list3.Sort();
|
||||
list3 = [.. list3.OrderBy(x => Utils.GetPlayerById(x.Item2).IsAlive())];
|
||||
list3 = [.. list3.OrderBy(x => !Utils.GetPlayerById(x.Item2).IsAlive())];
|
||||
foreach (var id in list3.Where(x => SummaryText3.ContainsKey(x.Item2)).ToArray())
|
||||
{
|
||||
bool alive = Utils.GetPlayerById(id.Item2).IsAlive();
|
||||
|
||||
+23
-1
@@ -182,6 +182,7 @@ class BeginCrewmatePatch
|
||||
var team = CustomTeamManager.GetCustomTeam(PlayerControl.LocalPlayer.PlayerId);
|
||||
if (team != null)
|
||||
{
|
||||
teamToDisplay = new();
|
||||
foreach (var pc in Main.AllPlayerControls)
|
||||
{
|
||||
if (CustomTeamManager.AreInSameCustomTeam(pc.PlayerId, PlayerControl.LocalPlayer.PlayerId))
|
||||
@@ -192,6 +193,18 @@ class BeginCrewmatePatch
|
||||
}
|
||||
}
|
||||
|
||||
if (Options.CurrentGameMode == CustomGameMode.FFA && FFAManager.FFATeamMode.GetBool() && FFAManager.PlayerTeams.TryGetValue(PlayerControl.LocalPlayer.PlayerId, out var ffaTeam))
|
||||
{
|
||||
teamToDisplay = new();
|
||||
foreach (var pc in Main.AllPlayerControls)
|
||||
{
|
||||
if (FFAManager.PlayerTeams.TryGetValue(pc.PlayerId, out var team) && team == ffaTeam)
|
||||
{
|
||||
teamToDisplay.Add(pc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -441,33 +454,42 @@ class BeginCrewmatePatch
|
||||
break;
|
||||
}
|
||||
case CustomGameMode.FFA:
|
||||
{
|
||||
__instance.TeamTitle.text = GetString("Killer");
|
||||
__instance.TeamTitle.color = __instance.BackgroundBar.material.color = new Color32(0, 255, 255, byte.MaxValue);
|
||||
var color = FFAManager.PlayerTeams.TryGetValue(PlayerControl.LocalPlayer.PlayerId, out var team) && ColorUtility.TryParseHtmlString(FFAManager.TeamColors[team], out var teamColor) ? teamColor : new(0, 255, 255, byte.MaxValue);
|
||||
__instance.TeamTitle.color = __instance.BackgroundBar.material.color = color;
|
||||
PlayerControl.LocalPlayer.Data.Role.IntroSound = GetIntroSound(RoleTypes.Shapeshifter);
|
||||
__instance.ImpostorText.gameObject.SetActive(true);
|
||||
__instance.ImpostorText.text = GetString("KillerInfo");
|
||||
break;
|
||||
}
|
||||
case CustomGameMode.MoveAndStop:
|
||||
{
|
||||
__instance.TeamTitle.text = GetString("MoveAndStop");
|
||||
__instance.TeamTitle.color = __instance.BackgroundBar.material.color = new Color32(0, 255, 160, byte.MaxValue);
|
||||
PlayerControl.LocalPlayer.Data.Role.IntroSound = GetIntroSound(RoleTypes.Shapeshifter);
|
||||
__instance.ImpostorText.gameObject.SetActive(true);
|
||||
__instance.ImpostorText.text = GetString("TaskerInfo");
|
||||
break;
|
||||
}
|
||||
case CustomGameMode.HotPotato:
|
||||
{
|
||||
__instance.TeamTitle.text = GetString("HotPotato");
|
||||
__instance.TeamTitle.color = __instance.BackgroundBar.material.color = new Color32(232, 205, 70, byte.MaxValue);
|
||||
PlayerControl.LocalPlayer.Data.Role.IntroSound = GetIntroSound(RoleTypes.Shapeshifter);
|
||||
__instance.ImpostorText.gameObject.SetActive(true);
|
||||
__instance.ImpostorText.text = GetString("PotatoInfo");
|
||||
break;
|
||||
}
|
||||
case CustomGameMode.HideAndSeek:
|
||||
{
|
||||
__instance.TeamTitle.text = GetString("HideAndSeek");
|
||||
__instance.TeamTitle.color = __instance.BackgroundBar.material.color = new Color32(52, 94, 235, byte.MaxValue);
|
||||
PlayerControl.LocalPlayer.Data.Role.IntroSound = GetIntroSound(RoleTypes.Impostor);
|
||||
__instance.ImpostorText.gameObject.SetActive(true);
|
||||
__instance.ImpostorText.text = GetString("SubText.HideAndSeek");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Input.GetKey(KeyCode.RightShift))
|
||||
|
||||
+28
-10
@@ -121,7 +121,7 @@ class CheckForEndVotingPatch
|
||||
}
|
||||
}
|
||||
|
||||
if (__instance.playerStates.TakeWhile(_ => !shouldSkip).Any(ps => !(Main.PlayerStates[ps.TargetPlayerId].IsDead || ps.DidVote)))
|
||||
if (!shouldSkip && !__instance.playerStates.All(ps => Main.PlayerStates[ps.TargetPlayerId].IsDead || ps.DidVote || Utils.GetPlayerById(ps.TargetPlayerId).Data.Disconnected))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -132,7 +132,7 @@ class CheckForEndVotingPatch
|
||||
foreach (var ps in __instance.playerStates)
|
||||
{
|
||||
if (ps == null) continue;
|
||||
voteLog.Info($"{ps.TargetPlayerId,-2}{$"({Utils.GetVoteName(ps.TargetPlayerId)})".PadRightV2(40)}:{ps.VotedFor,-3}{$"({Utils.GetVoteName(ps.VotedFor)})"}");
|
||||
voteLog.Info($"{ps.TargetPlayerId,-2}{$"({Utils.GetVoteName(ps.TargetPlayerId)})".PadRightV2(40)}:{ps.VotedFor,-3}({Utils.GetVoteName(ps.VotedFor)})");
|
||||
var voter = Utils.GetPlayerById(ps.TargetPlayerId);
|
||||
if (voter == null || voter.Data == null || voter.Data.Disconnected) continue;
|
||||
if (Options.VoteMode.GetBool())
|
||||
@@ -195,9 +195,6 @@ class CheckForEndVotingPatch
|
||||
VotedForId = ps.VotedFor
|
||||
});
|
||||
|
||||
Blackmailer.OnCheckForEndVoting();
|
||||
NiceSwapper.OnCheckForEndVoting();
|
||||
|
||||
if (CheckRole(ps.TargetPlayerId, CustomRoles.Mayor) && !Mayor.MayorHideVote.GetBool()) //Mayorの投票数
|
||||
{
|
||||
for (var i2 = 0; i2 < Mayor.MayorAdditionalVote.GetFloat(); i2++)
|
||||
@@ -221,8 +218,20 @@ class CheckForEndVotingPatch
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (Main.PlayerStates[ps.TargetPlayerId].Role is Adventurer { IsEnable: true } av && av.ActiveWeapons.Contains(Adventurer.Weapon.Proxy))
|
||||
{
|
||||
statesList.Add(new()
|
||||
{
|
||||
VoterId = ps.TargetPlayerId,
|
||||
VotedForId = ps.VotedFor
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Blackmailer.OnCheckForEndVoting();
|
||||
NiceSwapper.OnCheckForEndVoting();
|
||||
|
||||
states = [.. statesList];
|
||||
|
||||
var VotingData = __instance.CustomCalculateVotes();
|
||||
@@ -308,13 +317,13 @@ class CheckForEndVotingPatch
|
||||
|
||||
exiledPlayer?.Object.SetRealKiller(null);
|
||||
|
||||
//RPC
|
||||
// RPC
|
||||
if (AntiBlackout.OverrideExiledPlayer)
|
||||
{
|
||||
__instance.RpcVotingComplete(states.ToArray(), null, true);
|
||||
ExileControllerWrapUpPatch.AntiBlackout_LastExiled = exiledPlayer;
|
||||
}
|
||||
else __instance.RpcVotingComplete(states.ToArray(), exiledPlayer, tie); //通常処理
|
||||
else __instance.RpcVotingComplete(states.ToArray(), exiledPlayer, tie);
|
||||
|
||||
CheckForDeathOnExile(PlayerState.DeathReason.Vote, exileId);
|
||||
|
||||
@@ -387,7 +396,10 @@ class CheckForEndVotingPatch
|
||||
if (Options.ShowTeamNextToRoleNameOnEject.GetBool())
|
||||
{
|
||||
name += " (";
|
||||
if (player.GetCustomRole().IsImpostor() || player.Is(CustomRoles.Madmate))
|
||||
var team = CustomTeamManager.GetCustomTeam(player.PlayerId);
|
||||
if (team != null)
|
||||
name += Utils.ColorString(team.RoleRevealScreenBackgroundColor == "*" || !ColorUtility.TryParseHtmlString(team.RoleRevealScreenBackgroundColor, out var color) ? Color.yellow : color, team.RoleRevealScreenTitle == "*" ? team.TeamName : team.RoleRevealScreenTitle);
|
||||
else if (player.GetCustomRole().IsImpostor() || player.Is(CustomRoles.Madmate))
|
||||
name += Utils.ColorString(new(255, 25, 25, byte.MaxValue), GetString("TeamImpostor"));
|
||||
else if (player.GetCustomRole().IsNeutral() || player.Is(CustomRoles.Charmed))
|
||||
name += Utils.ColorString(new(255, 171, 27, byte.MaxValue), GetString("TeamNeutral"));
|
||||
@@ -584,6 +596,11 @@ static class ExtendedMeetingHud
|
||||
) VoteNum += VoteNum;
|
||||
}
|
||||
|
||||
if (Main.PlayerStates[ps.TargetPlayerId].Role is Adventurer { IsEnable: true } av && av.ActiveWeapons.Contains(Adventurer.Weapon.Proxy))
|
||||
{
|
||||
VoteNum++;
|
||||
}
|
||||
|
||||
if (CheckForEndVotingPatch.CheckRole(ps.TargetPlayerId, CustomRoles.TicketsStealer))
|
||||
{
|
||||
var ps1 = ps;
|
||||
@@ -654,7 +671,7 @@ class MeetingHudStartPatch
|
||||
AddMsg(string.Format(GetString("WorkaholicAdviceAlive"), string.Join(separator, workaholicAliveList)), 255, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Workaholic), GetString("WorkaholicAliveTitle")));
|
||||
}
|
||||
|
||||
//Bait Notify
|
||||
// Bait Notify
|
||||
if (MeetingStates.FirstMeeting && CustomRoles.Bait.RoleExist() && Options.BaitNotification.GetBool())
|
||||
{
|
||||
foreach (var pc in Main.AllAlivePlayerControls.Where(x => x.Is(CustomRoles.Bait)).ToArray())
|
||||
@@ -780,6 +797,7 @@ class MeetingHudStartPatch
|
||||
(pc.Is(CustomRoles.Marshall) && PlayerControl.LocalPlayer.Is(CustomRoleTypes.Crewmate) && pc.GetTaskState().IsTaskFinished) ||
|
||||
(Main.PlayerStates[pc.PlayerId].deathReason == PlayerState.DeathReason.Vote && Options.SeeEjectedRolesInMeeting.GetBool()) ||
|
||||
CustomTeamManager.AreInSameCustomTeam(pc.PlayerId, PlayerControl.LocalPlayer.PlayerId) ||
|
||||
Adventurer.KnowRole(PlayerControl.LocalPlayer, pc) ||
|
||||
Totocalcio.KnowRole(PlayerControl.LocalPlayer, pc) ||
|
||||
Romantic.KnowRole(PlayerControl.LocalPlayer, pc) ||
|
||||
EvilDiviner.IsShowTargetRole(PlayerControl.LocalPlayer, pc) ||
|
||||
@@ -834,7 +852,7 @@ class MeetingHudStartPatch
|
||||
|
||||
if (AmongUsClient.Instance.AmHost)
|
||||
{
|
||||
_ = _ = new LateTask(() =>
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
foreach (PlayerControl pc in Main.AllPlayerControls)
|
||||
{
|
||||
|
||||
@@ -231,7 +231,7 @@ class SetEverythingUpPatch
|
||||
{
|
||||
var winnerId = CustomWinnerHolder.WinnerIds.FirstOrDefault();
|
||||
__instance.BackgroundBar.material.color = new Color32(0, 255, 255, 255);
|
||||
WinnerText.text = Main.AllPlayerNames[winnerId] + " wins!";
|
||||
WinnerText.text = FFAManager.FFATeamMode.GetBool() ? string.Empty : Main.AllPlayerNames[winnerId] + " wins!";
|
||||
WinnerText.color = Main.PlayerColors[winnerId];
|
||||
goto EndOfText;
|
||||
}
|
||||
|
||||
@@ -330,6 +330,8 @@ class CheckMurderPatch
|
||||
|
||||
if (Penguin.IsVictim(killer)) return false;
|
||||
|
||||
if (!Adventurer.OnAnyoneCheckMurder(target)) return false;
|
||||
|
||||
if (killer.Is(CustomRoles.Refugee) && target.Is(CustomRoleTypes.Impostor)) return false;
|
||||
|
||||
if (SoulHunter.IsSoulHunterTarget(killer.PlayerId) && target.Is(CustomRoles.SoulHunter))
|
||||
@@ -660,7 +662,7 @@ class ShapeshiftPatch
|
||||
|
||||
if (Main.CheckShapeshift.TryGetValue(shapeshifter.PlayerId, out var last) && last == shapeshifting)
|
||||
{
|
||||
// Dunno how you would get here but ok
|
||||
// Don't know how you would get here but ok
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -720,6 +722,11 @@ class ShapeshiftPatch
|
||||
{
|
||||
pc.Notify(shapeshifting ? GetString("ShiftguardNotifySS") : "ShiftguardNotifyUnshift");
|
||||
}
|
||||
|
||||
if (Main.PlayerStates[pc.PlayerId].Role is Adventurer { IsEnable: true } av)
|
||||
{
|
||||
Adventurer.OnAnyoneShapeshiftLoop(av, __instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1261,6 +1268,8 @@ class FixedUpdatePatch
|
||||
var seer = PlayerControl.LocalPlayer;
|
||||
var target = __instance;
|
||||
|
||||
bool self = seer.PlayerId == target.PlayerId;
|
||||
|
||||
Mark.Clear();
|
||||
Suffix.Clear();
|
||||
|
||||
@@ -1320,8 +1329,6 @@ class FixedUpdatePatch
|
||||
break;
|
||||
}
|
||||
|
||||
bool self = seer.PlayerId == target.PlayerId;
|
||||
|
||||
switch (seer.GetCustomRole())
|
||||
{
|
||||
case CustomRoles.Lookout:
|
||||
@@ -1498,7 +1505,6 @@ class FixedUpdatePatch
|
||||
{
|
||||
case CustomGameMode.FFA:
|
||||
Suffix.Append(FFAManager.GetPlayerArrow(seer, target));
|
||||
if (self && FFAManager.FFAChatDuringGame.GetBool()) Suffix.Append((Suffix.Length > 0 && FFAManager.LatestChatMessage != string.Empty ? "\n" : string.Empty) + FFAManager.LatestChatMessage);
|
||||
break;
|
||||
case CustomGameMode.MoveAndStop when self:
|
||||
Suffix.Append(MoveAndStopManager.GetSuffixText(seer));
|
||||
@@ -1554,20 +1560,9 @@ class FixedUpdatePatch
|
||||
offset += 0.15f;
|
||||
}
|
||||
|
||||
if (!seer.IsAlive())
|
||||
{
|
||||
offset += 0.1f;
|
||||
}
|
||||
|
||||
if (isProgressTextLong)
|
||||
{
|
||||
offset += 0.3f;
|
||||
}
|
||||
|
||||
if (Options.CurrentGameMode == CustomGameMode.MoveAndStop)
|
||||
{
|
||||
offset += 0.2f;
|
||||
}
|
||||
if (!seer.IsAlive()) offset += 0.1f;
|
||||
if (isProgressTextLong) offset += 0.3f;
|
||||
if (Options.CurrentGameMode == CustomGameMode.MoveAndStop) offset += 0.2f;
|
||||
|
||||
RoleText.transform.SetLocalY(offset);
|
||||
}
|
||||
@@ -1688,7 +1683,7 @@ class EnterVentPatch
|
||||
{
|
||||
Logger.Info($" {pc.GetNameWithRole()}, Vent ID: {__instance.Id} ({__instance.name})", "EnterVent");
|
||||
|
||||
if (pc.GetRoleTypes() != RoleTypes.Engineer && !Main.PlayerStates[pc.PlayerId].Role.CanUseImpostorVentButton(pc))
|
||||
if (pc.GetRoleTypes() != RoleTypes.Engineer && !Main.PlayerStates[pc.PlayerId].Role.CanUseImpostorVentButton(pc) && Options.CurrentGameMode == CustomGameMode.Standard)
|
||||
{
|
||||
pc.MyPhysics?.RpcBootFromVent(__instance.Id);
|
||||
return;
|
||||
@@ -1803,10 +1798,7 @@ class CoEnterVentPatch
|
||||
if (Ventguard.BlockedVents.Contains(id))
|
||||
{
|
||||
var pc = __instance.myPlayer;
|
||||
if (Options.VentguardBlockDoesNotAffectCrew.GetBool() && pc.IsCrewmate())
|
||||
{
|
||||
}
|
||||
else
|
||||
if (!Options.VentguardBlockDoesNotAffectCrew.GetBool() || !pc.IsCrewmate())
|
||||
{
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
@@ -1827,7 +1819,7 @@ class CoEnterVentPatch
|
||||
Circumvent.OnCoEnterVent(__instance, id);
|
||||
}
|
||||
|
||||
if (__instance.myPlayer.GetCustomRole().GetDYRole() == RoleTypes.Impostor && !Main.PlayerStates[__instance.myPlayer.PlayerId].Role.CanUseImpostorVentButton(__instance.myPlayer))
|
||||
if (__instance.myPlayer.GetCustomRole().GetDYRole() == RoleTypes.Impostor && !Main.PlayerStates[__instance.myPlayer.PlayerId].Role.CanUseImpostorVentButton(__instance.myPlayer) && Options.CurrentGameMode == CustomGameMode.Standard)
|
||||
{
|
||||
_ = new LateTask(() => { __instance.RpcBootFromVent(id); }, 0.5f);
|
||||
}
|
||||
@@ -1835,7 +1827,7 @@ class CoEnterVentPatch
|
||||
if (((__instance.myPlayer.Data.Role.Role != RoleTypes.Engineer && !__instance.myPlayer.CanUseImpostorVentButton()) ||
|
||||
(__instance.myPlayer.Is(CustomRoles.Mayor) && Mayor.MayorUsedButtonCount.TryGetValue(__instance.myPlayer.PlayerId, out var count) && count >= Mayor.MayorNumOfUseButton.GetInt()) ||
|
||||
(__instance.myPlayer.Is(CustomRoles.Paranoia) && Paranoia.ParaUsedButtonCount.TryGetValue(__instance.myPlayer.PlayerId, out var count2) && count2 >= Options.ParanoiaNumOfUseButton.GetInt()))
|
||||
&& !__instance.myPlayer.Is(CustomRoles.Nimble) && !__instance.myPlayer.Is(CustomRoles.Bloodlust))
|
||||
&& !__instance.myPlayer.Is(CustomRoles.Nimble) && !__instance.myPlayer.Is(CustomRoles.Bloodlust) && Options.CurrentGameMode == CustomGameMode.Standard)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -71,7 +71,7 @@ class RepairSystemPatch
|
||||
if (RepairSender.enabled && AmongUsClient.Instance.NetworkMode != NetworkModes.OnlineGame)
|
||||
Logger.SendInGame("SystemType: " + systemType + ", PlayerName: " + player.GetNameWithRole().RemoveHtmlTags() + ", amount: " + amount);
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return true; //Execute the following only on the host
|
||||
if (!AmongUsClient.Instance.AmHost) return true; // Execute the following only on the host
|
||||
|
||||
IsComms = PlayerControl.LocalPlayer.myTasks.ToArray().Any(x => x.TaskType == TaskTypes.FixComms);
|
||||
|
||||
@@ -79,7 +79,7 @@ class RepairSystemPatch
|
||||
|
||||
if (Options.DisableSabotage.GetBool() && systemType == SystemTypes.Sabotage) return false;
|
||||
|
||||
//Note: "SystemTypes.Laboratory" сauses bugs in the Host, it is better not to use
|
||||
// Note: "SystemTypes.Laboratory" сauses bugs in the Host, it is better not to use
|
||||
if (player.Is(CustomRoles.Fool) &&
|
||||
(systemType is
|
||||
SystemTypes.Comms or
|
||||
@@ -168,20 +168,27 @@ class RepairSystemPatch
|
||||
var SwitchSystem = ShipStatus.Instance?.Systems?[SystemTypes.Electrical]?.Cast<SwitchSystem>();
|
||||
if (SwitchSystem is { IsActive: true })
|
||||
{
|
||||
switch (player.GetCustomRole())
|
||||
switch (Main.PlayerStates[player.PlayerId].Role)
|
||||
{
|
||||
case CustomRoles.SabotageMaster:
|
||||
case SabotageMaster:
|
||||
Logger.Info($"{player.GetNameWithRole().RemoveHtmlTags()} instant-fix-lights", "SwitchSystem");
|
||||
SabotageMaster.SwitchSystemRepair(player.PlayerId, SwitchSystem, amount);
|
||||
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
|
||||
break;
|
||||
case CustomRoles.Alchemist when Main.PlayerStates[player.PlayerId].Role is Alchemist { FixNextSabo: true } am:
|
||||
case Alchemist { FixNextSabo: true } am:
|
||||
Logger.Info($"{player.GetNameWithRole().RemoveHtmlTags()} instant-fix-lights", "SwitchSystem");
|
||||
SwitchSystem.ActualSwitches = 0;
|
||||
SwitchSystem.ExpectedSwitches = 0;
|
||||
am.FixNextSabo = false;
|
||||
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
|
||||
break;
|
||||
case Adventurer av:
|
||||
Logger.Info($"{player.GetNameWithRole().RemoveHtmlTags()} instant-fix-lights", "SwitchSystem");
|
||||
SwitchSystem.ActualSwitches = 0;
|
||||
SwitchSystem.ExpectedSwitches = 0;
|
||||
av.OnLightsFix();
|
||||
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
|
||||
break;
|
||||
}
|
||||
|
||||
if (player.Is(CustomRoles.Damocles) && Damocles.countRepairSabotage) Damocles.OnRepairSabotage(player.PlayerId);
|
||||
|
||||
+48
-12
@@ -240,7 +240,7 @@
|
||||
"Infectious": "Infectious",
|
||||
"Virus": "Virus",
|
||||
"Pursuer": "Pursuer",
|
||||
"Phantom": "Phantom",
|
||||
"Phantom": "Specter",
|
||||
"Pirate": "Pirate",
|
||||
"Jinx": "Jinx",
|
||||
"Maverick": "Maverick",
|
||||
@@ -761,7 +761,7 @@
|
||||
"InfectiousInfoLong": "(Neutrals):\\nAs the Infectious, your job is to infect as many players as you can.\\n\\nIf you infect all the killers, you then can simply outnumber the crew and win the game.",
|
||||
"VirusInfoLong": "(Neutrals):\\nThe virus' goal is to eliminate other players. When a crewmate is killed, their corpse is infected, and the reporting crewmate joins the virus team or dies if the virus isn't voted out. The Virus team wins if they outnumber the Crewmate team.",
|
||||
"PursuerInfoLong": "(Neutrals):\\nAs the Pursuer, you can use your ability on someone to make them shoot a blank when they try to kill (= reset their kill cooldown).\\n\\nTo win, just survive to the end of the game.",
|
||||
"PhantomInfoLong": "(Neutrals):\\nAs the Phantom, your job is to get killed and finish your tasks.\\nYou can do your tasks while alive.\\nYou cannot win if you're alive.\\nIf you get killed, you win with the winning team if your tasks are completed.",
|
||||
"PhantomInfoLong": "(Neutrals):\\nAs the Specter, your job is to get killed and finish your tasks.\\nYou can do your tasks while alive.\\nYou cannot win if you're alive.\\nIf you get killed, you win with the winning team if your tasks are completed.",
|
||||
"PirateInfoLong": "(Neutrals):\\nAs the Pirate, use your kill button to select a target every round. You will duel with your target when in a meeting. If both the Pirate and the target choose the same number Pirate wins.\\nAdditionally, if Pirate wins the duel, or Target doesn't duel Target will suicide.\\n\\nDueling command:- /duel X (where X can be 0, 1 or 2)\\n\\nYou win after winning a certain number of duels set by the host.",
|
||||
"JinxInfoLong": "(Neutrals):\\nAs the Jinx, whenever you are attacked, you jinx them, resulting in them dying to a jinx.\\nThis has limited uses.\\n\\nKill off everyone to win.",
|
||||
"MaverickInfoLong": "(Neutrals):\\nAs the Maverick, you can kill much like a Serial Killer.\\n\\nHowever, you win with the winning team rather than alone.\\nIf you die, you lose.",
|
||||
@@ -1946,7 +1946,7 @@
|
||||
"InfectiousBittenPlayer": "You successfully infected a player",
|
||||
"GuessNotAllowed": "Sorry, your role does not have access to guessing.",
|
||||
"GuessOnbound": "This player has the Onbound add-on, so your guess on them was canceled.",
|
||||
"GuessPhantom": "You can't guess a Phantom, that allows them to win!",
|
||||
"GuessPhantom": "You can't guess a Specter, that allows them to win!",
|
||||
"DovesOfNeaceOnGuard": "Ability used, {0} uses remain",
|
||||
"DovesOfNeaceMaxUsage": "Ability use limit reached",
|
||||
"DovesOfNeaceSkillNotify": "Pacifist reset your kill cooldown",
|
||||
@@ -3106,6 +3106,40 @@
|
||||
"CandleLighterEndVision": "End Vision (Smallest Vision)",
|
||||
"CandleLighterTimeMoveMeeting": "Time Moves During Meetings",
|
||||
"CandleLighterTasksFinishedVision": "Vision after completing all tasks",
|
||||
"AprilFoolsMode": "April Fools Mode",
|
||||
"SilenceMode": "Silencing Method",
|
||||
"Adventurer": "Adventurer",
|
||||
"AdventurerInfo": "Collect Resources to Perform Actions",
|
||||
"AdventurerInfoLong": "(Crewmates):\\nAs the Adventurer, you can collect resources listed below and craft them into weapons if you have the required amount of materials for it.<size=70%>\\n\\n<u><b>Resources (and how to obtain them):</b></u>\\n- ❖ (Complete a Task)\\n- Θ (Players Leave This Behind<sup>*</sup>)\\n- ♳ (Dead Bodies<sup>*</sup>)\\n- ⁂ (Shapeshift Skins<sup>*</sup>)\\n- \u2600 (Fix Lights)\\n- ○ (Found in Groups<sup>*</sup>)\\n<size=50%><sup>*</sup> When this resource is available somewhere, you get an arrow pointing towards that location. (Except dead bodies.) Go there to collect it.</size>\\n\\n<u><b>Weapons (and their ingredients):</b></u>\\n- Gun (1 ♳ + 1 ❖) (Kill someone (pet near them))\\n- Shield (3 ❖) (Gives someone a 1-time shield)\\n- Lantern (1 \u2600 + 1 ❖) (Increases crewmates' vision for some time)\\n- Portal (2 Θ) (Swaps you with a random player)\\n- Wrench (1 \u2600 + 2 ❖) (Clears the current sabotage)\\n- Proxy (2 ○ + 1 ❖) (Gives you +1 vote in the next meeting)\\n- Prediction (1 ♳ + 2 ⁂ + 1 ❖) (Reveals the nearest player's role)\\n- RNG (2 Θ + 2 ❖) (Makes a random weapon)</size>",
|
||||
"AdventurerWeaponDescription.Gun": "Kill the next player you go near",
|
||||
"AdventurerWeaponDescription.Shield": "Gives someone a 1-time shield",
|
||||
"AdventurerWeaponDescription.Lantern": "Increases crewmates' vision for some time",
|
||||
"AdventurerWeaponDescription.Portal": "Swaps you with a random player",
|
||||
"AdventurerWeaponDescription.Wrench": "Clears the current sabotage",
|
||||
"AdventurerWeaponDescription.Proxy": "Gives you +1 vote in the next meeting",
|
||||
"AdventurerWeaponDescription.Prediction": "Reveals the nearest player's role",
|
||||
"AdventurerWeaponDescription.RNG": "Makes a random weapon",
|
||||
"AdventurerIncreasedVisionDuration": "Increased Vision Duration",
|
||||
"AdventurerWeaponEnabled.Gun": "Gun Enabled",
|
||||
"AdventurerWeaponEnabled.Shield": "Healthy Dose Enabled",
|
||||
"AdventurerWeaponEnabled.Lantern": "Lantern Enabled",
|
||||
"AdventurerWeaponEnabled.Portal": "Portal Enabled",
|
||||
"AdventurerWeaponEnabled.Wrench": "Wrench Enabled",
|
||||
"AdventurerWeaponEnabled.Proxy": "Proxy Enabled",
|
||||
"AdventurerWeaponEnabled.Prediction": "Prediction Enabled",
|
||||
"AdventurerWeaponEnabled.RNG": "RNG Enabled",
|
||||
"AdventurerVentToEnterCrafting": "Vent to Enter Crafting Menu",
|
||||
"AdventurerIngredientsDisplay": "{0}: {1}\\nVent to craft this weapon / Pet to cycle to next weapon",
|
||||
"AdventurerWeaponCrafted": "Crafted Weapon: {0}",
|
||||
"AdventurerFound": "Found Resource: {0}",
|
||||
"AdventurerGun.Gun": "Gun",
|
||||
"AdventurerGun.Shield": "Shield",
|
||||
"AdventurerGun.Lantern": "Lantern",
|
||||
"AdventurerGun.Portal": "Portal",
|
||||
"AdventurerGun.Wrench": "Wrench",
|
||||
"AdventurerGun.Proxy": "Proxy",
|
||||
"AdventurerGun.Prediction": "Prediction",
|
||||
"AdventurerGun.RNG": "RNG",
|
||||
"Imitator": "Imitator",
|
||||
"ImitatorInfo": "Your kill cooldown shifts",
|
||||
"ImitatorInfoLong": "(Neutral):\\nAs the Imitator, your kill cooldown is different after every even numbered kill and every odd numbered kill of yours. You have a separate cooldown after meetings. Your first kill after every meeting will set your cooldown to the Even-Numbered Kill Cooldown, your second kill will set it to the Odd-Numbered Kill Cooldown, and the process repeats until a meeting is called again.",
|
||||
@@ -3203,6 +3237,8 @@
|
||||
"FFA_LowerVision": "Lowered Vision",
|
||||
"FFA_ModifiedVisionDuration": "Lowered Vision Duration",
|
||||
"FFA_EnableRandomTwists": "Enable Random Swaps from time to time",
|
||||
"FFA_TeamMode": "Enable Team Mode",
|
||||
"FFA_TeamNumber": "Number of Teams",
|
||||
"FFA-Event-GetShield": "You have a temporary shield!",
|
||||
"FFA-Event-GetIncreasedSpeed": "You have a temporary speed boost!",
|
||||
"FFA-Event-GetLowKCD": "You got a lower kill cooldown!",
|
||||
@@ -3301,8 +3337,8 @@
|
||||
"CommanderInfo": "Command your team",
|
||||
"CommanderInfoLong": "(Impostors):\\nAs the Commander, you can switch between 6 modes by venting/petting your pet. You can execute the selected action by shapeshifting.<size=70%>\\n\\n<b><u>Mark:</u></b> Marks your shapeshift target with a unique color visible to all impostors. Use this to command them to kill that player!\\n\\n<b><u>Whistle:</u></b> This tells all or 1 specific<sup>*</sup> impostor(s) to come to you and gives them (each) an arrow pointing towards you.\\n\\n<b><u>Kill Anyone:</u></b> Notifies all or 1 specific<sup>*</sup> impostor(s) to kill anyone.\\n\\n<b><u>Leave Player Alive:</u></b> Shapeshifting into a crewmate marks that player with a unique color and text telling other impostors to not kill that player. Shapeshifting into an impostor tells that impostor to not kill anyone.\\n\\n<b><u>Don't Sabotage:</u></b> Notifies all impostors to not call any sabotage.\\n\\n<b><u>Use Ability:</u></b> Notifies all or 1 specific<sup>*</sup> impostor(s) to use their ability.\\n\\n<size=60%><sup>*</sup> If you shapeshift into an impostor, the action executes specifically and only on them.</size></size>",
|
||||
"CommanderNotify": "The Commander wants you to meet with them",
|
||||
"CommanderTarget": "<size=1.7>Commander's target</color>",
|
||||
"CommanderDontKill": "<size=1.7>Don't kill this player</color>",
|
||||
"CommanderTarget": "<size=1.7>Commander's target</size>",
|
||||
"CommanderDontKill": "<size=1.7>Don't kill this player</size>",
|
||||
"CommanderWhistling": "Whistling",
|
||||
"CommanderKillAnyoneNotify": "Commander wants you to kill anyone",
|
||||
"CommanderDontSabotageNotify": "Commander wants you to not sabotage",
|
||||
@@ -3421,11 +3457,11 @@
|
||||
"WardenInfoLong": "(Crewmates):\\nAs the Warden, you can protect someone (optimally a crewmate) to notify them about being in danger and to give them a temporary speed boost.",
|
||||
"WardenNotify": "The Warden warns you that you're in danger!",
|
||||
"Prefix.Warden": "Warden",
|
||||
"Specter": "Specter",
|
||||
"Specter": "Phantom",
|
||||
"SpecterInfo": "Finish Tasks to Win!",
|
||||
"SpecterInfoLong": "(Crewmates):\\nAs the Specter, you must finish all of your tasks to win! Depending on a setting, you may also end the game and win alone if you do so!",
|
||||
"SpecterInfoLong": "(Crewmates):\\nAs the Phantom, you must finish all of your tasks to win! Depending on a setting, you may also end the game and win alone if you do so!",
|
||||
"SnatchWin": "Snatches Win (Win With Winning Team if Off)",
|
||||
"Prefix.Specter": "Specter",
|
||||
"Prefix.Specter": "Phantom",
|
||||
"Haunter": "Haunter",
|
||||
"HaunterInfo": "You're the Impostors' Worst Nightmare",
|
||||
"HaunterInfoLong": "(Neutrals):\\nAs the Haunter, when you complete all of your tasks, a random living impostor's name will show in red to everyone in meetings. When you have 1 task left, all impostors will get an arrow pointing towards you, and if any of them come close to you, you lose this role.",
|
||||
@@ -3802,7 +3838,7 @@
|
||||
"WinnerRoleText.Infectious": "Infectious Wins!",
|
||||
"WinnerRoleText.Rogue": "Mavericks Win!",
|
||||
"WinnerRoleText.Virus": "Virus Wins!",
|
||||
"WinnerRoleText.Phantom": "Phantom Wins!",
|
||||
"WinnerRoleText.Phantom": "Specter Wins!",
|
||||
"WinnerRoleText.Jinx": "Jinx Wins!",
|
||||
"WinnerRoleText.CursedSoul": "Cursed Soul Wins!",
|
||||
"WinnerRoleText.Ritualist": "Ritualist Wins!",
|
||||
@@ -3834,7 +3870,7 @@
|
||||
"WinnerRoleText.Sprayer": "Sprayer Wins!",
|
||||
"WinnerRoleText.SoulHunter": "Soul Hunter Wins!",
|
||||
"WinnerRoleText.Tiger": "Tiger Wins!",
|
||||
"WinnerRoleText.Specter": "Specter Wins!",
|
||||
"WinnerRoleText.Specter": "Phantom Wins!",
|
||||
"WinnerRoleText.Default": "{0} Wins!",
|
||||
"AdditionalWinnerRoleText.Sidekick": "along with Sidekicks",
|
||||
"AdditionalWinnerRoleText.Opportunist": "The Opportunist survived",
|
||||
@@ -3848,13 +3884,13 @@
|
||||
"AdditionalWinnerRoleText.Jester": "The Jester wins along",
|
||||
"AdditionalWinnerRoleText.Lovers": "Lovers win along",
|
||||
"AdditionalWinnerRoleText.Executioner": "Executioner wins along",
|
||||
"AdditionalWinnerRoleText.Phantom": "Phantom wins along",
|
||||
"AdditionalWinnerRoleText.Phantom": "Specter wins along",
|
||||
"AdditionalWinnerRoleText.Maverick": "The Maverick survived",
|
||||
"AdditionalWinnerRoleText.Romantic": "The Romantic wins along",
|
||||
"AdditionalWinnerRoleText.VengefulRomantic": "The Vengeful Romantic avenged their lover",
|
||||
"AdditionalWinnerRoleText.Postman": "The Postman delivered mail to everyone",
|
||||
"AdditionalWinnerRoleText.SoulHunter": "Soul Hunter wins along",
|
||||
"AdditionalWinnerRoleText.Specter": "Specter wins along",
|
||||
"AdditionalWinnerRoleText.Specter": "Phantom wins along",
|
||||
"AdditionalWinnerRoleText.Default": "{0} wins along",
|
||||
"ErrorEndText": "An error occurred",
|
||||
"ErrorEndTextDescription": "To avoid crashing, the game was forcibly ended.",
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace EHR.Roles.AddOns.GhostRoles
|
||||
|
||||
GameData.Instance.RpcSetTasks(pc.PlayerId, Array.Empty<byte>());
|
||||
pc.SyncSettings();
|
||||
pc.RpcResetAbilityCooldown();
|
||||
_ = new LateTask(pc.RpcResetAbilityCooldown, 1f, log: false);
|
||||
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
||||
}, 1f, "Specter Assign");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,366 @@
|
||||
using EHR.Patches;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace EHR.Roles.Crewmate
|
||||
{
|
||||
internal class Adventurer : RoleBase
|
||||
{
|
||||
public static bool On;
|
||||
public override bool IsEnable => On;
|
||||
|
||||
enum Resource
|
||||
{
|
||||
TaskCompletion,
|
||||
Random,
|
||||
DeadBody,
|
||||
ShapeshiftSkin,
|
||||
LightsFix,
|
||||
Grouping
|
||||
}
|
||||
|
||||
public enum Weapon
|
||||
{
|
||||
Gun,
|
||||
Shield,
|
||||
Lantern,
|
||||
Portal,
|
||||
Wrench,
|
||||
Proxy,
|
||||
Prediction,
|
||||
RNG
|
||||
}
|
||||
|
||||
private static readonly Dictionary<Resource, (char Icon, Color Color)> ResourceDisplayData = new()
|
||||
{
|
||||
{ Resource.TaskCompletion, ('\u2756', Color.blue) },
|
||||
{ Resource.Random, ('Θ', Color.cyan) },
|
||||
{ Resource.DeadBody, ('\u2673', Color.magenta) },
|
||||
{ Resource.ShapeshiftSkin, ('⁂', Color.gray) },
|
||||
{ Resource.LightsFix, ('\u2600', Color.yellow) },
|
||||
{ Resource.Grouping, ('\u25cb', Color.green) }
|
||||
};
|
||||
|
||||
private static readonly Dictionary<Weapon, List<(Resource Resource, int Count)>> Ingredients = new()
|
||||
{
|
||||
{ Weapon.Gun, [(Resource.DeadBody, 1), (Resource.TaskCompletion, 1)] },
|
||||
{ Weapon.Shield, [(Resource.TaskCompletion, 3)] },
|
||||
{ Weapon.Lantern, [(Resource.LightsFix, 1), (Resource.TaskCompletion, 1)] },
|
||||
{ Weapon.Portal, [(Resource.Random, 2)] },
|
||||
{ Weapon.Wrench, [(Resource.LightsFix, 1), (Resource.TaskCompletion, 2)] },
|
||||
{ Weapon.Proxy, [(Resource.Grouping, 2), (Resource.TaskCompletion, 1)] },
|
||||
{ Weapon.Prediction, [(Resource.DeadBody, 1), (Resource.ShapeshiftSkin, 2), (Resource.TaskCompletion, 1)] },
|
||||
{ Weapon.RNG, [(Resource.Random, 2), (Resource.TaskCompletion, 2)] }
|
||||
};
|
||||
|
||||
private static OptionItem IncreasedVisionDuration;
|
||||
private static readonly Dictionary<Weapon, OptionItem> WeaponEnabledSettings = [];
|
||||
|
||||
private static List<Weapon> EnabledWeapons = [];
|
||||
|
||||
static OptionItem CreateWeaponEnabledSetting(int id, Weapon weapon) => BooleanOptionItem.Create(id, $"AdventurerWeaponEnabled.{weapon}", true, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Adventurer]);
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
Options.SetupRoleOptions(11330, TabGroup.CrewmateRoles, CustomRoles.Adventurer);
|
||||
|
||||
IncreasedVisionDuration = IntegerOptionItem.Create(11332, "AdventurerIncreasedVisionDuration", new(1, 60, 1), 30, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Adventurer])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
|
||||
foreach (var weapon in EnumHelper.GetAllValues<Weapon>())
|
||||
{
|
||||
WeaponEnabledSettings[weapon] = CreateWeaponEnabledSetting(11333 + (int)weapon, weapon);
|
||||
}
|
||||
}
|
||||
|
||||
private PlayerControl AdventurerPC;
|
||||
|
||||
private readonly Dictionary<Resource, int> ResourceCounts = [];
|
||||
public bool InCraftingMode;
|
||||
private Weapon SelectedWeaponToCraft;
|
||||
|
||||
public List<Weapon> OrderedWeapons;
|
||||
public List<Weapon> ActiveWeapons;
|
||||
public HashSet<byte> ShieldedPlayers;
|
||||
public HashSet<byte> RevealedPlayers;
|
||||
|
||||
private long LastRandomResourceTimeStamp;
|
||||
private long LastGroupingResourceTimeStamp;
|
||||
private Dictionary<Resource, Vector2> ResourceLocations;
|
||||
|
||||
public override void Add(byte playerId)
|
||||
{
|
||||
On = true;
|
||||
AdventurerPC = Utils.GetPlayerById(playerId);
|
||||
|
||||
InCraftingMode = false;
|
||||
SelectedWeaponToCraft = new();
|
||||
|
||||
OrderedWeapons = [];
|
||||
ActiveWeapons = [];
|
||||
ShieldedPlayers = [];
|
||||
RevealedPlayers = [];
|
||||
|
||||
LastRandomResourceTimeStamp = Utils.TimeStamp + 8;
|
||||
LastGroupingResourceTimeStamp = Utils.TimeStamp + 20;
|
||||
ResourceLocations = [];
|
||||
|
||||
foreach (var resource in EnumHelper.GetAllValues<Resource>())
|
||||
{
|
||||
ResourceCounts[resource] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
On = false;
|
||||
|
||||
EnabledWeapons = WeaponEnabledSettings
|
||||
.Where(x => x.Value.GetBool())
|
||||
.Select(x => x.Key)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public override void OnExitVent(PlayerControl pc, Vent vent)
|
||||
{
|
||||
InCraftingMode = !InCraftingMode;
|
||||
|
||||
switch (InCraftingMode)
|
||||
{
|
||||
case true:
|
||||
OrderedWeapons = [.. EnabledWeapons.OrderBy(x => !Ingredients[x].All(r => r.Count <= ResourceCounts[r.Resource]))];
|
||||
SelectedWeaponToCraft = OrderedWeapons.FirstOrDefault();
|
||||
break;
|
||||
case false when Ingredients[SelectedWeaponToCraft].All(x => x.Count <= ResourceCounts[x.Resource]):
|
||||
var weapon = SelectedWeaponToCraft == Weapon.RNG ? EnabledWeapons[IRandom.Instance.Next(EnabledWeapons.Count)] : SelectedWeaponToCraft;
|
||||
ActiveWeapons.Add(weapon);
|
||||
pc.Notify(string.Format(Translator.GetString("AdventurerWeaponCrafted"), Translator.GetString($"AdventurerGun.{weapon}")));
|
||||
foreach ((Resource resource, int count) in Ingredients[weapon])
|
||||
{
|
||||
ResourceCounts[resource] -= count;
|
||||
}
|
||||
|
||||
switch (weapon)
|
||||
{
|
||||
case Weapon.Lantern:
|
||||
Utils.MarkEveryoneDirtySettings();
|
||||
_ = new LateTask(() => { ActiveWeapons.Remove(Weapon.Lantern); }, IncreasedVisionDuration.GetInt(), log: false);
|
||||
break;
|
||||
case Weapon.Portal:
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
var e = Main.AllAlivePlayerControls.Where(x => x.PlayerId != pc.PlayerId && !x.inVent && !x.inMovingPlat && !x.onLadder);
|
||||
var filtered = e as PlayerControl[] ?? e.ToArray();
|
||||
if (filtered.Length == 0) return;
|
||||
var target = filtered[IRandom.Instance.Next(filtered.Length)];
|
||||
target.TP(pc);
|
||||
pc.TP(target);
|
||||
ActiveWeapons.Remove(weapon);
|
||||
}, 1f, log: false);
|
||||
break;
|
||||
case Weapon.Wrench:
|
||||
if (Utils.IsActive(SystemTypes.Electrical))
|
||||
{
|
||||
var SwitchSystem = ShipStatus.Instance?.Systems?[SystemTypes.Electrical]?.TryCast<SwitchSystem>();
|
||||
if (SwitchSystem != null)
|
||||
{
|
||||
SwitchSystem.ActualSwitches = 0;
|
||||
SwitchSystem.ExpectedSwitches = 0;
|
||||
}
|
||||
}
|
||||
else if (Utils.IsActive(SystemTypes.Reactor))
|
||||
{
|
||||
ShipStatus.Instance.RpcUpdateSystem(SystemTypes.Reactor, 16);
|
||||
ShipStatus.Instance.RpcUpdateSystem(SystemTypes.Reactor, 17);
|
||||
}
|
||||
else if (Utils.IsActive(SystemTypes.Laboratory))
|
||||
{
|
||||
ShipStatus.Instance.RpcUpdateSystem(SystemTypes.Laboratory, 67);
|
||||
ShipStatus.Instance.RpcUpdateSystem(SystemTypes.Laboratory, 66);
|
||||
}
|
||||
else if (Utils.IsActive(SystemTypes.LifeSupp))
|
||||
{
|
||||
ShipStatus.Instance.RpcUpdateSystem(SystemTypes.LifeSupp, 67);
|
||||
ShipStatus.Instance.RpcUpdateSystem(SystemTypes.LifeSupp, 66);
|
||||
}
|
||||
else if (Utils.IsActive(SystemTypes.Comms))
|
||||
{
|
||||
ShipStatus.Instance.RpcUpdateSystem(SystemTypes.Comms, 16);
|
||||
ShipStatus.Instance.RpcUpdateSystem(SystemTypes.Comms, 17);
|
||||
}
|
||||
|
||||
ActiveWeapons.Remove(weapon);
|
||||
break;
|
||||
case Weapon.Prediction:
|
||||
var closest = Main.AllAlivePlayerControls.Where(x => x.PlayerId != pc.PlayerId).MinBy(x => Vector2.Distance(pc.Pos(), x.Pos()));
|
||||
RevealedPlayers.Add(closest.PlayerId);
|
||||
ActiveWeapons.Remove(weapon);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
||||
}
|
||||
|
||||
public override void OnPet(PlayerControl pc)
|
||||
{
|
||||
switch (InCraftingMode)
|
||||
{
|
||||
case true:
|
||||
SelectedWeaponToCraft = OrderedWeapons[(OrderedWeapons.IndexOf(SelectedWeaponToCraft) + 1) % OrderedWeapons.Count];
|
||||
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
||||
break;
|
||||
case false when ActiveWeapons.Count > 0:
|
||||
var target = ExternalRpcPetPatch.SelectKillButtonTarget(pc);
|
||||
switch (ActiveWeapons[0])
|
||||
{
|
||||
case Weapon.Gun when target != null:
|
||||
pc.RpcCheckAndMurder(target);
|
||||
ActiveWeapons.RemoveAt(0);
|
||||
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
||||
break;
|
||||
case Weapon.Shield when target != null:
|
||||
ShieldedPlayers.Add(target.PlayerId);
|
||||
ActiveWeapons.RemoveAt(0);
|
||||
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnTaskComplete(PlayerControl pc, int completedTaskCount, int totalTaskCount)
|
||||
{
|
||||
ResourceCounts[Resource.TaskCompletion]++;
|
||||
}
|
||||
|
||||
public override void OnGlobalFixedUpdate(PlayerControl pc, bool lowLoad)
|
||||
{
|
||||
long now = Utils.TimeStamp;
|
||||
if (lowLoad) return;
|
||||
|
||||
if (!GameStates.IsInTask)
|
||||
{
|
||||
LastGroupingResourceTimeStamp = now;
|
||||
LastRandomResourceTimeStamp = now;
|
||||
return;
|
||||
}
|
||||
|
||||
if (LastRandomResourceTimeStamp + 20 <= now && pc.PlayerId != AdventurerPC.PlayerId && IRandom.Instance.Next(50) == 0)
|
||||
{
|
||||
var pos = pc.Pos();
|
||||
LocateArrow.Add(AdventurerPC.PlayerId, pos);
|
||||
ResourceLocations[Resource.Random] = pos;
|
||||
LastRandomResourceTimeStamp = now;
|
||||
Utils.NotifyRoles(SpecifySeer: AdventurerPC, SpecifyTarget: AdventurerPC);
|
||||
}
|
||||
|
||||
if (LastGroupingResourceTimeStamp + 20 <= now && Main.AllAlivePlayerControls.Count(x => x.PlayerId != pc.PlayerId && Vector2.Distance(x.Pos(), pc.Pos()) < 2f) >= 2)
|
||||
{
|
||||
var pos = pc.Pos();
|
||||
LocateArrow.Add(AdventurerPC.PlayerId, pos);
|
||||
ResourceLocations[Resource.Grouping] = pos;
|
||||
LastGroupingResourceTimeStamp = now;
|
||||
Utils.NotifyRoles(SpecifySeer: AdventurerPC, SpecifyTarget: AdventurerPC);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnFixedUpdate(PlayerControl pc)
|
||||
{
|
||||
foreach ((Resource resource, Vector2 location) in ResourceLocations)
|
||||
{
|
||||
if (Vector2.Distance(pc.Pos(), location) < 2f)
|
||||
{
|
||||
ResourceCounts[resource]++;
|
||||
ResourceLocations.Remove(resource);
|
||||
LocateArrow.Remove(pc.PlayerId, location);
|
||||
|
||||
var displayData = ResourceDisplayData[resource];
|
||||
pc.Notify(string.Format(Translator.GetString("AdventurerFound"), Utils.ColorString(displayData.Color, $"{displayData.Icon}")));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void AfterMeetingTasks()
|
||||
{
|
||||
ActiveWeapons.Remove(Weapon.Proxy);
|
||||
}
|
||||
|
||||
public void OnLightsFix()
|
||||
{
|
||||
ResourceCounts[Resource.LightsFix]++;
|
||||
}
|
||||
|
||||
public static void OnAnyoneShapeshiftLoop(Adventurer av, PlayerControl shapeshifter)
|
||||
{
|
||||
av.ResourceLocations[Resource.ShapeshiftSkin] = shapeshifter.Pos();
|
||||
}
|
||||
|
||||
public static void OnAnyoneDead(PlayerControl target)
|
||||
{
|
||||
foreach (var state in Main.PlayerStates.Values)
|
||||
{
|
||||
if (state.Role is Adventurer { IsEnable: true } av)
|
||||
{
|
||||
av.ResourceLocations[Resource.DeadBody] = target.Pos();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool OnAnyoneCheckMurder(PlayerControl target)
|
||||
{
|
||||
bool any = false;
|
||||
foreach (var s in Main.PlayerStates.Values)
|
||||
{
|
||||
if (s.Role is Adventurer { IsEnable: true } av && av.ShieldedPlayers.Contains(target.PlayerId))
|
||||
{
|
||||
any = true;
|
||||
av.ShieldedPlayers.Remove(target.PlayerId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return !any;
|
||||
}
|
||||
|
||||
public static bool KnowRole(PlayerControl seer, PlayerControl target)
|
||||
{
|
||||
return Main.PlayerStates[seer.PlayerId].Role is Adventurer { IsEnable: true } av && av.RevealedPlayers.Contains(target.PlayerId);
|
||||
}
|
||||
|
||||
public static string GetSuffixAndHUDText(PlayerControl pc, bool hud = false, bool isForMeeting = false)
|
||||
{
|
||||
if (pc.IsModClient() && !hud) return string.Empty;
|
||||
if (Main.PlayerStates[pc.PlayerId].Role is not Adventurer { IsEnable: true } av) return string.Empty;
|
||||
|
||||
IEnumerable<string> resources =
|
||||
from resource in EnumHelper.GetAllValues<Resource>()
|
||||
let displayData = ResourceDisplayData[resource]
|
||||
select $"{Utils.ColorString(displayData.Color, $"{displayData.Icon}")}{av.ResourceCounts[resource]}";
|
||||
|
||||
string finalText = string.Join(' ', resources);
|
||||
if (isForMeeting) return finalText;
|
||||
|
||||
finalText += $"\n{LocateArrow.GetArrows(pc)}\n";
|
||||
|
||||
finalText += "<size=80%>";
|
||||
finalText += av.InCraftingMode
|
||||
? string.Format(
|
||||
Translator.GetString("AdventurerIngredientsDisplay"),
|
||||
Translator.GetString($"AdventurerGun.{av.SelectedWeaponToCraft}"),
|
||||
string.Join(' ', Ingredients[av.SelectedWeaponToCraft]
|
||||
.Select(x => $"{Utils.ColorString(ResourceDisplayData[x.Resource].Color, $"{ResourceDisplayData[x.Resource].Icon}")}" +
|
||||
$"{Utils.ColorString(x.Count > av.ResourceCounts[x.Resource] ? Color.red : Color.white, $"{x.Count}")}")))
|
||||
: Translator.GetString("AdventurerVentToEnterCrafting");
|
||||
finalText += "</size>";
|
||||
|
||||
return finalText;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -221,7 +221,7 @@ public class Witch : RoleBase
|
||||
{
|
||||
if (Main.PlayerStates[id].Role is Witch { IsEnable: true } wc && wc.IsSpelled(target))
|
||||
{
|
||||
return Utils.ColorString(Palette.ImpostorRed, "†");
|
||||
return Utils.ColorString(wc.IsHM ? Utils.GetRoleColor(CustomRoles.HexMaster) : Palette.ImpostorRed, "†");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace EHR.Roles.Neutral
|
||||
public override void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
|
||||
public override void ApplyGameOptions(IGameOptions opt, byte id) => opt.SetVision(true);
|
||||
public override bool CanUseImpostorVentButton(PlayerControl pc) => CanVent.GetBool();
|
||||
public override bool CanUseSabotage(PlayerControl pc) => true;
|
||||
public override bool CanUseSabotage(PlayerControl pc) => pc.IsAlive();
|
||||
|
||||
public override void OnPet(PlayerControl pc)
|
||||
{
|
||||
|
||||
@@ -96,7 +96,7 @@ public class Glitch : RoleBase
|
||||
|
||||
public override bool IsEnable => playerIdList.Count > 0;
|
||||
public override bool CanUseImpostorVentButton(PlayerControl pc) => CanVent.GetBool();
|
||||
public override bool CanUseSabotage(PlayerControl pc) => true;
|
||||
public override bool CanUseSabotage(PlayerControl pc) => pc.IsAlive();
|
||||
|
||||
void SendRPCSyncTimers()
|
||||
{
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace EHR.Roles.Neutral
|
||||
public override bool IsEnable => HookshotId != byte.MaxValue;
|
||||
public override void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
|
||||
public override bool CanUseImpostorVentButton(PlayerControl pc) => CanVent.GetBool();
|
||||
public override bool CanUseSabotage(PlayerControl pc) => true;
|
||||
public override bool CanUseSabotage(PlayerControl pc) => pc.IsAlive();
|
||||
public override void ApplyGameOptions(IGameOptions opt, byte id) => opt.SetVision(HasImpostorVision.GetBool());
|
||||
|
||||
void SendRPC()
|
||||
|
||||
@@ -88,7 +88,7 @@ public class Jackal : RoleBase
|
||||
public override void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
|
||||
public static bool CanRecruit(byte id) => id.GetAbilityUseLimit() > 0;
|
||||
public override bool CanUseImpostorVentButton(PlayerControl pc) => CanVent.GetBool();
|
||||
public override bool CanUseSabotage(PlayerControl pc) => CanSabotage.GetBool();
|
||||
public override bool CanUseSabotage(PlayerControl pc) => CanSabotage.GetBool() && pc.IsAlive();
|
||||
|
||||
public override void SetButtonTexts(HudManager hud, byte id)
|
||||
{
|
||||
|
||||
@@ -107,7 +107,7 @@ public class Magician : RoleBase
|
||||
public override void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
|
||||
public override void ApplyGameOptions(IGameOptions opt, byte id) => opt.SetVision(HasImpostorVision.GetBool());
|
||||
public override bool CanUseImpostorVentButton(PlayerControl pc) => CanVent.GetBool();
|
||||
public override bool CanUseSabotage(PlayerControl pc) => true;
|
||||
public override bool CanUseSabotage(PlayerControl pc) => pc.IsAlive();
|
||||
|
||||
public override void OnMurder(PlayerControl killer, PlayerControl target)
|
||||
{
|
||||
|
||||
@@ -139,6 +139,6 @@ namespace EHR.Roles.Neutral
|
||||
public override bool OnCheckMurder(PlayerControl killer, PlayerControl target) => IsEnable && target != null && InfectedPlayers.Contains(target.PlayerId);
|
||||
public override void AfterMeetingTasks() => Mycologist_.AddAbilityCD(CD.GetInt());
|
||||
public override bool CanUseImpostorVentButton(PlayerControl pc) => true;
|
||||
public override bool CanUseSabotage(PlayerControl pc) => SpreadAction.GetValue() == 1;
|
||||
public override bool CanUseSabotage(PlayerControl pc) => SpreadAction.GetValue() == 1 && pc.IsAlive();
|
||||
}
|
||||
}
|
||||
@@ -26,5 +26,5 @@ public class Sidekick : RoleBase
|
||||
public override void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = Jackal.KillCooldownSK.GetFloat();
|
||||
public override void ApplyGameOptions(IGameOptions opt, byte id) => opt.SetVision(Jackal.HasImpostorVision.GetBool());
|
||||
public override void SetButtonTexts(HudManager __instance, byte id) => __instance.SabotageButton.ToggleVisible(Jackal.CanSabotageSK.GetBool());
|
||||
public override bool CanUseSabotage(PlayerControl pc) => Jackal.CanSabotageSK.GetBool();
|
||||
public override bool CanUseSabotage(PlayerControl pc) => Jackal.CanSabotageSK.GetBool() && pc.IsAlive();
|
||||
}
|
||||
@@ -85,7 +85,7 @@ namespace EHR.Roles.Neutral
|
||||
public override void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
|
||||
public override void ApplyGameOptions(IGameOptions opt, byte id) => opt.SetVision(HasImpostorVision.GetBool());
|
||||
public override bool CanUseImpostorVentButton(PlayerControl pc) => CanVent.GetBool();
|
||||
public override bool CanUseSabotage(PlayerControl pc) => true;
|
||||
public override bool CanUseSabotage(PlayerControl pc) => pc.IsAlive();
|
||||
|
||||
public override bool OnSabotage(PlayerControl pc)
|
||||
{
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace EHR.Roles.Neutral
|
||||
|
||||
public override bool CanUseSabotage(PlayerControl pc)
|
||||
{
|
||||
return true;
|
||||
return pc.IsAlive();
|
||||
}
|
||||
|
||||
public override bool OnSabotage(PlayerControl pc)
|
||||
|
||||
@@ -43,5 +43,5 @@ public class Traitor : RoleBase
|
||||
public override void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
|
||||
public override void ApplyGameOptions(IGameOptions opt, byte id) => opt.SetVision(HasImpostorVision.GetBool());
|
||||
public override bool CanUseImpostorVentButton(PlayerControl pc) => CanVent.GetBool();
|
||||
public override bool CanUseSabotage(PlayerControl pc) => CanSabotage.GetBool();
|
||||
public override bool CanUseSabotage(PlayerControl pc) => CanSabotage.GetBool() && pc.IsAlive();
|
||||
}
|
||||
@@ -88,7 +88,7 @@ public class WeaponMaster : RoleBase
|
||||
|
||||
public override void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
|
||||
public override bool CanUseImpostorVentButton(PlayerControl pc) => CanVent.GetBool();
|
||||
public override bool CanUseSabotage(PlayerControl pc) => true;
|
||||
public override bool CanUseSabotage(PlayerControl pc) => pc.IsAlive();
|
||||
|
||||
public override void ApplyGameOptions(IGameOptions opt, byte id)
|
||||
{
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ namespace EHR
|
||||
|
||||
public virtual bool CanUseSabotage(PlayerControl pc)
|
||||
{
|
||||
return pc.Is(Team.Impostor) || pc.Is(CustomRoles.Mischievous) || (pc.Is(CustomRoles.Bloodlust) && Bloodlust.HasImpVision.GetBool());
|
||||
return pc.Is(Team.Impostor) || (pc.Is(CustomRoles.Mischievous) || (pc.Is(CustomRoles.Bloodlust) && Bloodlust.HasImpVision.GetBool()) && pc.IsAlive());
|
||||
}
|
||||
|
||||
public virtual void ApplyGameOptions(IGameOptions opt, byte playerId)
|
||||
|
||||
@@ -35,8 +35,8 @@ public class Main : BasePlugin
|
||||
public const string DebugKeySalt = "59687b";
|
||||
public static ConfigEntry<string> DebugKeyInput { get; private set; }
|
||||
public const string PluginGuid = "com.gurge44.endlesshostroles";
|
||||
public const string PluginVersion = "3.1.1";
|
||||
public const string PluginDisplayVersion = "3.1.1";
|
||||
public const string PluginVersion = "3.1.4";
|
||||
public const string PluginDisplayVersion = "3.1.4";
|
||||
public static readonly string SupportedAUVersion = "2024.3.5";
|
||||
|
||||
public Harmony Harmony { get; } = new(PluginGuid);
|
||||
@@ -305,6 +305,7 @@ public class Main : BasePlugin
|
||||
{ CustomRoles.Express, "#00ffff" },
|
||||
{ CustomRoles.NiceEraser, "#00a5ff" },
|
||||
{ CustomRoles.TaskManager, "#00ffa5" },
|
||||
{ CustomRoles.Adventurer, "#fbbb04" },
|
||||
{ CustomRoles.Randomizer, "#fcba03" },
|
||||
{ CustomRoles.Beacon, "#a3fdff" },
|
||||
{ CustomRoles.Rabbit, "#88d2ff" },
|
||||
|
||||
Reference in new issue
Block a user