Add Framer & Backstabber, Try fixing CNO (no success), other fixes

This commit is contained in:
Gurge44 committed 2024-08-06 14:05:09 +02:00
1 parent 1ca029b3c0
commit c5a2069b5b
22 files changed
+281 -75

No files matched your search

+2
View File
@@ -50,6 +50,7 @@ public enum CustomRoles
EvilGuesser,
EvilTracker,
FireWorks,
Framer,
Freezer,
Gambler,
Gangster,
@@ -248,6 +249,7 @@ public enum CustomRoles
Agitater,
Amnesiac,
Arsonist,
Backstabber,
Bandit,
Bargainer,
Beehive,
+30 -26
View File
@@ -20,13 +20,13 @@ namespace EHR
public PlayerControl playerControl;
private float PlayerControlTimer;
public Vector2 Position;
private string Sprite;
private string Sprite;
/*
protected void RpcChangeSprite(string sprite)
{
Sprite = sprite;
LateTask.New(() =>
{
LateTask.New(() => {
playerControl.RawSetName(sprite);
var name = PlayerControl.LocalPlayer.Data.Outfits[PlayerOutfitType.Default].PlayerName;
var colorId = PlayerControl.LocalPlayer.Data.Outfits[PlayerOutfitType.Default].ColorId;
@@ -67,8 +67,9 @@ namespace EHR
writer.EndMessage();
sender.EndMessage();
sender.SendMessage();
}, 0f, "CustomNetObject.RpcChangeSprite");
}, 0f);
}
*/
public void TP(Vector2 position)
{
@@ -78,15 +79,17 @@ namespace EHR
public void Despawn()
{
Logger.Info($" Despawn Custom Net Object {this.GetType().Name} (ID {Id})", "CNO.Despawn");
playerControl.Despawn();
AllObjects.Remove(this);
}
protected void Show(PlayerControl player)
protected void Hide(PlayerControl player)
{
Logger.Info($" Hide Custom Net Object {this.GetType().Name} (ID {Id}) from {player.GetNameWithRole()}", "CNO.Hide");
if (player.AmOwner)
{
playerControl.Visible = true;
playerControl.Visible = false;
return;
}
@@ -107,6 +110,7 @@ namespace EHR
PlayerControlTimer += Time.fixedDeltaTime;
if (PlayerControlTimer > 20f)
{
Logger.Info($" Recreate Custom Net Object {this.GetType().Name} (ID {Id})", "CNO.OnFixedUpdate");
PlayerControl oldPlayerControl = playerControl;
playerControl = Object.Instantiate(AmongUsClient.Instance.PlayerPrefab, Vector2.zero, Quaternion.identity);
playerControl.PlayerId = 255;
@@ -182,11 +186,11 @@ namespace EHR
writer.EndMessage();
sender.EndMessage();
sender.SendMessage();
}, 0.2f, "CustomNetObject.OnFixedUpdate");
}, 0.2f);
LateTask.New(() => oldPlayerControl.Despawn(), 0.3f);
playerControl.cosmetics.currentBodySprite.BodySprite.color = Color.clear;
playerControl.cosmetics.colorBlindText.color = Color.clear;
foreach (var pc in PlayerControl.AllPlayerControls)
foreach (var pc in Main.AllPlayerControls)
{
if (pc.AmOwner) continue;
LateTask.New(() =>
@@ -215,21 +219,23 @@ namespace EHR
}, 0.1f);
}
/*
if (this is TrapArea trapArea)
{
foreach (var pc in PlayerControl.AllPlayerControls)
{
if (trapArea.VisibleList.Contains(pc.PlayerId))
Show(pc);
if (!trapArea.VisibleList.Contains(pc.PlayerId))
Hide(pc);
}
}
*/
PlayerControlTimer = 0f;
}
}
protected void CreateNetObject(string sprite, Vector2 position)
{
Logger.Info($" Create Custom Net Object {this.GetType().Name} (ID {Id}) at {position}", "CNO.CreateNetObject");
playerControl = Object.Instantiate(AmongUsClient.Instance.PlayerPrefab, Vector2.zero, Quaternion.identity);
playerControl.PlayerId = 255;
playerControl.isNew = false;
@@ -304,7 +310,7 @@ namespace EHR
writer.EndMessage();
sender.EndMessage();
sender.SendMessage();
}, 0.2f, "CustomNetObject.CreateNetObject");
}, 0.2f);
Position = position;
PlayerControlTimer = 0f;
playerControl.cosmetics.currentBodySprite.BodySprite.color = Color.clear;
@@ -312,9 +318,9 @@ namespace EHR
Sprite = sprite;
++MaxId;
Id = MaxId;
if (MaxId > 10000) MaxId = 0;
if (MaxId == int.MaxValue) MaxId = int.MinValue;
AllObjects.Add(this);
foreach (var pc in PlayerControl.AllPlayerControls)
foreach (var pc in Main.AllPlayerControls)
{
if (pc.AmOwner) continue;
LateTask.New(() =>
@@ -340,7 +346,7 @@ namespace EHR
writer.EndMessage();
sender.EndMessage();
sender.SendMessage();
}, 0.1f, "CustomNetObject.CreateNetObject_2");
}, 0.1f);
}
}
@@ -361,6 +367,7 @@ namespace EHR
}
}
/*
internal sealed class Explosion : CustomNetObject
{
private readonly float Duration;
@@ -430,7 +437,7 @@ namespace EHR
WaitDuration = waitDuration;
State = 0;
CreateNetObject($"<size={Size}><font=\"VCR SDF\"><#c7c7c769>●", position);
visibleList.Select(x => x.GetPlayer()).DoIf(x => x != null, Show);
Main.AllAlivePlayerControls.ExceptBy(visibleList, x => x.PlayerId).Do(Hide);
}
protected override void OnFixedUpdate()
@@ -451,7 +458,7 @@ namespace EHR
}
}
}
*/
internal sealed class TornadoObject : CustomNetObject
{
private readonly long SpawnTimeStamp;
@@ -461,7 +468,7 @@ namespace EHR
{
SpawnTimeStamp = Utils.TimeStamp;
CreateNetObject("<size=100%><font=\"VCR SDF\"><line-height=72%><alpha=#00>\u2588<alpha=#00>\u2588<#bababa>\u2588<#bababa>\u2588<#bababa>\u2588<#bababa>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<br><alpha=#00>\u2588<#bababa>\u2588<#bababa>\u2588<#8c8c8c>\u2588<#8c8c8c>\u2588<#bababa>\u2588<#bababa>\u2588<alpha=#00>\u2588<br><#bababa>\u2588<#bababa>\u2588<#8c8c8c>\u2588<#8c8c8c>\u2588<#8c8c8c>\u2588<#8c8c8c>\u2588<#bababa>\u2588<#bababa>\u2588<br><#bababa>\u2588<#8c8c8c>\u2588<#8c8c8c>\u2588<#636363>\u2588<#636363>\u2588<#8c8c8c>\u2588<#8c8c8c>\u2588<#bababa>\u2588<br><#bababa>\u2588<#8c8c8c>\u2588<#8c8c8c>\u2588<#636363>\u2588<#636363>\u2588<#8c8c8c>\u2588<#8c8c8c>\u2588<#bababa>\u2588<br><#bababa>\u2588<#bababa>\u2588<#8c8c8c>\u2588<#8c8c8c>\u2588<#8c8c8c>\u2588<#8c8c8c>\u2588<#bababa>\u2588<#bababa>\u2588<br><alpha=#00>\u2588<#bababa>\u2588<#bababa>\u2588<#8c8c8c>\u2588<#8c8c8c>\u2588<#bababa>\u2588<#bababa>\u2588<alpha=#00>\u2588<br><alpha=#00>\u2588<alpha=#00>\u2588<#bababa>\u2588<#bababa>\u2588<#bababa>\u2588<#bababa>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<br></color></line-height></font></size>", position);
visibleList.Select(x => x.GetPlayer()).DoIf(x => x != null, Show);
Main.AllAlivePlayerControls.ExceptBy(visibleList, x => x.PlayerId).Do(Hide);
}
protected override void OnFixedUpdate()
@@ -496,7 +503,7 @@ namespace EHR
public PlayerDetector(Vector2 position, List<byte> visibleList, out int id)
{
CreateNetObject("<size=100%><font=\"VCR SDF\"><line-height=72%><alpha=#00>\u2588<alpha=#00>\u2588<#33e6b0>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<#33e6b0>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<br><alpha=#00>\u2588<#33e6b0>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<#33e6b0>\u2588<alpha=#00>\u2588<br><#33e6b0>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<#33e6b0>\u2588<#33e6b0>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<#33e6b0>\u2588<br><#33e6b0>\u2588<alpha=#00>\u2588<#33e6b0>\u2588<#000000>\u2588<#000000>\u2588<#33e6b0>\u2588<alpha=#00>\u2588<#33e6b0>\u2588<br><#33e6b0>\u2588<alpha=#00>\u2588<#33e6b0>\u2588<#000000>\u2588<#000000>\u2588<#33e6b0>\u2588<alpha=#00>\u2588<#33e6b0>\u2588<br><#33e6b0>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<#33e6b0>\u2588<#33e6b0>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<#33e6b0>\u2588<br><alpha=#00>\u2588<#33e6b0>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<#33e6b0>\u2588<alpha=#00>\u2588<br><alpha=#00>\u2588<alpha=#00>\u2588<#33e6b0>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<#33e6b0>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<br></color></line-height></font></size>", position);
visibleList.Select(x => x.GetPlayer()).DoIf(x => x != null, Show);
Main.AllAlivePlayerControls.ExceptBy(visibleList, x => x.PlayerId).Do(Hide);
id = Id;
}
}
@@ -510,7 +517,7 @@ namespace EHR
Resource = resource;
var data = Adventurer.ResourceDisplayData[resource];
CreateNetObject($"<size=300%><font=\"VCR SDF\"><line-height=72%>{Utils.ColorString(data.Color, data.Icon.ToString())}</line-height></font></size>", position);
visibleList.Select(x => x.GetPlayer()).DoIf(x => x != null, Show);
Main.AllAlivePlayerControls.ExceptBy(visibleList, x => x.PlayerId).Do(Hide);
}
}
@@ -519,7 +526,7 @@ namespace EHR
internal Toilet(Vector2 position, IEnumerable<PlayerControl> hideList)
{
CreateNetObject("<size=100%><font=\"VCR SDF\"><line-height=72%><alpha=#00>\u2588<#e6e6e6>\u2588<#e6e6e6>\u2588<#e6e6e6>\u2588<#e6e6e6>\u2588<#e6e6e6>\u2588<#e6e6e6>\u2588<#e6e6e6>\u2588<#e6e6e6>\u2588<alpha=#00>\u2588<br><#e6e6e6>\u2588<#d3d4ce>\u2588<#d3d4ce>\u2588<#d3d4ce>\u2588<#d3d4ce>\u2588<#d3d4ce>\u2588<#d3d4ce>\u2588<#d3d4ce>\u2588<#d3d4ce>\u2588<#e6e6e6>\u2588<br><#e6e6e6>\u2588<#d3d4ce>\u2588<#d3d4ce>\u2588<#d3d4ce>\u2588<#d3d4ce>\u2588<#d3d4ce>\u2588<#d3d4ce>\u2588<#d3d4ce>\u2588<#d3d4ce>\u2588<#e6e6e6>\u2588<br><alpha=#00>\u2588<#e6e6e6>\u2588<#d3d4ce>\u2588<#d3d4ce>\u2588<#d3d4ce>\u2588<#d3d4ce>\u2588<#d3d4ce>\u2588<#d3d4ce>\u2588<#e6e6e6>\u2588<alpha=#00>\u2588<br><alpha=#00>\u2588<#e6e6e6>\u2588<#e6e6e6>\u2588<#d3d4ce>\u2588<#dedede>\u2588<#dedede>\u2588<#d3d4ce>\u2588<#e6e6e6>\u2588<#e6e6e6>\u2588<alpha=#00>\u2588<br><alpha=#00>\u2588<#bfbfbf>\u2588<#454545>\u2588<#333333>\u2588<#333333>\u2588<#333333>\u2588<#333333>\u2588<#333333>\u2588<#333333>\u2588<#bfbfbf>\u2588<br><alpha=#00>\u2588<#bfbfbf>\u2588<#bfbfbf>\u2588<#454545>\u2588<#454545>\u2588<#454545>\u2588<#454545>\u2588<#454545>\u2588<#454545>\u2588<#bfbfbf>\u2588<br><alpha=#00>\u2588<alpha=#00>\u2588<#bfbfbf>\u2588<#bfbfbf>\u2588<#bfbfbf>\u2588<#bfbfbf>\u2588<#bfbfbf>\u2588<#bfbfbf>\u2588<#bfbfbf>\u2588<#bfbfbf>\u2588<br><alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<#dedede>\u2588<#dedede>\u2588<#dedede>\u2588<#dedede>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<br><alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<#dedede>\u2588<#dedede>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<br></color></line-height></font></size>", position);
Main.AllPlayerControls.Except(hideList).Do(Show);
hideList.Do(Hide);
}
}
@@ -528,7 +535,6 @@ namespace EHR
internal BlackHole(Vector2 position)
{
CreateNetObject("<size=100%><font=\"VCR SDF\"><line-height=72%><alpha=#00>\u2588<alpha=#00>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<br><alpha=#00>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<alpha=#00>\u2588<br><#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<br><#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<br><#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<br><#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<br><alpha=#00>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<alpha=#00>\u2588<br><alpha=#00>\u2588<alpha=#00>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<#000000>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<br></color></line-height></font></size>", position);
Main.AllPlayerControls.Do(Show);
}
}
@@ -537,7 +543,7 @@ namespace EHR
public SprayedArea(Vector2 position, IEnumerable<byte> visibleList)
{
CreateNetObject("<size=100%><font=\"VCR SDF\"><line-height=72%><alpha=#00>\u2588<alpha=#00>\u2588<#ffd000>\u2588<#ffd000>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<br><alpha=#00>\u2588<#ffd000>\u2588<#ffd000>\u2588<#ffd000>\u2588<#ffd000>\u2588<alpha=#00>\u2588<br><#ffd000>\u2588<#ffd000>\u2588<#ffd000>\u2588<#ffd000>\u2588<#ffd000>\u2588<#ffd000>\u2588<br><#ffd000>\u2588<#ffd000>\u2588<#ffd000>\u2588<#ffd000>\u2588<#ffd000>\u2588<#ffd000>\u2588<br><alpha=#00>\u2588<#ffd000>\u2588<#ffd000>\u2588<#ffd000>\u2588<#ffd000>\u2588<alpha=#00>\u2588<br><alpha=#00>\u2588<alpha=#00>\u2588<#ffd000>\u2588<#ffd000>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<br></line-height></size>", position);
visibleList.Select(x => x.GetPlayer()).DoIf(x => x != null, Show);
Main.AllAlivePlayerControls.ExceptBy(visibleList, x => x.PlayerId).Do(Hide);
}
}
@@ -546,7 +552,7 @@ namespace EHR
public CatcherTrap(Vector2 position, PlayerControl catcher)
{
CreateNetObject("<size=100%><font=\"VCR SDF\"><line-height=72%><alpha=#00>\u2588<alpha=#00>\u2588<#ccffda>\u2588<#ccffda>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<br><alpha=#00>\u2588<#ccffda>\u2588<#ccffda>\u2588<#ccffda>\u2588<#ccffda>\u2588<alpha=#00>\u2588<br><#ccffda>\u2588<#ccffda>\u2588<#ccffda>\u2588<#ccffda>\u2588<#ccffda>\u2588<#ccffda>\u2588<br><#ccffda>\u2588<#ccffda>\u2588<#ccffda>\u2588<#ccffda>\u2588<#ccffda>\u2588<#ccffda>\u2588<br><alpha=#00>\u2588<#ccffda>\u2588<#ccffda>\u2588<#ccffda>\u2588<#ccffda>\u2588<alpha=#00>\u2588<br><alpha=#00>\u2588<alpha=#00>\u2588<#ccffda>\u2588<#ccffda>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<br></line-height></size>", position);
Show(catcher);
Main.AllAlivePlayerControls.Without(catcher).Do(Hide);
}
}
@@ -555,7 +561,6 @@ namespace EHR
public YellowFlag(Vector2 position)
{
CreateNetObject("<size=100%><font=\"VCR SDF\"><line-height=72%><#000000>\u2588<#ffff00>\u2588<#ffff00>\u2588<#ffff00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<br><#000000>\u2588<#ffff00>\u2588<#ffff00>\u2588<#ffff00>\u2588<#ffff00>\u2588<#ffff00>\u2588<br><#000000>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<#ffff00>\u2588<#ffff00>\u2588<#ffff00>\u2588<br><#000000>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<br><#000000>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<br><#000000>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<br></line-height></size>", position);
Main.AllPlayerControls.Do(Show);
}
}
@@ -564,7 +569,6 @@ namespace EHR
public BlueFlag(Vector2 position)
{
CreateNetObject("<size=100%><font=\"VCR SDF\"><line-height=72%><#000000>\u2588<#0000ff>\u2588<#0000ff>\u2588<#0000ff>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<br><#000000>\u2588<#0000ff>\u2588<#0000ff>\u2588<#0000ff>\u2588<#0000ff>\u2588<#0000ff>\u2588<br><#000000>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<#0000ff>\u2588<#0000ff>\u2588<#0000ff>\u2588<br><#000000>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<br><#000000>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<br><#000000>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<alpha=#00>\u2588<br></line-height></size>", position);
Main.AllPlayerControls.Do(Show);
}
}
}
+22 -12
View File
@@ -144,6 +144,7 @@ internal static class CustomRolesHelper
CustomRoles.YinYanger => CustomRoles.Impostor,
CustomRoles.Duellist => CustomRoles.Shapeshifter,
CustomRoles.Consort => CustomRoles.Impostor,
CustomRoles.Framer => CustomRoles.Impostor,
CustomRoles.Mafioso => CustomRoles.Impostor,
CustomRoles.Chronomancer => CustomRoles.Impostor,
CustomRoles.Nullifier => CustomRoles.Impostor,
@@ -434,6 +435,7 @@ internal static class CustomRolesHelper
CustomRoles.SchrodingersCat => RoleTypes.Impostor,
CustomRoles.Shifter => RoleTypes.Impostor,
CustomRoles.Impartial => RoleTypes.Impostor,
CustomRoles.Backstabber => RoleTypes.Impostor,
CustomRoles.Predator => RoleTypes.Impostor,
CustomRoles.Reckless => RoleTypes.Impostor,
CustomRoles.Magician => RoleTypes.Impostor,
@@ -583,6 +585,7 @@ internal static class CustomRolesHelper
CustomRoles.Duellist or
CustomRoles.YinYanger or
CustomRoles.Consort or
CustomRoles.Framer or
CustomRoles.Mafioso or
CustomRoles.Nullifier or
CustomRoles.Chronomancer or
@@ -1062,6 +1065,20 @@ internal static class CustomRolesHelper
: CountTypes.Crew
};
public static Color GetTeamColor(this Team team) => ColorUtility.TryParseHtmlString(team switch
{
Team.Crewmate => Main.CrewmateColor,
Team.Neutral => Main.NeutralColor,
Team.Impostor => Main.ImpostorColor,
_ => string.Empty
}, out var color)
? color
: Color.clear;
public static string ToColoredString(this CustomRoles role) => Utils.ColorString(Utils.GetRoleColor(role), Translator.GetString($"{role}"));
#region OptionsAndCategories
public static RoleOptionType GetRoleOptionType(this CustomRoles role)
{
if (role.IsImpostor()) return role.GetImpostorRoleCategory();
@@ -1115,18 +1132,6 @@ internal static class CustomRolesHelper
_ => Palette.CrewmateBlue
};
public static Color GetTeamColor(this Team team) => ColorUtility.TryParseHtmlString(team switch
{
Team.Crewmate => Main.CrewmateColor,
Team.Neutral => Main.NeutralColor,
Team.Impostor => Main.ImpostorColor,
_ => string.Empty
}, out var color)
? color
: Color.clear;
public static string ToColoredString(this CustomRoles role) => Utils.ColorString(Utils.GetRoleColor(role), Translator.GetString($"{role}"));
public static RoleOptionType GetNeutralRoleCategory(this CustomRoles role) => role switch
{
CustomRoles.Opportunist => RoleOptionType.Neutral_Benign,
@@ -1139,6 +1144,7 @@ internal static class CustomRolesHelper
CustomRoles.FFF => RoleOptionType.Neutral_Benign,
CustomRoles.Revolutionist => RoleOptionType.Neutral_Benign,
CustomRoles.Impartial => RoleOptionType.Neutral_Benign,
CustomRoles.Backstabber => RoleOptionType.Neutral_Benign,
CustomRoles.Shifter => RoleOptionType.Neutral_Benign,
CustomRoles.Sunnyboy => RoleOptionType.Neutral_Benign,
CustomRoles.Maverick => RoleOptionType.Neutral_Benign,
@@ -1201,6 +1207,7 @@ internal static class CustomRolesHelper
CustomRoles.Cleaner => RoleOptionType.Impostor_Support,
CustomRoles.Commander => RoleOptionType.Impostor_Support,
CustomRoles.Consort => RoleOptionType.Impostor_Support,
CustomRoles.Framer => RoleOptionType.Impostor_Support,
CustomRoles.Deathpact => RoleOptionType.Impostor_Support,
CustomRoles.Devourer => RoleOptionType.Impostor_Support,
CustomRoles.Disperser => RoleOptionType.Impostor_Support,
@@ -1372,6 +1379,8 @@ internal static class CustomRolesHelper
CustomRoles.Tunneler => RoleOptionType.Crewmate_Miscellaneous,
_ => role.IsImpostor() ? RoleOptionType.Impostor_Miscellaneous : RoleOptionType.Neutral_Benign
};
#endregion
}
#pragma warning disable IDE0079
@@ -1425,6 +1434,7 @@ public enum CountTypes
None,
Crew,
Impostor,
CustomTeam,
Bloodlust,
Jackal,
Doppelganger,
+1 -2
View File
@@ -1,6 +1,5 @@
using System;
using System.Linq;
using EHR.Modules;
using HarmonyLib;
using Hazel;
using InnerNet;
@@ -27,7 +26,7 @@ internal static class EAC
public static bool ReceiveRpc(PlayerControl pc, byte callId, MessageReader reader)
{
if (!AmongUsClient.Instance.AmHost) return false;
if (RoleBasisChanger.IsChangeInProgress) return false;
// if (RoleBasisChanger.IsChangeInProgress) return false;
if (pc == null || reader == null) return false;
try
{
+4 -3
View File
@@ -975,7 +975,7 @@ static class ExtendedPlayerControl
public static bool IsNeutralKiller(this PlayerControl player) => player.Is(CustomRoles.Bloodlust) || player.GetCustomRole().IsNK();
public static bool IsNeutralBenign(this PlayerControl player) => player.GetCustomRole().GetNeutralRoleCategory() == RoleOptionType.Neutral_Benign;
public static bool IsNeutralEvil(this PlayerControl player) => player.GetCustomRole().GetNeutralRoleCategory() == RoleOptionType.Neutral_Evil;
public static bool IsSnitchTarget(this PlayerControl player) => player.Is(CustomRoles.Bloodlust) || player.GetCustomRole().IsSnitchTarget();
public static bool IsSnitchTarget(this PlayerControl player) => player.Is(CustomRoles.Bloodlust) || Framer.FramedPlayers.Contains(player.PlayerId) || player.GetCustomRole().IsSnitchTarget();
public static bool IsMadmate(this PlayerControl player) => player.Is(CustomRoles.Madmate) || player.GetCustomRole().IsMadmate();
public static bool HasGhostRole(this PlayerControl player) => GhostRolesManager.AssignedGhostRoles.ContainsKey(player.PlayerId) || Main.PlayerStates.TryGetValue(player.PlayerId, out var state) && state.SubRoles.Any(x => x.IsGhostRole());
@@ -1019,7 +1019,7 @@ static class ExtendedPlayerControl
}
var State = Main.PlayerStates[target.PlayerId];
if (State.RealKiller.TIMESTAMP != DateTime.MinValue && NotOverRide) return; // Do not overwrite if value already exists
if (State.RealKiller.TimeStamp != DateTime.MinValue && NotOverRide) return; // Do not overwrite if value already exists
byte killerId = killer == null ? byte.MaxValue : killer.PlayerId;
RPC.SetRealKiller(target.PlayerId, killerId);
}
@@ -1061,7 +1061,7 @@ static class ExtendedPlayerControl
public static bool Is(this PlayerControl target, Team team) => team switch
{
Team.Impostor => (target.IsMadmate() || target.GetCustomRole().IsImpostorTeamV2()) && !target.Is(CustomRoles.Bloodlust),
Team.Impostor => (target.IsMadmate() || target.GetCustomRole().IsImpostorTeamV2() || Framer.FramedPlayers.Contains(target.PlayerId)) && !target.Is(CustomRoles.Bloodlust),
Team.Neutral => target.GetCustomRole().IsNeutralTeamV2() || target.Is(CustomRoles.Bloodlust),
Team.Crewmate => target.GetCustomRole().IsCrewmateTeamV2(),
Team.None => target.Is(CustomRoles.GM) || target.Is(CountTypes.None) || target.Is(CountTypes.OutOfGame),
@@ -1070,6 +1070,7 @@ static class ExtendedPlayerControl
public static Team GetTeam(this PlayerControl target)
{
if (Framer.FramedPlayers.Contains(target.PlayerId)) return Team.Impostor;
var subRoles = target.GetCustomSubRoles();
if (target.Is(CustomRoles.Bloodlust) || subRoles.Any(x => x.IsConverted())) return Team.Neutral;
if (subRoles.Contains(CustomRoles.Madmate)) return Team.Impostor;
+5 -2
View File
@@ -64,7 +64,7 @@ public class PlayerState(byte playerId)
public CountTypes countTypes = CountTypes.Crew;
public PlainShipRoom LastRoom;
public CustomRoles MainRole = CustomRoles.NotAssigned;
public (DateTime TIMESTAMP, byte ID) RealKiller = (DateTime.MinValue, byte.MaxValue);
public (DateTime TimeStamp, byte ID) RealKiller = (DateTime.MinValue, byte.MaxValue);
public RoleBase Role = new VanillaRole();
public List<CustomRoles> SubRoles = [];
public Dictionary<byte, string> TargetColorData = [];
@@ -93,6 +93,9 @@ public class PlayerState(byte playerId)
};
}
if (CustomTeamManager.GetCustomTeam(PlayerId) != null && !CustomTeamManager.IsSettingEnabledForPlayerTeam(PlayerId, CTAOption.WinWithOriginalTeam))
countTypes = CountTypes.CustomTeam;
SubRoles.ForEach(SetAddonCountTypes);
Role = role.GetRoleClass();
@@ -283,7 +286,7 @@ public class PlayerState(byte playerId)
public void InitTask(PlayerControl player) => taskState.Init(player);
public void UpdateTask(PlayerControl player) => taskState.Update(player);
public byte GetRealKiller() => IsDead && RealKiller.TIMESTAMP != DateTime.MinValue ? RealKiller.ID : byte.MaxValue;
public byte GetRealKiller() => IsDead && RealKiller.TimeStamp != DateTime.MinValue ? RealKiller.ID : byte.MaxValue;
public int GetKillCount(bool ExcludeSelfKill = false) => Main.PlayerStates.Values.Where(state => !(ExcludeSelfKill && state.PlayerId == PlayerId) && state.GetRealKiller() == PlayerId).ToArray().Length;
}
+1 -1
View File
@@ -93,7 +93,7 @@ namespace EHR.Modules
{
if (Options.CurrentGameMode != CustomGameMode.Standard) return false;
if (AssignedGhostRoles.Count >= GhostRoles.Count) return false;
if (pc.IsAlive() || pc.GetCountTypes() is CountTypes.None or CountTypes.OutOfGame || pc.Is(CustomRoles.EvilSpirit)) return false;
if (pc.IsAlive() || pc.GetCountTypes() is CountTypes.None or CountTypes.OutOfGame || pc.Is(CustomRoles.EvilSpirit) || pc.Is(CustomRoles.Backstabber)) return false;
var suitableRole = GetSuitableGhostRole(pc);
return suitableRole switch
-1
View File
@@ -243,7 +243,6 @@ public static class Options
public static OptionItem VindicatorHideVote;
public static OptionItem DoctorTaskCompletedBatteryCharge;
public static OptionItem TrapperBlockMoveTime;
public static OptionItem DetectiveCanknowKiller;
public static OptionItem TransporterTeleportMax;
public static OptionItem CanTerroristSuicideWin;
public static OptionItem InnocentCanWinByImp;
+1 -1
View File
@@ -1115,7 +1115,7 @@ internal static class RPC
public static void SetRealKiller(byte targetId, byte killerId)
{
var state = Main.PlayerStates[targetId];
state.RealKiller.TIMESTAMP = DateTime.Now;
state.RealKiller.TimeStamp = DateTime.Now;
state.RealKiller.ID = killerId;
if (!AmongUsClient.Instance.AmHost) return;
+3 -2
View File
@@ -1,4 +1,4 @@
using AmongUs.GameOptions;
/*using AmongUs.GameOptions;
using HarmonyLib;
using Hazel;
using InnerNet;
@@ -98,4 +98,5 @@ namespace EHR.Modules
}
}
}
}
}*/
+8 -13
View File
@@ -680,6 +680,7 @@ public static class Utils
case CustomRoles.SchrodingersCat:
case CustomRoles.Shifter:
case CustomRoles.Impartial:
case CustomRoles.Backstabber:
case CustomRoles.Predator:
case CustomRoles.Reckless:
case CustomRoles.WeaponMaster:
@@ -1797,16 +1798,11 @@ public static class Utils
public static void NotifyRoles(bool isForMeeting = false, PlayerControl SpecifySeer = null, PlayerControl SpecifyTarget = null, bool NoCache = false, bool ForceLoop = false, bool CamouflageIsForMeeting = false, bool GuesserIsForMeeting = false, bool MushroomMixup = false)
{
//if (Options.DeepLowLoad.GetBool()) await Task.Run(() => { DoNotifyRoles(isForMeeting, SpecifySeer, NoCache, ForceLoop, CamouflageIsForMeeting, GuesserIsForMeeting); });
/*else */
if (!SetUpRoleTextPatch.IsInIntro && ((SpecifySeer != null && SpecifySeer.IsModClient()) || !AmongUsClient.Instance.AmHost || Main.AllPlayerControls == null || (GameStates.IsMeeting && !isForMeeting) || GameStates.IsLobby)) return;
if (SetUpRoleTextPatch.IsInIntro || isForMeeting || CamouflageIsForMeeting || GuesserIsForMeeting || MushroomMixup) _ = DoNotifyRoles(isForMeeting, SpecifySeer, SpecifyTarget, NoCache, ForceLoop, CamouflageIsForMeeting, GuesserIsForMeeting, MushroomMixup);
else Main.Instance.StartCoroutine(DoNotifyRoles(false, SpecifySeer, SpecifyTarget, NoCache, ForceLoop));
DoNotifyRoles(isForMeeting, SpecifySeer, SpecifyTarget, NoCache, ForceLoop, CamouflageIsForMeeting, GuesserIsForMeeting, MushroomMixup);
}
public static System.Collections.IEnumerator DoNotifyRoles(bool isForMeeting = false, PlayerControl SpecifySeer = null, PlayerControl SpecifyTarget = null, bool NoCache = false, bool ForceLoop = false, bool CamouflageIsForMeeting = false, bool GuesserIsForMeeting = false, bool MushroomMixup = false)
public static void DoNotifyRoles(bool isForMeeting = false, PlayerControl SpecifySeer = null, PlayerControl SpecifyTarget = null, bool NoCache = false, bool ForceLoop = false, bool CamouflageIsForMeeting = false, bool GuesserIsForMeeting = false, bool MushroomMixup = false)
{
PlayerControl[] seerList = SpecifySeer != null ? [SpecifySeer] : Main.AllPlayerControls;
PlayerControl[] targetList = SpecifyTarget != null ? [SpecifyTarget] : Main.AllPlayerControls;
@@ -1816,8 +1812,6 @@ public static class Utils
// seer: Players who can see changes made here
// target: Players subject to changes that seer can see
int i = 0;
bool instant = SetUpRoleTextPatch.IsInIntro || isForMeeting || CamouflageIsForMeeting || GuesserIsForMeeting || MushroomMixup;
foreach (PlayerControl seer in seerList)
{
try
@@ -2293,12 +2287,13 @@ public static class Utils
{
Logger.Error($"Error for {seer.GetNameWithRole()}: {ex}", "NR");
}
i++;
if (i % 3 == 0 && !instant) yield return null;
}
Logger.Info($" Seers: {seerLogInfo.ToString().TrimEnd(',', ' ')} ---- Targets: {targetLogInfo.ToString().TrimEnd(',', ' ')}", "NR");
string seers = seerLogInfo.ToString().TrimEnd(',', ' ');
string targets = targetLogInfo.ToString().TrimEnd(',', ' ');
if (seers.Length == 0) seers = "\u2205";
if (targets.Length == 0) targets = "\u2205";
Logger.Info($" Seers: {seers} ---- Targets: {targets}", "NR");
}
public static void MarkEveryoneDirtySettings()
+5 -1
View File
@@ -177,6 +177,10 @@ class GameEndChecker
WinnerIds.Add(pc.PlayerId);
AdditionalWinnerTeams.Add(AdditionalWinners.Impartial);
break;
case CustomRoles.Backstabber when (Main.PlayerStates[pc.PlayerId].Role as Backstabber).CheckWin():
WinnerIds.Add(pc.PlayerId);
AdditionalWinnerTeams.Add(AdditionalWinners.Backstabber);
break;
case CustomRoles.Predator when (Main.PlayerStates[pc.PlayerId].Role as Predator).IsWon:
WinnerIds.Add(pc.PlayerId);
AdditionalWinnerTeams.Add(AdditionalWinners.Predator);
@@ -405,7 +409,7 @@ class GameEndChecker
if ((!role.IsNK() && role != CustomRoles.Bloodlust) || role.IsMadmate() || role is CustomRoles.Sidekick) continue;
var countTypes = role.GetCountTypes();
if (countTypes is CountTypes.Crew or CountTypes.Impostor or CountTypes.None or CountTypes.OutOfGame) continue;
if (countTypes is CountTypes.Crew or CountTypes.Impostor or CountTypes.None or CountTypes.OutOfGame or CountTypes.CustomTeam) continue;
CustomRoles? keyRole = role.IsRecruitingRole() ? null : role;
CustomWinner keyWinner = (CustomWinner)role;
+1 -1
View File
@@ -18,7 +18,7 @@ class SetUpRoleTextPatch
{
// After showing team for non-modded clients, update player names.
IsInIntro = false;
_ = Utils.DoNotifyRoles(NoCache: true);
Utils.DoNotifyRoles(NoCache: true);
var lp = PlayerControl.LocalPlayer;
+2 -2
View File
@@ -56,9 +56,9 @@ class EndGamePatch
}
var sb = new StringBuilder(GetString("KillLog") + ":");
foreach ((byte key, PlayerState value) in Main.PlayerStates.OrderBy(x => x.Value.RealKiller.TIMESTAMP.Ticks))
foreach ((byte key, PlayerState value) in Main.PlayerStates.OrderBy(x => x.Value.RealKiller.TimeStamp.Ticks))
{
var date = value.RealKiller.TIMESTAMP;
var date = value.RealKiller.TimeStamp;
if (date == DateTime.MinValue) continue;
var killerId = value.GetRealKiller();
var gmIsFM = Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.MoveAndStop;
+16
View File
@@ -1408,6 +1408,9 @@
"PsychicCanSeeNum": "Max number of red names",
"PsychicFresh": "New red names every meeting",
"DetectiveCanknowKiller": "Can find the killer's role",
"DetectiveCanknowDeathReason": "Can find the cause of death",
"DetectiveCanknowAddons": "Can find the dead player's add-ons",
"DetectiveCanknowKillTime": "Can find how long ago the player died",
"ParanoiaVentCooldown": "Vent Cooldown",
"ParanoiaNumOfUseButton": "Max number of portable buttons",
"EveryOneKnowSuperStar": "Everyone knows the <color=#f6f657>Super Star</color>",
@@ -1898,6 +1901,9 @@
"DetectiveNoticeVictim": "According to your investigation,\\nthe victim (<b>{0}</b>) had the role [{1}]",
"DetectiveNoticeKiller": "\\nThe killer's role is <b>{0}</b>",
"DetectiveNoticeKillerNotFound": "The Detective couldn't find evidence leading to a murderer, this is most likely suicide.",
"DetectiveNoticeDeathReason": "\\nThe victim's cause of death is <b>{0}</b>",
"DetectiveNoticeAddons": "\\nThe victim's add-ons are: <b>{0}</b>",
"DetectiveNoticeKillTime": "\\nThe victim died <b>{0}</b> seconds ago",
"SleuthMsg": "{0}'s role is: {1}",
"GodNoticeAlive": "During the meeting, each player felt a revelation from heaven, and it turned out that God is still alive!",
"WorkaholicAdviceAlive": "It's not recommended to kill or vote <b>{0}</b> out. Doing so will help them finish their tasks quicker.",
@@ -3605,6 +3611,16 @@
"LibrarianNormalMode": "Normal",
"CanKillWhileShifted": "Can Kill While Shapeshifting",
"Shapeshift": "Shapeshift",
"Framer": "Framer",
"FramerInfo": "Frame Other Players",
"FramerInfoLong": "(Impostors):\\nAs the Framer, single click with your kill button on someone to frame them, making the game think they're on the impostor team. Double click to kill normally.",
"Framer.TargetFramedNotify": "The game now thinks {0} is an <#ff1919>impostor</color>",
"Backstabber": "Backstabber",
"BackstabberInfo": "Stab a Team in the Back",
"BackstabberInfoLong": "(Neutral):\\nAs the Backstabber, you can optionally kill 1 player. If you don't kill anyone, you will win with the crewmates. If you kill an Impostor or a Madmate, you will win with the winning Neutral Killer. If you kill anyone other than an Impostor or a Madmate, you will win with the Impostors.",
"Backstabber.MurderNotify": "Your kill target was {0}\\nThis means, you'll win with {1}",
"BackstabberTeam.Imp": "the <#ff1919>Impostors</color>",
"BackstabberTeam.NK": "a <#ffab1b>Neutral Killer</color>",
"Postman": "Postman",
"PostmanInfo": "Deliver Mail to Everyone!",
"PostmanInfoLong": "(Neutral):\\nAs the Postman, your job is to deliver mail to everyone. You'll always have a target, and you need to click your kill button on that target to deliver the mail to them. When you've delivered mail to everyone, your win condition is satisfied. You'll win with the winning team, no matter what happens.",
+35 -3
View File
@@ -1,9 +1,16 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
namespace EHR.Crewmate
{
internal class Detective : RoleBase
{
public static OptionItem DetectiveCanknowKiller;
public static OptionItem DetectiveCanknowDeathReason;
public static OptionItem DetectiveCanknowAddons;
public static OptionItem DetectiveCanknowKillTime;
public static Dictionary<byte, string> DetectiveNotify = [];
public override bool IsEnable => false;
@@ -11,7 +18,13 @@ namespace EHR.Crewmate
public override void SetupCustomOption()
{
Options.SetupRoleOptions(6600, TabGroup.CrewmateRoles, CustomRoles.Detective);
Options.DetectiveCanknowKiller = new BooleanOptionItem(6610, "DetectiveCanknowKiller", true, TabGroup.CrewmateRoles)
DetectiveCanknowKiller = new BooleanOptionItem(6610, "DetectiveCanknowKiller", true, TabGroup.CrewmateRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Detective]);
DetectiveCanknowDeathReason = new BooleanOptionItem(6611, "DetectiveCanknowDeathReason", true, TabGroup.CrewmateRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Detective]);
DetectiveCanknowAddons = new BooleanOptionItem(6612, "DetectiveCanknowAddons", true, TabGroup.CrewmateRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Detective]);
DetectiveCanknowKillTime = new BooleanOptionItem(6613, "DetectiveCanknowKillTime", true, TabGroup.CrewmateRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Detective]);
}
@@ -26,13 +39,32 @@ namespace EHR.Crewmate
public static void OnReportDeadBody(PlayerControl player, PlayerControl tpc)
{
string msg = string.Format(Translator.GetString("DetectiveNoticeVictim"), tpc.GetRealName(), tpc.GetCustomRole().ToColoredString());
if (Options.DetectiveCanknowKiller.GetBool())
if (DetectiveCanknowKiller.GetBool())
{
var realKiller = tpc.GetRealKiller();
if (realKiller == null) msg += ";" + Translator.GetString("DetectiveNoticeKillerNotFound");
else msg += ";" + string.Format(Translator.GetString("DetectiveNoticeKiller"), realKiller.GetCustomRole().ToColoredString());
}
if (DetectiveCanknowDeathReason.GetBool())
{
msg += ";" + string.Format(Translator.GetString("DetectiveNoticeDeathReason"), Translator.GetString($"DeathReason.{Main.PlayerStates[tpc.PlayerId].deathReason}"));
}
if (DetectiveCanknowAddons.GetBool())
{
msg += ";" + string.Format(Translator.GetString("DetectiveNoticeAddons"), string.Join(", ", tpc.GetCustomSubRoles().Select(x => x.ToColoredString())));
}
if (DetectiveCanknowKillTime.GetBool())
{
var deathTimeStamp = Main.PlayerStates[tpc.PlayerId].RealKiller.TimeStamp;
var now = DateTime.UtcNow;
var timeSpanSeconds = (now - deathTimeStamp).TotalSeconds;
msg += ";" + string.Format(Translator.GetString("DetectiveNoticeKillTime"), (int)timeSpanSeconds);
}
DetectiveNotify.Add(player.PlayerId, msg);
}
}
+2 -1
View File
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using AmongUs.GameOptions;
using EHR.Impostor;
using EHR.Modules;
using Hazel;
using static EHR.Options;
@@ -92,7 +93,7 @@ public class Psychic : RoleBase
if (!IsEnable || !AmongUsClient.Instance.AmHost) return;
List<PlayerControl> BadListPc = Main.AllAlivePlayerControls.Where(x =>
(x.Is(CustomRoleTypes.Impostor) && !x.Is(CustomRoles.Trickster)) || x.Is(CustomRoles.Madmate) || x.Is(CustomRoles.Rascal) || x.Is(CustomRoles.Recruit) || x.Is(CustomRoles.Charmed) || x.Is(CustomRoles.Contagious) ||
(x.Is(CustomRoleTypes.Impostor) && !x.Is(CustomRoles.Trickster)) || x.Is(CustomRoles.Madmate) || x.Is(CustomRoles.Rascal) || Framer.FramedPlayers.Contains(x.PlayerId) || x.IsConverted() ||
(x.GetCustomRole().GetCrewmateRoleCategory() == RoleOptionType.Crewmate_Killing && CkshowEvil.GetBool()) ||
(x.GetCustomRole().GetNeutralRoleCategory() == RoleOptionType.Neutral_Evil && NEshowEvil.GetBool()) ||
(x.GetCustomRole().GetNeutralRoleCategory() == RoleOptionType.Neutral_Benign && NBshowEvil.GetBool())
+50
View File
@@ -0,0 +1,50 @@
using System.Collections.Generic;
namespace EHR.Impostor
{
public class Framer : RoleBase
{
public static bool On;
public static readonly HashSet<byte> FramedPlayers = [];
private static OptionItem AbilityUseLimit;
private static OptionItem FramerAbilityUseGainWithEachKill;
public override bool IsEnable => On;
public override void SetupCustomOption()
{
Options.SetupRoleOptions(647196, TabGroup.ImpostorRoles, CustomRoles.Framer);
AbilityUseLimit = new IntegerOptionItem(647198, "AbilityUseLimit", new(0, 5, 1), 0, TabGroup.ImpostorRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Framer])
.SetValueFormat(OptionFormat.Times);
FramerAbilityUseGainWithEachKill = new FloatOptionItem(647199, "AbilityUseGainWithEachKill", new(0f, 5f, 0.1f), 0.4f, TabGroup.ImpostorRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Framer])
.SetValueFormat(OptionFormat.Times);
}
public override void Init()
{
On = false;
FramedPlayers.Clear();
}
public override void Add(byte playerId)
{
On = true;
playerId.SetAbilityUseLimit(AbilityUseLimit.GetInt());
}
public override bool OnCheckMurder(PlayerControl killer, PlayerControl target)
{
if (killer.GetAbilityUseLimit() < 1f) return true;
return killer.CheckDoubleTrigger(target, () =>
{
FramedPlayers.Add(target.PlayerId);
killer.SetKillCooldown();
killer.Notify(string.Format(Translator.GetString("Framer.TargetFramedNotify"), target.PlayerId.ColoredPlayerName()));
killer.RpcRemoveAbilityUse();
});
}
}
}
+83
View File
@@ -0,0 +1,83 @@
using AmongUs.GameOptions;
namespace EHR.Neutral
{
public class Backstabber : RoleBase
{
public static bool On;
private static OptionItem KillCooldown;
private static OptionItem CanVent;
private static OptionItem HasImpostorVision;
private WinningTeam Team;
public override bool IsEnable => On;
public override void SetupCustomOption()
{
int id = 649100;
Options.SetupRoleOptions(id++, TabGroup.NeutralRoles, CustomRoles.Backstabber);
KillCooldown = new FloatOptionItem(++id, "KillCooldown", new(0f, 180f, 0.5f), 15f, TabGroup.NeutralRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Backstabber])
.SetValueFormat(OptionFormat.Seconds);
CanVent = new BooleanOptionItem(++id, "CanVent", true, TabGroup.NeutralRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Backstabber]);
HasImpostorVision = new BooleanOptionItem(++id, "ImpostorVision", true, TabGroup.NeutralRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Backstabber]);
}
public override void Init()
{
On = false;
}
public override void Add(byte playerId)
{
On = true;
Team = WinningTeam.Crew;
playerId.SetAbilityUseLimit(1);
}
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 OnCheckMurder(PlayerControl killer, PlayerControl target)
{
return killer.GetAbilityUseLimit() > 0f;
}
public override void OnMurder(PlayerControl killer, PlayerControl target)
{
Team targetTeam = target.GetTeam();
Team = targetTeam switch
{
EHR.Team.Impostor => WinningTeam.NK,
_ => WinningTeam.Imp
};
killer.RpcRemoveAbilityUse();
killer.Notify(string.Format(Translator.GetString("Backstabber.MurderNotify"), Utils.ColorString(targetTeam.GetTeamColor(), Translator.GetString(targetTeam.ToString())), Translator.GetString($"BackstabberTeam.{Team}")), 10f);
}
public bool CheckWin()
{
return CustomWinnerHolder.WinnerTeam switch
{
CustomWinner.Crewmate => Team == WinningTeam.Crew,
CustomWinner.Impostor => Team == WinningTeam.Imp,
CustomWinner.Neutrals => Team == WinningTeam.NK,
CustomWinner.None => false,
CustomWinner.Default or CustomWinner.Draw or CustomWinner.Error => true,
_ => Team == WinningTeam.NK
};
}
enum WinningTeam
{
Crew,
Imp,
NK
}
}
}
+5 -2
View File
@@ -28,6 +28,7 @@ public class Jackal : RoleBase
private static OptionItem PromotedSKCanRecruit;
public static bool On;
private byte SidekickId;
public override bool IsEnable => PlayerIdList.Count > 0;
@@ -88,6 +89,7 @@ public class Jackal : RoleBase
On = true;
PlayerIdList.Add(playerId);
playerId.SetAbilityUseLimit(1);
SidekickId = byte.MaxValue;
}
public override void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
@@ -117,6 +119,7 @@ public class Jackal : RoleBase
killer.RpcRemoveAbilityUse();
target.RpcSetCustomRole(targetRoleType == RoleTypes.Shapeshifter ? CustomRoles.Recruit : CustomRoles.Sidekick);
// if (needBasisChange) target.ChangeRoleBasis(RoleTypes.Impostor);
SidekickId = target.PlayerId;
Main.ResetCamPlayerList.Add(target.PlayerId);
@@ -146,8 +149,8 @@ public class Jackal : RoleBase
public override void OnFixedUpdate(PlayerControl pc)
{
if (!SKPromotesToJackal.GetBool() || pc.IsAlive()) return;
var sk = Main.AllPlayerControls.FirstOrDefault(x => x.Is(CustomRoles.Sidekick));
if (sk == null) return;
var sk = SidekickId.GetPlayer();
if (sk == null || !sk.Is(CustomRoles.Sidekick)) return;
sk.RpcSetCustomRole(CustomRoles.Jackal);
if (!PromotedSKCanRecruit.GetBool()) sk.SetAbilityUseLimit(0);
}
+1
View File
@@ -3,6 +3,7 @@
internal class VanillaRole : RoleBase
{
public static bool On;
public override bool IsEnable => On;
public override void SetupCustomOption()
+4 -2
View File
@@ -180,7 +180,7 @@ public class Main : BasePlugin
int i = 0;
foreach (var pc in PlayerControl.AllPlayerControls)
{
if (pc == null) continue;
if (pc == null || pc.PlayerId == 255) continue;
result[i++] = pc;
}
@@ -200,7 +200,7 @@ public class Main : BasePlugin
int i = 0;
foreach (var pc in PlayerControl.AllPlayerControls)
{
if (pc == null || !pc.IsAlive() || pc.Data.Disconnected || Pelican.IsEaten(pc.PlayerId)) continue;
if (pc == null || pc.PlayerId == 255 || !pc.IsAlive() || pc.Data.Disconnected || Pelican.IsEaten(pc.PlayerId)) continue;
result[i++] = pc;
}
@@ -491,6 +491,7 @@ public class Main : BasePlugin
{ CustomRoles.SchrodingersCat, "#616161" },
{ CustomRoles.Shifter, "#777777" },
{ CustomRoles.Impartial, "#4287f5" },
{ CustomRoles.Backstabber, "#fcba03" },
{ CustomRoles.Predator, "#c73906" },
{ CustomRoles.Reckless, "#6e000d" },
{ CustomRoles.Magician, "#BF5FFF" },
@@ -864,6 +865,7 @@ public enum AdditionalWinners
Maverick = CustomRoles.Maverick,
Postman = CustomRoles.Postman,
Impartial = CustomRoles.Impartial,
Backstabber = CustomRoles.Backstabber,
Predator = CustomRoles.Predator,
SoulHunter = CustomRoles.SoulHunter,
SchrodingersCat = CustomRoles.SchrodingersCat