mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-20 01:46:25 +00:00
Add Framer & Backstabber, Try fixing CNO (no success), other fixes
This commit is contained in:
1 parent
1ca029b3c0
commit
c5a2069b5b
22 files changed
+281
-75
No files matched your search
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.",
|
||||
|
||||
@@ -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,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())
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
internal class VanillaRole : RoleBase
|
||||
{
|
||||
public static bool On;
|
||||
|
||||
public override bool IsEnable => On;
|
||||
|
||||
public override void SetupCustomOption()
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user