Add Gatekeeper

This commit is contained in:
Gurge44 committed 2026-07-10 12:58:15 +02:00
1 parent 6f64958a0e
commit 1f2e2b4de5
5 files changed
+128

No files matched your search

+1
View File
@@ -68,6 +68,7 @@ public enum CustomRoles
Frightener,
Gambler,
Gangster,
Gatekeeper,
Generator,
Godfather,
Greedy,
+1
View File
@@ -68,6 +68,7 @@ public enum CustomRoles
Frightener,
Gambler,
Gangster,
Gatekeeper,
Generator,
Godfather,
Greedy,
+3
View File
@@ -162,6 +162,7 @@ internal static class CustomRolesHelper
CustomRoles.Exclusionary => CustomRoles.Impostor,
CustomRoles.Centralizer => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
CustomRoles.Venerer => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
CustomRoles.Gatekeeper => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
CustomRoles.Kidnapper => CustomRoles.Shapeshifter,
CustomRoles.Frightener => CustomRoles.Shapeshifter,
CustomRoles.Chainbinder => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
@@ -774,6 +775,7 @@ internal static class CustomRolesHelper
CustomRoles.Psychopath or
CustomRoles.Ambusher or
CustomRoles.Kidnapper or
CustomRoles.Gatekeeper or
CustomRoles.Exorcist or
CustomRoles.Frightener or
CustomRoles.Obstructer or
@@ -1265,6 +1267,7 @@ internal static class CustomRolesHelper
CustomRoles.EvilEraser => RoleOptionType.Impostor_Support,
CustomRoles.Freezer => RoleOptionType.Impostor_Support,
CustomRoles.Gangster => RoleOptionType.Impostor_Support,
CustomRoles.Gatekeeper => RoleOptionType.Impostor_Support,
CustomRoles.Godfather => RoleOptionType.Impostor_Support,
CustomRoles.Hypnotist => RoleOptionType.Impostor_Support,
CustomRoles.Librarian => RoleOptionType.Impostor_Support,
+4
View File
@@ -1945,6 +1945,10 @@
"GangsterRecruitLimit": "Recruit limit",
"GangsterRecruitmentFailure": "Target cannot be recruited",
"GangsterSuccessfullyRecruited": "You successfully recruited a player",
"Gatekeeper": "Gatekeeper",
"GatekeeperInfo": "Keep Track Of People In Rooms",
"GatekeeperInfoLong": "(Impostors):\\nAs the Gatekeeper, you may pet/shapeshift to mark the room you're in. From now, you'll now see how many living players are in that room, updated in real time. Dead bodies aren't counted.",
"Gatekeeper.MaxRoomsMarkedAtOnce": "Max Rooms Marked At Once",
"Generator": "Generator",
"GeneratorInfo": "Power up the ship",
"GeneratorInfoLong": "(Impostors):\\nAs the Generator, you generate charges every second. You can only kill/vent/shapeshift/sabotage if you have enough charges to do so. You also lose charges while shapeshifted.",
@@ -0,0 +1,119 @@
using System.Collections.Generic;
using System.Linq;
using EHR.Modules;
using Hazel;
namespace EHR.Roles;
public class Gatekeeper : RoleBase
{
public static bool On;
private static OptionItem AbilityUseLimit;
private static OptionItem AbilityUseGainWithEachKill;
private static OptionItem MaxRoomsMarkedAtOnce;
public override bool IsEnable => On;
private Dictionary<SystemTypes, int> MarkedRooms = [];
private StringBuilder Suffix;
private byte GatekeeperId;
public override void SetupCustomOption()
{
StartSetup(659200)
.AutoSetupOption(ref AbilityUseLimit, 1f, new FloatValueRule(0, 20, 0.05f), OptionFormat.Times)
.AutoSetupOption(ref AbilityUseGainWithEachKill, 1f, new FloatValueRule(0f, 5f, 0.1f), OptionFormat.Times)
.AutoSetupOption(ref MaxRoomsMarkedAtOnce, 5, new IntegerValueRule(1, 30, 1));
}
public override void Init()
{
On = false;
}
public override void Add(byte playerId)
{
On = true;
Suffix = new();
MarkedRooms = [];
GatekeeperId = playerId;
playerId.SetAbilityUseLimit(AbilityUseLimit.GetFloat());
}
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (!shapeshifting) return true;
MarkRoom(shapeshifter);
return false;
}
public override void OnPet(PlayerControl pc)
{
MarkRoom(pc);
}
private void MarkRoom(PlayerControl pc)
{
if (pc.GetAbilityUseLimit() < 1f) return;
var room = pc.GetPlainShipRoom();
if (room && MarkedRooms.TryAdd(room.RoomId, -1))
{
pc.RpcRemoveAbilityUse();
if (MarkedRooms.Count > MaxRoomsMarkedAtOnce.GetInt())
MarkedRooms.Remove(MarkedRooms.Keys.First());
}
}
public override void OnFixedUpdate(PlayerControl pc)
{
if (!pc.IsAlive() || !PerSecondUpdateScheduler.ShouldRunUpdate(pc.PlayerId)) return;
bool first = true;
bool changed = false;
var aapc = Main.CachedAlivePlayerControls();
Suffix.Clear();
Suffix.Append("<size=80%>");
foreach ((SystemTypes markedRoom, int oldCount) in MarkedRooms)
{
int newCount = aapc.Count(x => x.IsInRoom(markedRoom));
MarkedRooms[markedRoom] = newCount;
if (oldCount != newCount) changed = true;
if (!first) Suffix.Append('\n');
Suffix.Append("<#00a5ff>");
Suffix.Append(Translator.GetString(markedRoom));
Suffix.Append("</color>");
Suffix.Append(' ');
Suffix.Append('-');
Suffix.Append(' ');
Suffix.Append("<#00ffff>");
Suffix.Append(newCount);
Suffix.Append("</color>");
first = false;
}
if (changed)
{
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
if (pc.IsNonHostModdedClient()) Utils.SendRPC(CustomRPC.SyncRoleData, pc.PlayerId, MarkedRooms.Count > 5 ? Suffix.ToString().RemoveHtmlTags() : Suffix.ToString());
}
}
public void ReceiveRPC(MessageReader reader)
{
Suffix.Clear();
Suffix.Append(reader.ReadString());
}
public override string GetSuffix(PlayerControl seer, PlayerControl target, bool hud = false, bool meeting = false)
{
if (seer.PlayerId != GatekeeperId || seer.PlayerId != target.PlayerId || (seer.IsModdedClient() && !hud) || meeting) return string.Empty;
return Suffix.ToString();
}
}