mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-20 11:39:54 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d816b7c063 | ||
|
|
24924815a6 | ||
|
|
5f5ebd137e | ||
|
|
e219d884da | ||
|
|
ca6baa56fe | ||
|
|
39dd11eddb | ||
|
|
4b7e308417 |
No files matched your search
@@ -272,6 +272,7 @@ public enum CustomRoles
|
||||
Ritualist,
|
||||
Romantic,
|
||||
RuthlessRomantic,
|
||||
Samurai,
|
||||
SchrodingersCat,
|
||||
NSerialKiller, // Serial Killer
|
||||
Sidekick,
|
||||
|
||||
@@ -272,6 +272,7 @@ public enum CustomRoles
|
||||
Ritualist,
|
||||
Romantic,
|
||||
RuthlessRomantic,
|
||||
Samurai,
|
||||
SchrodingersCat,
|
||||
NSerialKiller, // Serial Killer
|
||||
Sidekick,
|
||||
|
||||
@@ -85,11 +85,14 @@ internal static class FFAManager
|
||||
.SetGameMode(CustomGameMode.FFA)
|
||||
.SetColor(new Color32(0, 255, 165, byte.MaxValue))
|
||||
.SetValueFormat(OptionFormat.Multiplier);
|
||||
FFAModifiedSpeedDuration = FloatOptionItem.Create(67_223_009, "FFA_ModifiedSpeedDuration", new(1f, 60f, 1f), 10f, TabGroup.GameSettings).SetGameMode(CustomGameMode.FFA).SetColor(new Color32(0, 255, 165, byte.MaxValue))
|
||||
FFAModifiedSpeedDuration = FloatOptionItem.Create(67_223_009, "FFA_ModifiedSpeedDuration", new(1f, 60f, 1f), 10f, TabGroup.GameSettings)
|
||||
.SetGameMode(CustomGameMode.FFA).SetColor(new Color32(0, 255, 165, byte.MaxValue))
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
FFALowerVision = FloatOptionItem.Create(67_223_010, "FFA_LowerVision", new(0f, 1f, 0.05f), 0.5f, TabGroup.GameSettings).SetGameMode(CustomGameMode.FFA).SetColor(new Color32(0, 255, 165, byte.MaxValue))
|
||||
FFALowerVision = FloatOptionItem.Create(67_223_010, "FFA_LowerVision", new(0f, 1f, 0.05f), 0.5f, TabGroup.GameSettings)
|
||||
.SetGameMode(CustomGameMode.FFA).SetColor(new Color32(0, 255, 165, byte.MaxValue))
|
||||
.SetValueFormat(OptionFormat.Multiplier);
|
||||
FFAModifiedVisionDuration = FloatOptionItem.Create(67_223_011, "FFA_ModifiedVisionDuration", new(1f, 70f, 1f), 5f, TabGroup.GameSettings).SetGameMode(CustomGameMode.FFA).SetColor(new Color32(0, 255, 165, byte.MaxValue))
|
||||
FFAModifiedVisionDuration = FloatOptionItem.Create(67_223_011, "FFA_ModifiedVisionDuration", new(1f, 70f, 1f), 5f, TabGroup.GameSettings)
|
||||
.SetGameMode(CustomGameMode.FFA).SetColor(new Color32(0, 255, 165, byte.MaxValue))
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
FFAEnableRandomTwists = BooleanOptionItem.Create(67_223_012, "FFA_EnableRandomTwists", true, TabGroup.GameSettings)
|
||||
.SetGameMode(CustomGameMode.FFA)
|
||||
|
||||
@@ -333,6 +333,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.BloodKnight => RoleTypes.Impostor,
|
||||
CustomRoles.Poisoner => RoleTypes.Impostor,
|
||||
CustomRoles.NSerialKiller => RoleTypes.Impostor,
|
||||
CustomRoles.Samurai => RoleTypes.Impostor,
|
||||
CustomRoles.Bargainer => RoleTypes.Impostor,
|
||||
CustomRoles.Tiger => RoleTypes.Impostor,
|
||||
CustomRoles.SoulHunter => RoleTypes.Impostor,
|
||||
@@ -434,6 +435,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Refugee or
|
||||
CustomRoles.Parasite or
|
||||
CustomRoles.NSerialKiller or
|
||||
CustomRoles.Samurai or
|
||||
CustomRoles.Bargainer or
|
||||
CustomRoles.Tiger or
|
||||
CustomRoles.Enderman or
|
||||
@@ -1158,6 +1160,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.PlagueBearer => CountTypes.PlagueBearer,
|
||||
CustomRoles.Parasite => CountTypes.Impostor,
|
||||
CustomRoles.NSerialKiller => CountTypes.NSerialKiller,
|
||||
CustomRoles.Samurai => CountTypes.Samurai,
|
||||
CustomRoles.Bargainer => CountTypes.Bargainer,
|
||||
CustomRoles.Tiger => CountTypes.Tiger,
|
||||
CustomRoles.Enderman => CountTypes.Enderman,
|
||||
@@ -1308,6 +1311,7 @@ public enum CountTypes
|
||||
HexMaster,
|
||||
Wraith,
|
||||
NSerialKiller,
|
||||
Samurai,
|
||||
Bargainer,
|
||||
Tiger,
|
||||
Enderman,
|
||||
|
||||
@@ -518,6 +518,7 @@ public static class Utils
|
||||
case CustomRoles.Eclipse:
|
||||
case CustomRoles.Pyromaniac:
|
||||
case CustomRoles.NSerialKiller:
|
||||
case CustomRoles.Samurai:
|
||||
case CustomRoles.Bargainer:
|
||||
case CustomRoles.Tiger:
|
||||
case CustomRoles.SoulHunter:
|
||||
@@ -2128,6 +2129,13 @@ public static class Utils
|
||||
TargetMark.Append($"<color={GetRoleColorCode(CustomRoles.Analyst)}>○</color>");
|
||||
}
|
||||
|
||||
break;
|
||||
case CustomRoles.Samurai: // Same as Analyst
|
||||
if ((Main.PlayerStates[seer.PlayerId].Role as Samurai).Target.Id == target.PlayerId)
|
||||
{
|
||||
TargetMark.Append($"<color={GetRoleColorCode(CustomRoles.Samurai)}>○</color>");
|
||||
}
|
||||
|
||||
break;
|
||||
case CustomRoles.Puppeteer when Puppeteer.PuppeteerList.ContainsValue(seer.PlayerId) && Puppeteer.PuppeteerList.ContainsKey(target.PlayerId):
|
||||
TargetMark.Append($"<color={GetRoleColorCode(CustomRoles.Impostor)}>◆</color>");
|
||||
|
||||
@@ -966,18 +966,12 @@ internal class ChatCommands
|
||||
string[] args = text.Split(' ');
|
||||
string subArgs;
|
||||
|
||||
if (GuessManager.GuesserMsg(player, text))
|
||||
if (GuessManager.GuesserMsg(player, text) ||
|
||||
Judge.TrialMsg(player, text) ||
|
||||
NiceSwapper.SwapMsg(player, text) ||
|
||||
ParityCop.ParityCheckMsg(player, text) ||
|
||||
Councillor.MurderMsg(player, text))
|
||||
{
|
||||
if (Judge.TrialMsg(player, text) ||
|
||||
NiceSwapper.SwapMsg(player, text) ||
|
||||
ParityCop.ParityCheckMsg(player, text) ||
|
||||
Councillor.MurderMsg(player, text))
|
||||
{
|
||||
canceled = true;
|
||||
LastSentCommand[player.PlayerId] = now;
|
||||
return;
|
||||
}
|
||||
|
||||
canceled = true;
|
||||
LastSentCommand[player.PlayerId] = now;
|
||||
return;
|
||||
|
||||
@@ -227,7 +227,7 @@ class GameEndChecker
|
||||
WinnerIds.RemoveWhere(x => CustomTeamManager.GetCustomTeam(x) != null);
|
||||
}
|
||||
|
||||
if (WinnerTeam == CustomWinner.Lovers || WinnerIds.Any(x => Main.PlayerStates[x].SubRoles.Contains(CustomRoles.Lovers)))
|
||||
if ((WinnerTeam == CustomWinner.Lovers || WinnerIds.Any(x => Main.PlayerStates[x].SubRoles.Contains(CustomRoles.Lovers))) && Main.LoversPlayers.All(x => x.IsAlive()))
|
||||
{
|
||||
if (WinnerTeam != CustomWinner.Lovers) AdditionalWinnerTeams.Add(AdditionalWinners.Lovers);
|
||||
Main.AllPlayerControls
|
||||
|
||||
@@ -642,17 +642,10 @@ class CmdCheckShapeshiftPatch
|
||||
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.Shapeshift))]
|
||||
class ShapeshiftPatch
|
||||
{
|
||||
private static readonly List<byte> IgnoreSS = [];
|
||||
|
||||
public static bool ProcessShapeshift(PlayerControl shapeshifter, PlayerControl target)
|
||||
{
|
||||
if (!Main.ProcessShapeshifts) return true;
|
||||
if (shapeshifter == null || target == null) return true;
|
||||
if (IgnoreSS.Contains(shapeshifter.PlayerId))
|
||||
{
|
||||
IgnoreSS.Remove(shapeshifter.PlayerId);
|
||||
return true;
|
||||
}
|
||||
|
||||
Logger.Info($"{shapeshifter.GetNameWithRole()} => {target.GetNameWithRole()}", "Shapeshift");
|
||||
|
||||
@@ -720,7 +713,7 @@ class ShapeshiftPatch
|
||||
if (doSSwithoutAnim)
|
||||
{
|
||||
shapeshifter.RpcShapeshift(target, false);
|
||||
IgnoreSS.Add(shapeshifter.PlayerId);
|
||||
return false;
|
||||
}
|
||||
|
||||
return isSSneeded || (!shouldCancel && !forceCancel) || (!shapeshifting && !shouldAlwaysCancel);
|
||||
@@ -1414,6 +1407,13 @@ class FixedUpdatePatch
|
||||
Mark.Append($"<color={GetRoleColorCode(CustomRoles.Analyst)}>○</color>");
|
||||
}
|
||||
|
||||
break;
|
||||
case CustomRoles.Samurai:
|
||||
if ((Main.PlayerStates[seer.PlayerId].Role as Samurai).Target.Id == target.PlayerId)
|
||||
{
|
||||
Mark.Append($"<color={GetRoleColorCode(CustomRoles.Samurai)}>○</color>");
|
||||
}
|
||||
|
||||
break;
|
||||
case CustomRoles.Puppeteer:
|
||||
if (Puppeteer.PuppeteerList.ContainsValue(seer.PlayerId) && Puppeteer.PuppeteerList.ContainsKey(target.PlayerId))
|
||||
|
||||
@@ -195,23 +195,26 @@ class OnPlayerLeftPatch
|
||||
else if (GameStates.IsLobby)
|
||||
msg = GetString("Message.HostLeftGameInLobby");
|
||||
|
||||
player.SetName(title);
|
||||
player?.SetName(title);
|
||||
DestroyableSingleton<HudManager>.Instance.Chat.AddChat(player, msg);
|
||||
player.SetName(name);
|
||||
player?.SetName(name);
|
||||
|
||||
var writer = CustomRpcSender.Create("MessagesToSend");
|
||||
writer.StartMessage(clientId);
|
||||
writer.StartRpc(player.NetId, (byte)RpcCalls.SetName)
|
||||
.Write(title)
|
||||
.EndRpc();
|
||||
writer.StartRpc(player.NetId, (byte)RpcCalls.SendChat)
|
||||
.Write(msg)
|
||||
.EndRpc();
|
||||
writer.StartRpc(player.NetId, (byte)RpcCalls.SetName)
|
||||
.Write(player.Data.PlayerName)
|
||||
.EndRpc();
|
||||
writer.EndMessage();
|
||||
writer.SendMessage();
|
||||
if (player != null && player.Data != null)
|
||||
{
|
||||
var writer = CustomRpcSender.Create("MessagesToSend");
|
||||
writer.StartMessage(clientId);
|
||||
writer.StartRpc(player.NetId, (byte)RpcCalls.SetName)
|
||||
.Write(title)
|
||||
.EndRpc();
|
||||
writer.StartRpc(player.NetId, (byte)RpcCalls.SendChat)
|
||||
.Write(msg)
|
||||
.EndRpc();
|
||||
writer.StartRpc(player.NetId, (byte)RpcCalls.SetName)
|
||||
.Write(player.Data.PlayerName)
|
||||
.EndRpc();
|
||||
writer.EndMessage();
|
||||
writer.SendMessage();
|
||||
}
|
||||
}
|
||||
|
||||
// Additional description of the reason for disconnection
|
||||
@@ -243,7 +246,7 @@ class OnPlayerLeftPatch
|
||||
|
||||
Utils.CountAlivePlayers(true);
|
||||
|
||||
data.Character.Data.Disconnected = true;
|
||||
if (data != null && data.Character != null) data.Character.Data.Disconnected = true;
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
{
|
||||
@@ -252,6 +255,10 @@ class OnPlayerLeftPatch
|
||||
{
|
||||
Logger.Error(ex.ToString(), "OnPlayerLeftPatch.Postfix");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Utils.NotifyRoles(NoCache: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,12 +29,12 @@
|
||||
|
||||
## Visit our website for more information: [EHR](https://sites.google.com/view/ehr-au)
|
||||
## Main Features
|
||||
- Note: The goal with this branch is to improve the existing stuff over adding new roles. If some of the stuff you see below are in TOHRE, they were originally coded by me.
|
||||
### New gamemode
|
||||
- Note: The goal with this branch is to improve the existing stuff over adding new roles. If some of the stuff you see below are in other mods, they were originally coded by me.
|
||||
### Most Popular Game Mode
|
||||
- A brand new official gamemode, Basic FFA (Free For All)
|
||||
- This mode makes everyone a killer and the last player alive wins
|
||||
- Features: Random events, ranks and scoring, random ability gain for every kill, game timer, scoreboard (task list), unique end screen, fully customizable
|
||||
### Overall improvements
|
||||
### Overall improvements compared to other mods
|
||||
- Role spawn chances are in percentages
|
||||
- Gain more ability uses for completing tasks as crewmate roles
|
||||
- Gain more ability uses for getting kills as impostor roles
|
||||
@@ -103,91 +103,7 @@
|
||||
- Provocateur: No longer suicides after selecting a target
|
||||
- Pursuer: Target doesn't die when trying to use their kill button, they'll just have their kill cooldown reset
|
||||
|
||||
### Now, some new roles as well
|
||||
- Lighter (Crewmate)
|
||||
- Demolitionist (Crewmate)
|
||||
- Ventguard (Crewmate)
|
||||
- Express (Crewmate)
|
||||
- Witness (Crewmate)
|
||||
- Alchemist (Crewmate)
|
||||
- Task Manager (Crewmate)
|
||||
- Speedrunner (Crewmate)
|
||||
- Ignitor (Crewmate)
|
||||
- Security Guard (Crewmate)
|
||||
- Aid (Crewmate)
|
||||
- Spy (Crewmate)
|
||||
- Tether (Crewmate)
|
||||
- Ricochet (Crewmate)
|
||||
- Door Master (Crewmate)
|
||||
- Hacker (Crewmate)
|
||||
- Guess Manager (Crewmate)
|
||||
- Altruist (Crewmate)
|
||||
- Transmitter (Crewmate)
|
||||
- Autocrat (Crewmate)
|
||||
- Benefactor (Crewmate)
|
||||
- Nightmare (Crewmate)
|
||||
- Camera Man (Crewmate)
|
||||
- Escort (Crewmate)
|
||||
- Donut Delivery (Crewmate)
|
||||
- Drainer (Crewmate)
|
||||
- Insight (Crewmate)
|
||||
- Tunneler (Crewmate)
|
||||
- Detour (Crewmate)
|
||||
- Gaulois (Crewmate)
|
||||
- Analyst (Crewmate)
|
||||
- Electric (Crewmate)
|
||||
- Mole (Crewmate)
|
||||
- Tornado (Crewmate)
|
||||
- Sentinel (Crewmate)
|
||||
- Rabbit (Crewmate)
|
||||
- Perceiver (Crewmate)
|
||||
- Convener (Crewmate)
|
||||
- Mathematician (Crewmate)
|
||||
- Romantic (Neutral)
|
||||
- Werewolf (Neutral)
|
||||
- Imitator (Neutral)
|
||||
- Head Hunter (Neutral)
|
||||
- Vengeance (Neutral)
|
||||
- Eclipse (Neutral)
|
||||
- Pyromaniac (Neutral)
|
||||
- Weapon Master (Neutral)
|
||||
- Postman (Neutral)
|
||||
- Reckless (Neutral)
|
||||
- Magician (Neutral)
|
||||
- Enderman (Neutral)
|
||||
- Mycologist (Neutral)
|
||||
- Bubble (Neutral)
|
||||
- Hookshot (Neutral)
|
||||
- Sprayer (Neutral)
|
||||
- Soul Hunter (Neutral)
|
||||
- Necromancer / Deathknight (Neutral)
|
||||
- Undertaker (Impostor)
|
||||
- Gambler (Impostor)
|
||||
- Mastermind (Impostor)
|
||||
- Rift Maker (Impostor)
|
||||
- Hitman (Impostor)
|
||||
- Sapper (Impostor)
|
||||
- Nullifier (Impostor)
|
||||
- Chronomancer (Impostor)
|
||||
- Librarian (Impostor)
|
||||
- Yin Yanger (Impostor)
|
||||
- Cantankerous (Impostor)
|
||||
- Duellist (Impostor)
|
||||
- Kamikaze (Impostor)
|
||||
- Swapster (Impostor)
|
||||
- Swiftclaw (Impostor)
|
||||
- Damocles (Impostor-only Add-on)
|
||||
- Deadly Quota (Impostor-only Add-on)
|
||||
- Nimble (Add-on)
|
||||
- Physicist (Add-on)
|
||||
- Stressed (Add-on)
|
||||
- Giant (Add-on)
|
||||
- Magnet (Add-on)
|
||||
- Sleuth (Add-on)
|
||||
- Asthmatic (Add-on)
|
||||
- Disco (Add-on)
|
||||
- Truant (Add-on)
|
||||
- Busy (Add-on)
|
||||
### To see the full list of unique roles and their descriptions, visit our website: [EHR](https://sites.google.com/view/ehr-au)
|
||||
|
||||
## Note:
|
||||
- You can use parts of the code in here, but if you do, you'll have to credit me (Gurge44) or the mod by mentioning its name (EHR) and providing a link to this github page. (Or leaving the in-game credits as they are is also fine!)
|
||||
@@ -198,11 +114,11 @@
|
||||
## Credit to these mods and their developers for the code and help:
|
||||
### :star: [TOHER/TOHRE/TOHEN](https://github.com/0xDrMoe/TownofHost-Enhanced) :
|
||||
>
|
||||
> - Our repo is forked from TOHEN
|
||||
> - Our repo is forked from TOHRE (from a long time ago)
|
||||
>
|
||||
### :star: [TOHE/TONX](https://github.com/KARPED1EM/TownOfHostEdited) :
|
||||
>
|
||||
> - Our repo is a continuation of EHR
|
||||
> - Our repo is a continuation of TOHE
|
||||
> - TONX reference: Modify character limit for chat messages
|
||||
>
|
||||
### :star: [TOH](https://github.com/tukasa0001/TownOfHost) :
|
||||
@@ -263,17 +179,31 @@
|
||||
>
|
||||
|
||||
### Endless Host Roles (EHR), with Endless Possibilities, brought to you by the Endless Network.
|
||||
- Contributors:
|
||||
- Gurge44 (main)
|
||||
##### Developers:
|
||||
- Gurge44
|
||||
##### Contributors:
|
||||
- Dx
|
||||
- PH_Gaming
|
||||
##### Special Thanks:
|
||||
- Seleneous
|
||||
- thewhiskas27
|
||||
- HyperAtill
|
||||
##### Translators:
|
||||
- Dx (PT-BR)
|
||||
- PH_Gaming (PT-BR)
|
||||
- Tomix (PT-BR)
|
||||
- aviiiv (PT-BR)
|
||||
- HyperAtill (RU)
|
||||
|
||||
|
||||
# License for the Custom Team Assinger application
|
||||
# License for the Custom Team Assigner application
|
||||
|
||||
Copyright (c) 2024, Gurge44
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
@@ -288,6 +218,8 @@ modification, are permitted provided that the following conditions are met:
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
|
||||
@@ -2631,6 +2631,13 @@
|
||||
"Sentry.Notify.Info.NoData": "<#ff0000>none</color>",
|
||||
"Sentry.Notify.Shapeshifted": "{0} shapeshifted into {1} in your monitored room",
|
||||
"Sentry.Notify.Vented": "{0} vented in your monitored room",
|
||||
"Sentry.Notify.InvalidRoom": "You are not in a room",
|
||||
"Samurai": "Samurai",
|
||||
"SamuraiInfo": "Kill Players in Unique Ways",
|
||||
"SamuraiInfoLong": "(Neutrals):\\nAs the Samurai, you can do delayed kills and normal kills. What decides? Well, if you click your kill button on someone (the kill won't occur immediately) and you stay near them for a few seconds (like an arsonist douse), you get a lower kill cooldown and the kill will be delayed. If you fail to stay near them, you do a normal kill, lunge included.",
|
||||
"Samurai.NearbyDuration": "Time to Stay Near Target",
|
||||
"Samurai.SuccessKCD": "Kill Cooldown for Delayed Kills",
|
||||
"Samurai.KillDelay": "Kill Delay",
|
||||
"Bargainer": "Bargainer",
|
||||
"BargainerInfo": "Gain Money & Buy Power-Ups",
|
||||
"BargainerInfoLong": "(Neutrals):\\nAs the Bargainer, you can gain money by killing, sabotaging and surviving meetings. You can use this money to buy some items from the shop. All devices on this map represent a shop you can use by going near it. You can buy the following items:<size=80%>\\n- Energy Drink (lowers your kill cooldown for that round)\\n- Lens Of Truth (reveals a random player's role for some time)\\n- Band Aid (gives you a shield for some time)</size>\\nWhen you step away from a shop, the selected item will be purchased if you have enough money for it. You can choose to not buy anything. While in the shop, sabotage to cycle between the available items.",
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace EHR.Roles.Crewmate
|
||||
return;
|
||||
}
|
||||
|
||||
if (CurrentTarget.TIME + Duration.GetInt() < Utils.TimeStamp)
|
||||
if (CurrentTarget.TIME + Duration.GetInt() <= Utils.TimeStamp)
|
||||
{
|
||||
CurrentTarget.ID = byte.MaxValue;
|
||||
pc.RpcRemoveAbilityUse();
|
||||
|
||||
+39
-17
@@ -61,7 +61,12 @@ namespace EHR.Roles.Impostor
|
||||
public override void OnPet(PlayerControl pc)
|
||||
{
|
||||
var room = pc.GetPlainShipRoom();
|
||||
if (room == null) return;
|
||||
if (room == default(PlainShipRoom))
|
||||
{
|
||||
pc.AddAbilityCD(1);
|
||||
pc.Notify(Translator.GetString("Sentry.Notify.InvalidRoom"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (MonitoredRoom == null || MonitoredRoom == default || MonitoredRoom == default(PlainShipRoom)) MonitoredRoom = room;
|
||||
else DisplayRoomInfo(pc);
|
||||
@@ -74,7 +79,7 @@ namespace EHR.Roles.Impostor
|
||||
if (pc.GetAbilityUseLimit() < 1) return;
|
||||
pc.RpcRemoveAbilityUse();
|
||||
|
||||
var players = Main.AllAlivePlayerControls.Where(IsInMonitoredRoom).Select(x => Utils.ColorString(Main.PlayerColors[x.PlayerId], x.GetRealName())).Join();
|
||||
var players = Main.AllAlivePlayerControls.Where(IsInMonitoredRoom).Select(x => Utils.GetPlayerById(x.shapeshiftTargetPlayerId) ?? x).Select(x => Utils.ColorString(Main.PlayerColors[x.PlayerId], x.GetRealName())).Join();
|
||||
var bodies = GetColoredNames(DeadBodiesInRoom);
|
||||
|
||||
var noDataString = Translator.GetString("Sentry.Notify.Info.NoData");
|
||||
@@ -91,14 +96,24 @@ namespace EHR.Roles.Impostor
|
||||
|
||||
public void OnAnyoneShapeshiftLoop(PlayerControl shapeshifter, PlayerControl target)
|
||||
{
|
||||
if (IsInMonitoredRoom(shapeshifter))
|
||||
if (IsInMonitoredRoom(shapeshifter) && NameNotifyManager.Notice.TryGetValue(SentryPC.PlayerId, out var notify))
|
||||
{
|
||||
SentryPC.Notify(
|
||||
string.Format(
|
||||
Translator.GetString("Sentry.Notify.Shapeshifted"),
|
||||
Utils.ColorString(Main.PlayerColors[shapeshifter.PlayerId], shapeshifter.GetRealName()),
|
||||
Utils.ColorString(Main.PlayerColors[target.PlayerId], target.GetRealName())),
|
||||
ShowInfoDuration.GetFloat());
|
||||
var ssTarget = Utils.GetPlayerById(shapeshifter.shapeshiftTargetPlayerId);
|
||||
var text = "\n" + string.Format(
|
||||
Translator.GetString("Sentry.Notify.Shapeshifted"),
|
||||
ssTarget == null
|
||||
? Utils.ColorString(Main.PlayerColors[shapeshifter.PlayerId], shapeshifter.GetRealName())
|
||||
: Utils.ColorString(Main.PlayerColors[ssTarget.PlayerId], ssTarget.GetRealName()),
|
||||
Utils.ColorString(Main.PlayerColors[target.PlayerId], target.GetRealName()));
|
||||
|
||||
notify.TEXT += text;
|
||||
Utils.NotifyRoles(SpecifySeer: SentryPC, SpecifyTarget: SentryPC);
|
||||
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
if (NameNotifyManager.Notice.TryGetValue(SentryPC.PlayerId, out var laterNotify))
|
||||
laterNotify.TEXT = laterNotify.TEXT.Replace(text, string.Empty);
|
||||
}, 3f, log: false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,23 +132,30 @@ namespace EHR.Roles.Impostor
|
||||
{
|
||||
foreach (var state in Main.PlayerStates.Values)
|
||||
{
|
||||
if (state.Role is Sentry st && st.IsInMonitoredRoom(pc))
|
||||
if (state.Role is Sentry st && st.IsInMonitoredRoom(pc) && NameNotifyManager.Notice.TryGetValue(st.SentryPC.PlayerId, out var notify))
|
||||
{
|
||||
st.SentryPC.Notify(
|
||||
string.Format(
|
||||
Translator.GetString("Sentry.Notify.Vented"),
|
||||
Utils.ColorString(Main.PlayerColors[pc.PlayerId], pc.GetRealName())),
|
||||
ShowInfoDuration.GetFloat());
|
||||
var text = "\n" + string.Format(
|
||||
Translator.GetString("Sentry.Notify.Vented"),
|
||||
Utils.ColorString(Main.PlayerColors[pc.PlayerId], pc.GetRealName()));
|
||||
|
||||
notify.TEXT += text;
|
||||
Utils.NotifyRoles(SpecifySeer: st.SentryPC, SpecifyTarget: st.SentryPC);
|
||||
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
if (NameNotifyManager.Notice.TryGetValue(st.SentryPC.PlayerId, out var laterNotify))
|
||||
laterNotify.TEXT = laterNotify.TEXT.Replace(text, string.Empty);
|
||||
}, 3f, log: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetSuffix(PlayerControl seer)
|
||||
{
|
||||
if (!PlayersKnowAboutCamera.GetBool()) return string.Empty;
|
||||
|
||||
if (Main.PlayerStates[seer.PlayerId].Role is Sentry s && s.MonitoredRoom != null) return string.Format(Translator.GetString("Sentry.Suffix.Self"), Translator.GetString($"{s.MonitoredRoom.RoomId}"));
|
||||
|
||||
if (!PlayersKnowAboutCamera.GetBool()) return string.Empty;
|
||||
|
||||
foreach (var state in Main.PlayerStates.Values)
|
||||
{
|
||||
if (state.Role is Sentry st && st.IsInMonitoredRoom(seer))
|
||||
|
||||
@@ -357,6 +357,8 @@ namespace EHR.Roles.Neutral
|
||||
}
|
||||
|
||||
foreach (var index in indexesToRemove) ActiveItems.RemoveAt(index);
|
||||
|
||||
Utils.GetPlayerById(BargainerId).ResetKillCooldown();
|
||||
}
|
||||
|
||||
public static bool KnowRole(PlayerControl seer, PlayerControl target)
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
using System.Collections.Generic;
|
||||
using AmongUs.GameOptions;
|
||||
using UnityEngine;
|
||||
using static EHR.Options;
|
||||
|
||||
namespace EHR.Roles.Neutral
|
||||
{
|
||||
internal class Samurai : RoleBase
|
||||
{
|
||||
public static bool On;
|
||||
|
||||
private static OptionItem KillCooldown;
|
||||
private static OptionItem CanVent;
|
||||
private static OptionItem HasImpostorVision;
|
||||
private static OptionItem NearbyDuration;
|
||||
private static OptionItem SuccessKCD;
|
||||
private static OptionItem KillDelay;
|
||||
|
||||
public (byte Id, long TimeStamp) Target;
|
||||
private Dictionary<byte, long> Delays;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
const int id = 16880;
|
||||
SetupRoleOptions(id, TabGroup.NeutralRoles, CustomRoles.Samurai);
|
||||
KillCooldown = FloatOptionItem.Create(id + 2, "KillCooldown", new(0f, 180f, 2.5f), 22.5f, TabGroup.NeutralRoles)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Samurai])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
CanVent = BooleanOptionItem.Create(id + 3, "CanVent", true, TabGroup.NeutralRoles)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Samurai]);
|
||||
HasImpostorVision = BooleanOptionItem.Create(id + 4, "ImpostorVision", true, TabGroup.NeutralRoles)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Samurai]);
|
||||
NearbyDuration = FloatOptionItem.Create(id + 5, "Samurai.NearbyDuration", new(0f, 30f, 0.5f), 3f, TabGroup.NeutralRoles)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Samurai])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
SuccessKCD = FloatOptionItem.Create(id + 6, "Samurai.SuccessKCD", new(0f, 180f, 0.5f), 17.5f, TabGroup.NeutralRoles)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Samurai])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
KillDelay = FloatOptionItem.Create(id + 7, "Samurai.KillDelay", new(0f, 60f, 0.5f), 5f, TabGroup.NeutralRoles)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Samurai])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
}
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
On = false;
|
||||
}
|
||||
|
||||
public override void Add(byte playerId)
|
||||
{
|
||||
On = true;
|
||||
Target = (byte.MaxValue, 0);
|
||||
Delays = [];
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
public override bool IsEnable => On;
|
||||
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 CanUseKillButton(PlayerControl pc) => Target.Id == byte.MaxValue && pc.IsAlive();
|
||||
|
||||
public override bool OnCheckMurder(PlayerControl killer, PlayerControl target)
|
||||
{
|
||||
if (Target.Id != byte.MaxValue) return false;
|
||||
|
||||
Target = (target.PlayerId, Utils.TimeStamp);
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void OnFixedUpdate(PlayerControl pc)
|
||||
{
|
||||
if (!GameStates.IsInTask) return;
|
||||
|
||||
long now = Utils.TimeStamp;
|
||||
|
||||
foreach (var kvp in Delays)
|
||||
{
|
||||
var player = Utils.GetPlayerById(kvp.Key);
|
||||
if (player == null || !player.IsAlive()) continue;
|
||||
|
||||
if (kvp.Value + KillDelay.GetInt() <= now)
|
||||
{
|
||||
if (pc.RpcCheckAndMurder(player, check: true))
|
||||
player.Suicide(realKiller: pc);
|
||||
}
|
||||
}
|
||||
|
||||
if (Target.Id == byte.MaxValue || !pc.IsAlive()) return;
|
||||
|
||||
var target = Utils.GetPlayerById(Target.Id);
|
||||
if (target == null) return;
|
||||
|
||||
if (Vector2.Distance(target.Pos(), pc.Pos()) > (NormalGameOptionsV07.KillDistances[Mathf.Clamp(pc.Is(CustomRoles.Reach) ? 2 : Main.NormalOptions.KillDistance, 0, 2)] + 0.5f))
|
||||
{
|
||||
Target = (byte.MaxValue, 0);
|
||||
pc.RpcCheckAndMurder(target);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Target.TimeStamp + NearbyDuration.GetInt() <= now)
|
||||
{
|
||||
Delays[Target.Id] = now;
|
||||
Target = (byte.MaxValue, 0);
|
||||
pc.SetKillCooldown(SuccessKCD.GetFloat());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,8 +35,8 @@ public class Main : BasePlugin
|
||||
public const string DebugKeySalt = "59687b";
|
||||
public static ConfigEntry<string> DebugKeyInput { get; private set; }
|
||||
public const string PluginGuid = "com.gurge44.endlesshostroles";
|
||||
public const string PluginVersion = "3.2.1";
|
||||
public const string PluginDisplayVersion = "3.2.1";
|
||||
public const string PluginVersion = "3.2.2";
|
||||
public const string PluginDisplayVersion = "3.2.2";
|
||||
public static readonly string SupportedAUVersion = "2024.3.5";
|
||||
|
||||
public Harmony Harmony { get; } = new(PluginGuid);
|
||||
@@ -424,6 +424,7 @@ public class Main : BasePlugin
|
||||
{ CustomRoles.HexMaster, "#ff00ff" },
|
||||
{ CustomRoles.Wraith, "#4B0082" },
|
||||
{ CustomRoles.NSerialKiller, "#233fcc" },
|
||||
{ CustomRoles.Samurai, "#73495c" },
|
||||
{ CustomRoles.Bargainer, "#4f2f36" },
|
||||
{ CustomRoles.Tiger, "#fcba03" },
|
||||
{ CustomRoles.SoulHunter, "#3f2c61" },
|
||||
@@ -682,6 +683,7 @@ public enum CustomWinner
|
||||
Necromancer = CustomRoles.Necromancer,
|
||||
Wraith = CustomRoles.Wraith,
|
||||
SerialKiller = CustomRoles.NSerialKiller,
|
||||
Samurai = CustomRoles.Samurai,
|
||||
Bargainer = CustomRoles.Bargainer,
|
||||
Tiger = CustomRoles.Tiger,
|
||||
Enderman = CustomRoles.Enderman,
|
||||
|
||||
Reference in new issue
Block a user