diff --git a/Modules/ExtendedPlayerControl.cs b/Modules/ExtendedPlayerControl.cs
index c4de7424c..8e5c7ae33 100644
--- a/Modules/ExtendedPlayerControl.cs
+++ b/Modules/ExtendedPlayerControl.cs
@@ -238,6 +238,35 @@ public static void RpcResetAbilityCooldown(this PlayerControl target)
ホストのクールダウンは直接リセットします。
*/
}
+ public static void RpcSpecificShapeshift(this PlayerControl player, PlayerControl target, bool shouldAnimate)
+ {
+ if (!AmongUsClient.Instance.AmHost) return;
+ if (player.PlayerId == 0)
+ {
+ player.Shapeshift(target, shouldAnimate);
+ return;
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpcImmediately(player.NetId, (byte)RpcCalls.Shapeshift, SendOption.Reliable, player.GetClientId());
+ messageWriter.WriteNetObject(target);
+ messageWriter.Write(shouldAnimate);
+ AmongUsClient.Instance.FinishRpcImmediately(messageWriter);
+ }
+ public static void RpcSpecificRejectShapeshift(this PlayerControl player, PlayerControl target, bool shouldAnimate)
+ {
+ if (!AmongUsClient.Instance.AmHost) return;
+ foreach (var seer in Main.AllPlayerControls)
+ {
+ if (seer != player)
+ {
+ MessageWriter msg = AmongUsClient.Instance.StartRpcImmediately(player.NetId, (byte)RpcCalls.RejectShapeshift, SendOption.Reliable, seer.GetClientId());
+ AmongUsClient.Instance.FinishRpcImmediately(msg);
+ }
+ else
+ {
+ player.RpcSpecificShapeshift(target, shouldAnimate);
+ }
+ }
+ }
public static void RpcDesyncUpdateSystem(this PlayerControl target, SystemTypes systemType, int amount)
{
MessageWriter messageWriter = AmongUsClient.Instance.StartRpcImmediately(ShipStatus.Instance.NetId, (byte)RpcCalls.UpdateSystem, SendOption.Reliable, target.GetClientId());
@@ -570,9 +599,18 @@ public static PlainShipRoom GetPlainShipRoom(this PlayerControl pc)
}
return null;
}
- public static void RpcSnapTo(this PlayerControl pc, Vector2 position)
+ public static void RpcSnapToForced(this PlayerControl pc, Vector2 position)
{
- pc.NetTransform.RpcSnapTo(position);
+ var netTransform = pc.NetTransform;
+ if (AmongUsClient.Instance.AmClient)
+ {
+ netTransform.SnapTo(position, (ushort)(netTransform.lastSequenceId + 128));
+ }
+ ushort newSid = (ushort)(netTransform.lastSequenceId + 2);
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpcImmediately(netTransform.NetId, (byte)RpcCalls.SnapTo, SendOption.Reliable);
+ NetHelpers.WriteVector2(position, messageWriter);
+ messageWriter.Write(newSid);
+ AmongUsClient.Instance.FinishRpcImmediately(messageWriter);
}
public static void RpcSnapToDesync(this PlayerControl pc, PlayerControl target, Vector2 position)
{
diff --git a/Modules/GameState.cs b/Modules/GameState.cs
index 15497a438..c80f35def 100644
--- a/Modules/GameState.cs
+++ b/Modules/GameState.cs
@@ -31,6 +31,8 @@ public bool CanUseMovingPlatform
}
public (DateTime, byte) RealKiller;
public PlainShipRoom LastRoom;
+ /// 会議等の後に湧いた後かどうか
+ public bool HasSpawned { get; set; } = false;
public Dictionary TargetColorData;
public PlayerState(byte playerId)
{
diff --git a/Modules/OptionSerializer.cs b/Modules/OptionSerializer.cs
index ba34b662e..719418f92 100644
--- a/Modules/OptionSerializer.cs
+++ b/Modules/OptionSerializer.cs
@@ -82,7 +82,8 @@ public static string GenerateModOptionsString()
/// 生成された文字列
public static string GenerateVanillaOptionsString()
{
- byte[] bytes = GameOptionsManager.Instance.gameOptionsFactory.ToBytes(GameOptionsManager.Instance.CurrentGameOptions);
+ // 保存時はエイプリルフール無効
+ byte[] bytes = GameOptionsManager.Instance.gameOptionsFactory.ToBytes(GameOptionsManager.Instance.CurrentGameOptions, false);
return Convert.ToBase64String(bytes);
}
///
diff --git a/Modules/RPC.cs b/Modules/RPC.cs
index b66f1d4c4..d2208c4f8 100644
--- a/Modules/RPC.cs
+++ b/Modules/RPC.cs
@@ -19,24 +19,10 @@ public enum CustomRPC
EndGame,
PlaySound,
SetCustomRole,
- SetBountyTarget,
- WitchSync,
- SetSheriffShotLimit,
- SetDousedPlayer,
SetNameColorData,
- SniperSync,
SetLoversPlayers,
- SetExecutionerTarget,
- SetCurrentDousingTarget,
- SetEvilTrackerTarget,
SetRealKiller,
- SyncPuppet,
- SetSchrodingerCatTeam,
- StealthDarken,
- EvilHackerCreateMurderNotify,
- PenguinSync,
- MareSync,
- SyncPlagueDoctor,
+ CustomRoleSync,
}
public enum Sounds
{
@@ -153,8 +139,8 @@ public static void Postfix(PlayerControl __instance, [HarmonyArgument(0)] byte c
byte killerId = reader.ReadByte();
RPC.SetRealKiller(targetId, killerId);
break;
- default:
- CustomRoleManager.DispatchRpc(reader, rpcType);
+ case CustomRPC.CustomRoleSync:
+ CustomRoleManager.DispatchRpc(reader);
break;
}
}
diff --git a/Modules/SystemEnvironment.cs b/Modules/SystemEnvironment.cs
new file mode 100644
index 000000000..8ad623fa2
--- /dev/null
+++ b/Modules/SystemEnvironment.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace TownOfHost.Modules;
+
+public static class SystemEnvironment
+{
+ public static void SetEnvironmentVariables()
+ {
+ // ユーザ環境変数に最近開かれたTOHアモアスフォルダのパスを設定
+ Environment.SetEnvironmentVariable("TOWN_OF_HOST_DIR_ROOT", Environment.CurrentDirectory, EnvironmentVariableTarget.User);
+ }
+}
diff --git a/Patches/AirshipStatus.cs b/Patches/AirshipStatus.cs
index fa7744024..d2214a754 100644
--- a/Patches/AirshipStatus.cs
+++ b/Patches/AirshipStatus.cs
@@ -12,7 +12,6 @@ public static bool Prefix()
{
if (PlayerControl.LocalPlayer.Is(CustomRoles.GM))
{
- RandomSpawn.hostReady = true;
RandomSpawn.AirshipSpawn(PlayerControl.LocalPlayer);
// GMは湧き画面をスキップ
return false;
diff --git a/Patches/ExilePatch.cs b/Patches/ExilePatch.cs
index 73c92c5df..38e29e423 100644
--- a/Patches/ExilePatch.cs
+++ b/Patches/ExilePatch.cs
@@ -47,6 +47,16 @@ static void WrapUpPostfix(GameData.PlayerInfo exiled)
exiled = AntiBlackout_LastExiled;
}
+ var mapId = Main.NormalOptions.MapId;
+ // エアシップではまだ湧かない
+ if ((MapNames)mapId != MapNames.Airship)
+ {
+ foreach (var state in PlayerState.AllPlayerStates.Values)
+ {
+ state.HasSpawned = true;
+ }
+ }
+
bool DecidedWinner = false;
if (!AmongUsClient.Instance.AmHost) return; //ホスト以外はこれ以降の処理を実行しません
AntiBlackout.RestoreIsDead(doSend: false);
@@ -76,7 +86,7 @@ static void WrapUpPostfix(GameData.PlayerInfo exiled)
if (RandomSpawn.IsRandomSpawn())
{
RandomSpawn.SpawnMap map;
- switch (Main.NormalOptions.MapId)
+ switch (mapId)
{
case 0:
map = new RandomSpawn.SkeldSpawnMap();
diff --git a/Patches/GameStartManagerPatch.cs b/Patches/GameStartManagerPatch.cs
index ba45f0521..5a83ca876 100644
--- a/Patches/GameStartManagerPatch.cs
+++ b/Patches/GameStartManagerPatch.cs
@@ -211,7 +211,7 @@ public static bool Prefix(GameStartManager __instance)
Main.LastShapeshifterCooldown.Value = AURoleOptions.ShapeshifterCooldown;
AURoleOptions.ShapeshifterCooldown = 0f;
- PlayerControl.LocalPlayer.RpcSyncSettings(GameOptionsManager.Instance.gameOptionsFactory.ToBytes(opt));
+ PlayerControl.LocalPlayer.RpcSyncSettings(GameOptionsManager.Instance.gameOptionsFactory.ToBytes(opt, AprilFoolsMode.IsAprilFoolsModeToggledOn));
__instance.ReallyBegin(false);
return false;
@@ -250,7 +250,7 @@ public static void Prefix()
if (GameStates.IsCountDown)
{
Main.NormalOptions.KillCooldown = Options.DefaultKillCooldown;
- PlayerControl.LocalPlayer.RpcSyncSettings(GameOptionsManager.Instance.gameOptionsFactory.ToBytes(GameOptionsManager.Instance.CurrentGameOptions));
+ PlayerControl.LocalPlayer.RpcSyncSettings(GameOptionsManager.Instance.gameOptionsFactory.ToBytes(GameOptionsManager.Instance.CurrentGameOptions, AprilFoolsMode.IsAprilFoolsModeToggledOn));
}
}
}
diff --git a/Patches/IntroPatch.cs b/Patches/IntroPatch.cs
index 9dc85318a..84ef4812a 100644
--- a/Patches/IntroPatch.cs
+++ b/Patches/IntroPatch.cs
@@ -223,10 +223,22 @@ class IntroCutsceneDestroyPatch
public static void Postfix(IntroCutscene __instance)
{
if (!GameStates.IsInGame) return;
+
Main.introDestroyed = true;
+
+ var mapId = Main.NormalOptions.MapId;
+ // エアシップではまだ湧かない
+ if ((MapNames)mapId != MapNames.Airship)
+ {
+ foreach (var state in PlayerState.AllPlayerStates.Values)
+ {
+ state.HasSpawned = true;
+ }
+ }
+
if (AmongUsClient.Instance.AmHost)
{
- if (Main.NormalOptions.MapId != 4)
+ if (mapId != 4)
{
Main.AllPlayerControls.Do(pc => pc.RpcResetAbilityCooldown());
if (Options.FixFirstKillCooldown.GetBool())
@@ -244,7 +256,7 @@ public static void Postfix(IntroCutscene __instance)
if (RandomSpawn.IsRandomSpawn())
{
RandomSpawn.SpawnMap map;
- switch (Main.NormalOptions.MapId)
+ switch (mapId)
{
case 0:
map = new RandomSpawn.SkeldSpawnMap();
diff --git a/Patches/MeetingHudPatch.cs b/Patches/MeetingHudPatch.cs
index f80e27b75..be3866786 100644
--- a/Patches/MeetingHudPatch.cs
+++ b/Patches/MeetingHudPatch.cs
@@ -195,8 +195,6 @@ public static void Postfix()
if (AmongUsClient.Instance.AmHost)
{
AntiBlackout.SetIsDead();
- Main.AllPlayerControls.Do(pc => RandomSpawn.FirstTP[pc.PlayerId] = true);
- RandomSpawn.FastSpawnPosition.Clear();
}
// MeetingVoteManagerを通さずに会議が終了した場合の後処理
MeetingVoteManager.Instance?.Destroy();
diff --git a/Patches/PlayerContorolPatch.cs b/Patches/PlayerContorolPatch.cs
index 819f7ec85..56c61b44d 100644
--- a/Patches/PlayerContorolPatch.cs
+++ b/Patches/PlayerContorolPatch.cs
@@ -190,6 +190,80 @@ public static void Postfix(PlayerControl __instance, [HarmonyArgument(0)] Player
CustomRoleManager.OnMurderPlayer(__instance, target);
}
}
+ [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.CheckShapeshift))]
+ public static class PlayerControlCheckShapeshiftPatch
+ {
+ private static readonly LogHandler logger = Logger.Handler(nameof(PlayerControl.CheckShapeshift));
+
+ public static bool Prefix(PlayerControl __instance, [HarmonyArgument(0)] PlayerControl target, [HarmonyArgument(1)] bool shouldAnimate)
+ {
+ if (AmongUsClient.Instance.IsGameOver || !AmongUsClient.Instance.AmHost)
+ {
+ return false;
+ }
+
+ // 無効な変身を弾く.これより前に役職等の処理をしてはいけない
+ if (!CheckInvalidShapeshifting(__instance, target, shouldAnimate))
+ {
+ __instance.RpcRejectShapeshift();
+ return false;
+ }
+ // 役職の処理
+ var role = __instance.GetRoleClass();
+ if (role?.OnCheckShapeshift(target, ref shouldAnimate) == false)
+ {
+ if (role.CanDesyncShapeshift)
+ {
+ __instance.RpcSpecificRejectShapeshift(target, shouldAnimate);
+ }
+ else
+ {
+ __instance.RpcRejectShapeshift();
+ }
+ return false;
+ }
+
+ __instance.RpcShapeshift(target, shouldAnimate);
+ return false;
+ }
+ private static bool CheckInvalidShapeshifting(PlayerControl instance, PlayerControl target, bool animate)
+ {
+ logger.Info($"Checking shapeshift {instance.GetNameWithRole()} -> {(target == null || target.Data == null ? "(null)" : target.GetNameWithRole())}");
+
+ if (!target || target.Data == null)
+ {
+ logger.Info("targetがnullのため変身をキャンセルします");
+ return false;
+ }
+ if (!instance.IsAlive())
+ {
+ logger.Info("変身者が死亡しているため変身をキャンセルします");
+ return false;
+ }
+ // RoleInfoによるdesyncシェイプシフター用の判定を追加
+ if (instance.Data.Role.Role != RoleTypes.Shapeshifter && instance.GetCustomRole().GetRoleInfo()?.BaseRoleType?.Invoke() != RoleTypes.Shapeshifter)
+ {
+ logger.Info("変身者がシェイプシフターではないため変身をキャンセルします");
+ return false;
+ }
+ if (instance.Data.Disconnected)
+ {
+ logger.Info("変身者が切断済のため変身をキャンセルします");
+ return false;
+ }
+ if (target.IsMushroomMixupActive() && animate)
+ {
+ logger.Info("キノコカオス中のため変身をキャンセルします");
+ return false;
+ }
+ if (MeetingHud.Instance && animate)
+ {
+ logger.Info("会議中のため変身をキャンセルします");
+ return false;
+ }
+ return true;
+ }
+ }
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.Shapeshift))]
class ShapeshiftPatch
{
diff --git a/Patches/RandomSpawnPatch.cs b/Patches/RandomSpawnPatch.cs
index d957d982e..6fa43caa3 100644
--- a/Patches/RandomSpawnPatch.cs
+++ b/Patches/RandomSpawnPatch.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using HarmonyLib;
+using Hazel;
using UnityEngine;
using TownOfHost.Roles.Core;
@@ -68,95 +69,130 @@ public enum SpawnPoint
}
class RandomSpawn
{
- public static Dictionary FirstTP = new();
- public static Dictionary FastSpawnPosition = new();
- public static bool hostReady;
- [HarmonyPatch(typeof(CustomNetworkTransform), nameof(CustomNetworkTransform.RpcSnapTo))]
- public class RpcSnapToPatch
+ [HarmonyPatch(typeof(CustomNetworkTransform), nameof(CustomNetworkTransform.HandleRpc))]
+ public class CustomNetworkTransformHandleRpcPatch
{
- public static void Postfix(CustomNetworkTransform __instance, Vector2 position)
+ public static bool Prefix(CustomNetworkTransform __instance, [HarmonyArgument(0)] byte callId, [HarmonyArgument(1)] MessageReader reader)
{
- var player = __instance.myPlayer;
- //Logger.Info($"RpcSnapToPost:{player.name} pos:{position}", "RandomSpawn");
- if (!AmongUsClient.Instance.AmHost) return;
- if (Main.NormalOptions.MapId != 4) return;//AirShip以外無効
- if (FirstTP.TryGetValue(player.PlayerId, out var first) && first)
+ if (!__instance.isActiveAndEnabled)
+ {
+ return false;
+ }
+ if ((RpcCalls)callId == RpcCalls.SnapTo && (MapNames)Main.NormalOptions.MapId == MapNames.Airship)
{
- hostReady = true;
- //ホスト用処理
- //他視点へRPCを最初に送るのはスポーン位置選択後のため
- //クライアントへRPCを発行するときにはすでにクライアントの初期配置は終わっている。
- AirshipSpawn(player);
+ var player = __instance.myPlayer;
+ // プレイヤーがまだ湧いていない
+ if (!PlayerState.GetByPlayerId(player.PlayerId).HasSpawned)
+ {
+ // SnapTo先の座標を読み取る
+ Vector2 position;
+ {
+ var newReader = MessageReader.Get(reader);
+ position = NetHelpers.ReadVector2(newReader);
+ newReader.Recycle();
+ }
+ Logger.Info($"SnapTo: {player.GetRealName()}, ({position.x}, {position.y})", "RandomSpawn");
+ // SnapTo先が湧き位置だったら湧き処理に進む
+ if (IsAirshipVanillaSpawnPosition(position))
+ {
+ AirshipSpawn(player);
+ return false;
+ }
+ else
+ {
+ Logger.Info("ポジションは湧き位置ではありません", "RandomSpawn");
+ }
+ }
}
+ return true;
}
- }
- [HarmonyPatch(typeof(CustomNetworkTransform), nameof(CustomNetworkTransform.HandleRpc))]
- public class HandleRpcPatch
- {
- public static void Postfix(CustomNetworkTransform __instance)
- {
- var player = __instance.myPlayer;
- //Logger.Info($"HandleRpcPost:{player.name}", "RandomSpawn");
-
- if (!AmongUsClient.Instance.AmHost) return;
- if (Main.NormalOptions.MapId != 4) return;//AirShip以外無効
- if (FirstTP.TryGetValue(player.PlayerId, out var first) && first)
+ private static bool IsAirshipVanillaSpawnPosition(Vector2 position)
+ {
+ // 湧き位置の座標が0.1刻みであることを利用し,float型の誤差やReadVector2の実装による誤差の拡大の対策として座標を10倍したint型で比較する
+ var decupleXFloat = position.x * 10f;
+ var decupleYFloat = position.y * 10f;
+ var decupleXInt = Mathf.RoundToInt(decupleXFloat);
+ // 10倍した値の差が0.1近く以上あったら,元の座標が0.1刻みではないので湧き位置ではない
+ if (Mathf.Abs(((float)decupleXInt) - decupleXFloat) >= 0.09f)
+ {
+ return false;
+ }
+ var decupleYInt = Mathf.RoundToInt(decupleYFloat);
+ if (Mathf.Abs(((float)decupleYInt) - decupleYFloat) >= 0.09f)
{
- //クライアント用処理
- //他視点へRPCを最初に送るのはスポーン位置選択後のため
- //ランダムスポーン発生
- AirshipSpawn(player);
+ return false;
}
+ var decuplePosition = (decupleXInt, decupleYInt);
+ return decupleVanillaSpawnPositions.Contains(decuplePosition);
}
- }
- [HarmonyPatch(typeof(CustomNetworkTransform), nameof(CustomNetworkTransform.SnapTo), typeof(Vector2), typeof(ushort))]
- public class SnapToPatch
- {
- public static void Postfix(CustomNetworkTransform __instance, Vector2 position, ushort minSid)
+ /// 比較用 エアシップのバニラ湧き位置の10倍
+ private static readonly HashSet<(int x, int y)> decupleVanillaSpawnPositions = new()
{
- var player = __instance.myPlayer;
- //Logger.Info($"SnapTo:{player.name} pos:{position} minSid={minSid}", "RandomSpawn");
- }
+ (-7, 85), // 宿舎前通路
+ (-7, -10), // エンジン
+ (-70, -115), // キッチン
+ (335, -15), // 貨物
+ (200, 105), // アーカイブ
+ (155, 0), // メインホール
+ };
}
- [HarmonyPatch(typeof(SpawnInMinigame), nameof(SpawnInMinigame.Begin))]
- public class SpawnInMinigamePatch
+ [HarmonyPatch(typeof(SpawnInMinigame), nameof(SpawnInMinigame.SpawnAt))]
+ public static class SpawnInMinigameSpawnAtPatch
{
- public static void Postfix()
+ public static bool Prefix(SpawnInMinigame __instance, [HarmonyArgument(0)] SpawnInMinigame.SpawnLocation spawnPoint)
{
- Logger.Info($"BeginPost", "SpawnInMinigame");
- if (!AmongUsClient.Instance.AmHost) return;
- hostReady = true;
+ if (!AmongUsClient.Instance.AmHost)
+ {
+ return true;
+ }
+
+ if (__instance.amClosing != Minigame.CloseState.None)
+ {
+ return false;
+ }
+ // ランダムスポーンが有効ならバニラの湧きをキャンセル
+ if (IsRandomSpawn())
+ {
+ // バニラ処理のRpcSnapToをAirshipSpawnに置き換えたもの
+ __instance.gotButton = true;
+ PlayerControl.LocalPlayer.SetKinematic(true);
+ PlayerControl.LocalPlayer.NetTransform.SetPaused(true);
+ AirshipSpawn(PlayerControl.LocalPlayer);
+ DestroyableSingleton.Instance.PlayerCam.SnapToTarget();
+ __instance.StopAllCoroutines();
+ __instance.StartCoroutine(__instance.CoSpawnAt(PlayerControl.LocalPlayer, spawnPoint));
+ return false;
+ }
+ else
+ {
+ AirshipSpawn(PlayerControl.LocalPlayer);
+ return true;
+ }
}
}
public static void AirshipSpawn(PlayerControl player)
{
- FirstTP[player.PlayerId] = false;
- if (player.Is(CustomRoles.Penguin))
- {
- var penguin = player.GetRoleClass() as Penguin;
- penguin?.OnSpawnAirship();
- }
- player.RpcResetAbilityCooldown();
- if (Options.FixFirstKillCooldown.GetBool() && !MeetingStates.MeetingCalled) player.SetKillCooldown(Main.AllPlayerKillCooldown[player.PlayerId]);
- if (IsRandomSpawn())
- {
- new AirshipSpawnMap().RandomTeleport(player);
- }
- else if (player.Is(CustomRoles.GM))
+ Logger.Info($"Spawn: {player.GetRealName()}", "RandomSpawn");
+ if (AmongUsClient.Instance.AmHost)
{
- new AirshipSpawnMap().FirstTeleport(player);
- }
- foreach (var (sp, pos) in FastSpawnPosition)
- {
- //早湧きした人を船外から初期位置に戻す
- sp.RpcSnapToDesync(player, pos);
- }
- if (!hostReady)
- {
- //ホストのSpawnMiniGame開始までに湧いたプレイヤーを記録
- FastSpawnPosition[player] = player.transform.position;
+ if (player.Is(CustomRoles.Penguin))
+ {
+ var penguin = player.GetRoleClass() as Penguin;
+ penguin?.OnSpawnAirship();
+ }
+ player.RpcResetAbilityCooldown();
+ if (Options.FixFirstKillCooldown.GetBool() && !MeetingStates.MeetingCalled) player.SetKillCooldown(Main.AllPlayerKillCooldown[player.PlayerId]);
+ if (IsRandomSpawn())
+ {
+ new AirshipSpawnMap().RandomTeleport(player);
+ }
+ else if (player.Is(CustomRoles.GM))
+ {
+ new AirshipSpawnMap().FirstTeleport(player);
+ }
}
+ PlayerState.GetByPlayerId(player.PlayerId).HasSpawned = true;
}
public static bool IsRandomSpawn()
{
@@ -290,7 +326,7 @@ private void Teleport(PlayerControl player, bool isRadndom)
{
var location = GetLocation(!isRadndom);
Logger.Info($"{player.Data.PlayerName}:{location}", "RandomSpawn");
- player.RpcSnapTo(location);
+ player.RpcSnapToForced(location);
}
public Vector2 GetLocation(Boolean first = false)
diff --git a/Patches/ShipStatusPatch.cs b/Patches/ShipStatusPatch.cs
index 4367b9b59..91893dc22 100644
--- a/Patches/ShipStatusPatch.cs
+++ b/Patches/ShipStatusPatch.cs
@@ -93,6 +93,14 @@ public static void Prefix(ShipStatus __instance, PlayerControl reporter, GameDat
MeetingStates.ReportTarget = target;
MeetingStates.DeadBodies = UnityEngine.Object.FindObjectsOfType();
}
+ public static void Postfix()
+ {
+ // 全プレイヤーを湧いてない状態にする
+ foreach (var state in PlayerState.AllPlayerStates.Values)
+ {
+ state.HasSpawned = false;
+ }
+ }
}
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.Begin))]
class BeginPatch
diff --git a/Patches/UsablesPatch.cs b/Patches/UsablesPatch.cs
index 446b0139d..0e3227d4c 100644
--- a/Patches/UsablesPatch.cs
+++ b/Patches/UsablesPatch.cs
@@ -38,7 +38,7 @@ public static bool Prefix(Vent __instance, [HarmonyArgument(0)] GameData.PlayerI
// カスタムロールを元にベントを使えるか判定
// エンジニアベースの役職は常にtrue
- couldUse = playerControl.CanUseImpostorVentButton() || pc.Role.Role == RoleTypes.Engineer;
+ couldUse = playerControl.CanUseImpostorVentButton() || (pc.Role.Role == RoleTypes.Engineer && pc.Role.CanUse(__instance.Cast()));
canUse = couldUse;
// カスタムロールが使えなかったら使用不可
diff --git a/Patches/onGameStartedPatch.cs b/Patches/onGameStartedPatch.cs
index 36b4f5563..218807e7f 100644
--- a/Patches/onGameStartedPatch.cs
+++ b/Patches/onGameStartedPatch.cs
@@ -40,10 +40,6 @@ public static void Postfix(AmongUsClient __instance)
Main.introDestroyed = false;
- RandomSpawn.FirstTP = new();
- RandomSpawn.FastSpawnPosition = new();
- RandomSpawn.hostReady = false;
-
Main.DefaultCrewmateVision = Main.RealOptionsData.GetFloat(FloatOptionNames.CrewLightMod);
Main.DefaultImpostorVision = Main.RealOptionsData.GetFloat(FloatOptionNames.ImpostorLightMod);
@@ -85,7 +81,6 @@ public static void Postfix(AmongUsClient __instance)
ReportDeadBodyPatch.WaitReport[pc.PlayerId] = new();
pc.cosmetics.nameText.text = pc.name;
- RandomSpawn.FirstTP.Add(pc.PlayerId, true);
var outfit = pc.Data.DefaultOutfit;
Camouflage.PlayerSkins[pc.PlayerId] = new GameData.PlayerOutfit().Set(outfit.PlayerName, outfit.ColorId, outfit.HatId, outfit.SkinId, outfit.VisorId, outfit.PetId);
Main.clientIdList.Add(pc.GetClientId());
diff --git a/README-EN.md b/README-EN.md
index f879bfa14..b74f894f7 100644
--- a/README-EN.md
+++ b/README-EN.md
@@ -15,7 +15,7 @@ This mod is not affiliated with Among Us or Innersloth LLC, and the content cont
## Releases
-AmongUs Version: **2023.11.28**
+AmongUs Version: **2024.03.05**
**Latest Version: [Here](https://github.com/tukasa0001/TownOfHost/releases/latest)**
diff --git a/README.md b/README.md
index fb313dfbb..612255b19 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@
## リリース
-AmongUsバージョン : **2023.11.28**
+AmongUsバージョン : **2024.03.05**
**最新版は[こちら](https://github.com/tukasa0001/TownOfHost/releases/latest)**
diff --git a/Resources/string.csv b/Resources/string.csv
index ca511e732..6b6de901b 100644
--- a/Resources/string.csv
+++ b/Resources/string.csv
@@ -118,10 +118,10 @@
"InsiderInfo","Knowledge is power","知は力なり","知识就是力量","","Знание - сила!","Conhecimento é poder",""
"# マッドメイト系役職"
-"MadmateInfo","","インポスターの援助をしよう","帮助其他内鬼杀掉所有人","幫助偽裝者","Помогите Предателям убить всех","Ajude os Impostores","Ajude os Impostores"
+"MadmateInfo","Help the Impostors","インポスターの援助をしよう","帮助内鬼","幫助偽裝者","Помогите Предателям","Ajude os Impostores","Ajude os Impostores"
"BeforeMadmateInfo","Finish your tasks","タスクを済ませろ","完成你的任务","完成你的任務","Завершите свои задания","Termine as suas tarefas","Termine as suas tarefas"
-"MadGuardianInfo","Finish your tasks and help the Impostors","タスクを済ませ、インポスターの援助をしよう","完成任务后来帮助内鬼","完成你的任務並幫助偽裝者","Завершите свои задания чтобы помочь Предателям","Termine as suas tarefas e ajude os Impostores","Termine as suas tarefas e ajude os Impostores"
-"MadSnitchInfo","","タスクを済ませ、インポスターの援助をしよう","完成任务后来帮助内鬼","完成你的任務並幫助偽裝者","Завершите свои задания, чтобы помочь Предателям","Termine as suas tarefas e ajude os Impostores","Termine as suas tarefas e ajude os Impostores"
+"MadGuardianInfo","Finish your tasks and help the Impostors","タスクを済ませ、インポスターの援助をしよう","完成任务后来帮助内鬼","完成你的任務並幫助偽裝者","Завершите свои задания, чтобы помочь Предателям","Termine as suas tarefas e ajude os Impostores","Termine as suas tarefas e ajude os Impostores"
+"MadSnitchInfo","Finish your tasks and help the Impostors","タスクを済ませ、インポスターの援助をしよう","完成任务后来帮助内鬼","完成你的任務並幫助偽裝者","Завершите свои задания, чтобы помочь Предателям","Termine as suas tarefas e ajude os Impostores","Termine as suas tarefas e ajude os Impostores"
"SKMadmateInfo","You are now on Team Impostors","サイドキックにされた","你是内鬼的好帮手","你現在屬於偽裝者們了,盡你所能幫助他們","Теперь вы в команде Предателя","Você agora está no Time Impostor","Você agora está no Time Impostor"
"# 特殊クルー役職"
@@ -133,7 +133,7 @@
"SnitchInfo","Finish your tasks to find the Impostors","タスクを早く済ませよう","完成任务 揪出内鬼","完成你的所有任務來找到偽裝者","Завершите свои задания чтобы узнать Предателей","Termine as suas tarefas para dedurar os Impostores","Termine as suas tarefas para dedurar os Impostores"
"SpeedBoosterInfo","Boost others' speed","走らせろ","让其他人跑起来吧","讓其他人跑得更快","Ускорьте случайного игрока","Impulsione a velocidade dos jogadores","Impulsione a velocidade dos jogadores"
"DoctorInfo","And thus they died...","斯くして奴は死んだ","调查他人死因","查看他們的死因","Вы знаете причину смерти игроков","Veja os sinais vitais e causa da morte","Veja os sinais vitais e causa da morte"
-"TrapperInfo","","敵を罠にはめよう","诱骗敌人,让敌人落入你的陷阱","誘捕你的敵人","Убийца моментально зарепортит ваш труп","Prenda os seus inimigos","Prenda os seus inimigos"
+"TrapperInfo","Trap your enemies","敵を罠にはめよう","引诱敌人落入你的陷阱当中","誘捕你的敵人","Ловите своих врагов","Prenda os seus inimigos","Prenda os seus inimigos"
"DictatorInfo","Decide who to eject","独裁政治をしよう","让我统治世界,拥有无上的权利","讓所有人臣服於你","Повесьте своего врага на страх и риск","Escolha quem será exilado","Escolha quem será exilado"
"SeerInfo","You see the moment someone dies","他人の死んだ瞬間がわかる","你能感知死亡","你擁有陰陽眼","Вы видите когда умирают игроки","Veja o momento em que alguém morre","Veja o momento em que alguém morre"
"TimeManagerInfo","Do the tasks and extend meeting time","タスクをして会議時間を延ばそう","任务搞快点,不就有时间开会了嘛","完成你的任務來延長會議時間","Выполняйте задания чтобы увеличить время встречи","Faça as tarefas e aumente o tempo de reunião",""
@@ -155,7 +155,7 @@
"PlagueDoctorInfo","Spread disease to wipe out the crew","ペストをばらまけ","在船员之中散布瘟疫","","Распространите чуму","Espalhe doenças para acabar com a tripulação",""
"# HideAndSeek"
-"HASFoxInfo","","とにかく生き残りましょう","苟着吧,苟也是个不错的选择","","Останьтесь в живых","Sobreviva a qualquer custo","Sobreviva a qualquer custo"
+"HASFoxInfo","Just stay alive","とにかく生き残りましょう","活下去吧!活到最后你就成为了赢家!","盡你所能地活下去吧!","Останьтесь в живых","Sobreviva a qualquer custo","Sobreviva a qualquer custo"
"HASTrollInfo","Get killed","自爆しよう","轰!你为了同伴牺牲了!","盡可能讓獵人殺死你","Будьте убитым","Seja morto","Seja morto"
"# GM"
@@ -261,7 +261,7 @@
"DisableStartReactorTask","Disable StartReactor Tasks","原子炉起動タスク","禁用启动反应堆任务","禁用啟動反應堆任務","Отключить задание ''Запустить Реактор''","Desativar Tarefas de Acionar Reator",""
"DisableResetBreakerTask","Disable ResetBreaker Tasks","ブレーカーリセットタスク","禁用重置反应堆任务","禁用重置斷路器任務","Отключить задание ''Рычаги(Airship)''","Desativar Reiniciar Disjuntores",""
"SuffixMode","Suffix","名前の二行目","附加标签","名字標籤","Суффикс","Sufixo",""
-"SuffixMode.None","Never","なし","不更换","關閉","Никогда","Nunca",""
+"SuffixMode.None","Never","なし","不更换","關閉","Никто","Nunca",""
"SuffixMode.Version","Version","バージョン","版本","版本","Версия","Versão",""
"SuffixMode.Streaming","Streaming","配信中","直播中","直播中","Стримит","Ao Vivo",""
"SuffixMode.Recording","Recording","録画中","录制中","錄影中","Записывает","Gravando",""
@@ -291,7 +291,7 @@
"SelfVote","Self Vote","自投票","自票","投自己","Само Голос","Votar Em Si",""
"Skip","Skip","スキップ","跳过","跳過","Пропуск","Pular",""
"WhenTie","When Tied Vote","同数投票時","平票时","平票時","Когда ничья","Quando Empatar Votos",""
-"TieMode.Default","","デフォルト","默认随机算法","預設","По умолчанию","",""
+"TieMode.Default","Default","デフォルト","默认随机算法","預設算法","По умолчанию","Padrão",""
"TieMode.All","Eject All","全員追放","全体放逐","全員放逐","Изгнать всех","Exilar Todos",""
"TieMode.Random","Eject Random","ランダムに追放","随机放逐","隨機放逐","Изгнать случайно","Exilar Aleatório",""
"DisableDevices","Disable Devices","デバイスを無効化","禁用设备","禁用裝置","Отключить устройства","Desativar Dispositivos",""
@@ -301,17 +301,17 @@
"DisableAirshipDevices","Disable Airship Device","エアシップのデバイス無効化","禁用飞艇设备","禁用The Airship中的設備","Отключить устройства на The Airship","Desativar Dispositivos de Airship",""
"DisableFungleDevices","Disable Fungle Devices","ファングルのデバイス無効化","禁用蘑菇岛设备","","Отключить устройства на The Fangle","",""
"DisableSkeldAdmin","Disable Admin","アドミン無効化","禁用管理室地图","禁用管理室地圖","Отключить стол администратора","Desativar Admin",""
-"DisableMiraHQAdmin","","アドミン無効化","禁用管理室地图","禁用管理室地圖","Отключить стол администратора","",""
-"DisablePolusAdmin","","アドミン無効化","禁用管理室地图","禁用管理室地圖","Отключить стол администратора","",""
+"DisableMiraHQAdmin","Disable Admin","アドミン無効化","禁用管理室地图","禁用管理室地圖","Отключить стол администратора","Desativar Admin",""
+"DisablePolusAdmin","Disable Admin","アドミン無効化","禁用管理室地图","禁用管理室地圖","Отключить стол администратора","",""
"DisableAirshipCockpitAdmin","Disable Cockpit Admin","アドミン無効化(コックピット)","禁用飞艇(驾驶舱)管理室地图","禁用The Airship(駕駛艙)的管理室地圖","Отключить стол администратора в ''Кабине''","Desativar Admin da Cabine",""
"DisableAirshipRecordsAdmin","Disable Records Admin","アドミン無効化(アーカイブ)","禁用飞艇(档案室)管理室地图","禁用The Airship(檔案室)的管理室地圖","Отключить стол администратора в ''Архиве''","Desativar Admin da Sala de Arquivos",""
-"DisableSkeldCamera","Disable Camera","カメラ無効化","禁用飞艇监控","禁用飞艇监控设备","Отключить камеры","Desativar Câmeras",""
-"DisablePolusCamera","","カメラ無効化","禁用监控","禁用波鲁斯监控设备","Отключить камеры","Desativar Câmeras",""
-"DisableAirshipCamera","","カメラ無効化","禁用监控","禁用飞艇监控设备","Отключить камеры","Desativar Câmeras",""
+"DisableSkeldCamera","Disable Camera","カメラ無効化","禁用监控","禁用飞艇监控设备","Отключить камеры","Desativar Câmeras",""
+"DisablePolusCamera","Disable Camera","カメラ無効化","禁用监控","禁用飞艇监控设备","Отключить камеры","Desativar Câmeras",""
+"DisableAirshipCamera","Disable Camera","カメラ無効化","禁用监控","禁用飞艇监控设备","Отключить камеры","Desativar Câmeras",""
"DisableMiraHQDoorLog","Disable DoorLog","ドアログ無効化","禁用米拉总部门禁记录","禁用米拉总部门禁日志","Отключить журналы","Desativar Portaria",""
-"DisablePolusVital","Disable Vital","バイタル無効化","禁用飞艇生命监测装置","禁用飞艇生命监测装置","Отключить пульсы","Desativar Vitais",""
-"DisableAirshipVital","","バイタル無効化","禁用蘑菇岛生命监测装置","","Отключить пульсы","Desativar Vitais",""
-"DisableFungleVital","","バイタル無効化","禁用生命监测装置","","Отключить пульсы","",""
+"DisablePolusVital","Disable Vital","バイタル無効化","禁用生命监测装置","禁用飞艇生命监测装置","Отключить пульсы","Desativar Vitais",""
+"DisableAirshipVital","Disable Vital","バイタル無効化","禁用生命监测装置","禁用飞艇生命监测装置","Отключить пульсы","Desativar Vitais",""
+"DisableFungleVital","Disable Vital","バイタル無効化","禁用蘑菇岛生命监测装置","禁用飞艇生命监测装置","Отключить пульсы","",""
"IgnoreConditions","Ignore Conditions","除外条件","忽略条件","忽略條件","Игнорируют условия","Ignorar Condições",""
"IgnoreImpostors","Ignore Impostors","インポスターを除く","忽略内鬼","偽裝者陣營除外","Игнорируют Предатели","Ignorar Impostores",""
"IgnoreMadmates","Ignore Madmates","マッドメイト系を除く","忽略叛徒","叛徒職業除外","Игнорируют Безумцы","Ignorar Tripulantes Loucos",""
@@ -337,11 +337,11 @@
"EnableDebugMode","Enable Debug Mode","デバッグモードを有効化する","开启调试模式","啟用偵錯模式","Включить режим отладки","Ativar Modo de Depuração",""
"ChangeNameToRoleInfo","Show Role Descriptions to Unmodded Client","役職説明を非modクライアントにも表示する","对未安装本mod的玩家显示职业说明","對未安裝本模組的玩家顯示職業說明","Показать краткую информацию о роли в начале игры","Mostrar Descrição de Classe para Clientes Sem Mod",""
"RoleAssigningAlgorithm","Role Assigning Algorithm","役職割り当てのアルゴリズム","职业分配算法","職業分配算法","Алгоритм назначения Ролей","Algoritmo de Atribuição de Classes",""
-"RoleAssigningAlgorithm.Default","","デフォルト","默认","預設算法","По умолчанию","Padrão",""
-"RoleAssigningAlgorithm.NetRandom","",".NET System.Random",".NET 系统随机算法","NET系統隨機算法","Случайный","Sistema Aleatório .NET",""
-"RoleAssigningAlgorithm.HashRandom","","HashRandom","哈希随机算法","Hash值隨機算法","HashRandom","",""
-"RoleAssigningAlgorithm.Xorshift","","Xorshift","Xorshift随机算法","Xorshift隨機算法","Xorshift","",""
-"RoleAssigningAlgorithm.MersenneTwister","","Mersenne Twister","Mersenne Twister随机算法","Mersenne Twister隨機算法","MersenneTwister","",""
+"RoleAssigningAlgorithm.Default","Default","デフォルト","默认随机算法","預設算法","По умолчанию","Padrão",""
+"RoleAssigningAlgorithm.NetRandom",".NET System.Random",".NET System.Random",".NET 系统随机算法","NET系統隨機算法","Случайный","Sistema Aleatório .NET",""
+"RoleAssigningAlgorithm.HashRandom","HashRandom","HashRandom","哈希随机算法","Hash值隨機算法","HashRandom","",""
+"RoleAssigningAlgorithm.Xorshift","Xorshift","Xorshift","Xorshift随机算法","Xorshift隨機算法","Xorshift","",""
+"RoleAssigningAlgorithm.MersenneTwister","Mersenne Twister","Mersenne Twister","Mersenne Twister随机算法","Mersenne Twister隨機算法","MersenneTwister","",""
"ApplyDenyNameList","Apply DenyName List","DenyNameリストを適用する","启用违禁昵称名单","自動禁止具有不良名字的人加入","Применить файл запрещённых имён (DenyName)","Aplicar Lista de Nomes Proibidos (DenyName)",""
"KickPlayerFriendCodeNotExist","Kick Players Whose Friend Code Does Not Exist","フレンドコードが存在しないプレイヤーをキックする","踢出好友编号无效的玩家","將沒有好友代碼的玩家自動踢出","Кикнуть игроков у которых нет Кода Друга","Expulsar Jogadores Sem Código de Amigo",""
"ApplyBanList","Apply BanList","BANリストを適用する","启用封禁名单","啟用封禁名單","Применить файл с забаненными игроками (BanList)","Aplicar Lista de Banimentos (BanList)",""
@@ -384,7 +384,7 @@
"CanMakeMadmateCount","Sidekick Madmate Max Count","サイドキックマッドメイト(人)","变形者可以招募叛徒的数量","變形者招募叛徒最大人數","Максимум союзников Безумца","Máximo de Tripulantes Loucos Ajudantes",""
"MadSnitchTasks","Mad Snitch Tasks","マッドスニッチのタスク数","背叛的告密者任务数","背叛告密者任務數量","Задания Безумного Стукача","Tarefas do Dedo-Duro Louco",""
"MadSnitchCanAlsoBeExposedToImpostor","Known to Impostors","インポスターからも視認できる","对内鬼同样可见","對偽裝者同樣可見","Также не защищен от Предателей","Visível Para Impostor",""
-"MadSnitchTaskTrigger","Tasks Until Boost Activated","効果を発動するタスク数","效果发动所需任务数","效果發動所需任務數","Задачи повышающие скорость","Tarefas Para Ativar Impulso",""
+"MadSnitchTaskTrigger","Tasks Until Boost Activated","効果を発動するタスク数","发动技能所需完成任务数量","效果發動所需任務數","Задачи повышающие скорость","Tarefas Para Ativar Impulso",""
"MadGuardianCanSeeWhoTriedToKill","Can See Attempted Murderer","自身の殺害未遂者を知ることができる","背叛的守卫可以得知尝试对其击杀的玩家","背叛天使可以看到是誰嘗試殺害自己","Может видеть кто пытался его убить","Pode Ver Quem Tentou Matar",""
"MadmateCanFixLightsOut","Mad Roles Can Fix Lights","マッドメイト系役職が停電を直せる","叛徒系职业可以修理照明破坏","叛徒職業的玩家可以修理電燈","Безумцы могут чинить Свет","Loucos Podem Consertar Luzes",""
"MadmateCanFixComms","Mad Roles Can Fix Comms","マッドメイト系役職が通信障害を直せる","叛徒系职业可以修理通讯","叛徒職業的玩家可以修理通訊","Безумцы могут чинить Связь","Loucos Podem Consertar Comunicações",""
@@ -398,7 +398,7 @@
"LighterMaxVision","Max Vision","最大視界","完成任务后的视野","做完任務的視野","Дальность обзора","Aumento de Visão",""
"LighterTaskCompletedDisableLightOut","Ignore Fix Lights Effect","タスク完了時に停電を無効にする","完成任务的执灯人不受熄灯影响","完成任務的小燈人視野不受關燈影響","Имеет дальность Обзора Предателя","Ignorar Efeitos do Apagão",""
"LighterTriggerType","Ability Activation Condition","能力発動条件","技能发动条件","","Условие активации способности","Condição de Ativação da Habilidade",""
-"LighterTaskTrigger","","効果を発動するタスク数","加速所需任务数","","Задачи повышающие скорость","Tarefas Para Ativar Impulso",""
+"LighterTaskTrigger","Tasks Until Boost Activated","効果を発動するタスク数","发动技能所需完成任务数量","效果發動所需任務數","Задачи повышающие скорость","Tarefas Para Ativar Impulso",""
"SabotageMasterFixesDoors","Can Open Multiple Doors","1度に複数のドアを開けられる","修理大师打开多扇关闭的门","修理工可以一次性修理多扇門","Может открыть все двери","Pode Abrir Múltiplas Portas",""
"SabotageMasterFixesReactors","Can Fix Both Reactors","リアクターに対して能力を使える","修理大师可以一人修理核反应堆","修理工可以獨自修理兩邊的反應堆","Может починить саботаж Реактора","Pode Consertar Reatores",""
"SabotageMasterFixesOxygens","Can Fix Both O2","酸素妨害に対して能力を使える","修理大师修理氧气破坏时另一边的氧气设备将会被同时修理","修理工可以獨自修理兩邊的氧氣","Может починить саботаж O2","Pode Consertar Ambos O2",""
@@ -418,7 +418,7 @@
"SnitchCanFindNeutralKiller","Can Find Neutral Killers","ニュートラルのキル可能役職を見つけることが出来る","告密者也可以和拥有击杀能力的独立阵营玩家互相发现","告密者也可以和中立陣營帶刀職業互認","Может видеть Нейтральных Убийц","Pode Achar Assassinos Neutros",""
"SnitchRemainingTaskFound","Remaining tasks to be found","敵陣営に見つかるタスク残量","剩余任务数对敌对阵营可见","帶刀職業可見告密者剩餘任務數","Оставшиеся задания при которых он будет виден","Tarefas restantes para encontrar",""
"SpeedBoosterUpSpeed","Random Player's Speed Boost","加速値","增速者加速时的移动速度","被加速器加速的玩家的移動速度","Повысить скорость игрока на","Impulso de Velocidade",""
-"SpeedBoosterTaskTrigger","","効果を発動するタスク数","发动技能所需完成任务数量","效果發動所需任務數","Задачи повышающие скорость","Tarefas Para Ativar Impulso",""
+"SpeedBoosterTaskTrigger","Tasks Until Boost Activated","効果を発動するタスク数","加速所需任务数","效果發動所需任務數","Задачи повышающие скорость","Tarefas Para Ativar Impulso",""
"MayorAdditionalVote","Additional Votes Count","追加投票の個数","附加票数","附加票數","Дополнительные голоса","Votos Adicionais",""
"MayorHasPortableButton","Mayor Has Mobile Emergency Button","ポータブルボタンを持っている","市长跳通风管触发紧急会议","可以隨時拍桌","У Мэра есть портативная Кнопка","Botão Móvel de Emergência",""
"MayorNumOfUseButton","Number Of Mobile Emergency Button","ポータブルボタンの使用可能回数","市长紧急会议最大次数","隨時拍桌最大次數","Количество портативных Кнопок","Número de Botões de Emergência",""
@@ -442,9 +442,9 @@
"TimeThiefDecreaseMeetingTime","Time Thief Time Stolen","減少する会議時間","蚀时者每次击杀缩短的会议时间","時間小偷每次殺人減少的會議時間","Уменьшить длительность обсуждения на","Tempo Roubado de Reunião",""
"TimeThiefLowerLimitVotingTime","Minimum Voting Time","投票時間の下限","蚀时者存活时会议时间最低下限","時間小偷在場時會議時間最低下限","Уменьшить длительность голосования на","Tempo Mínimo de Votação",""
"TimeThiefReturnStolenTimeUponDeath","Return Stolen Time After Death","死亡後に盗んだ時間を返す","蚀时者死亡后会议时间重置","時間小偷死亡後將會議時間重設","Вернуть украденное время после его смерти","Devolver Tempo Roubado ao Morrer",""
-"EvilTrackerCanSeeKillFlash","Can See ''Kill Flash''","インポスターキル時にフラッシュが見える","内鬼进行击杀时邪恶的追踪者可见击杀闪光","當狼人隊友殺人時邪惡的追蹤者可以看到閃光","Может видеть ''Вспышку Убийства''","Pode Ver ""Clarão"" Quando Impostor Matar",""
+"EvilTrackerCanSeeKillFlash","Can See ''Kill Flash''","インポスターキル時にフラッシュが見える","当内鬼击杀时你可以看到杀戮闪烁","當狼人隊友殺人時邪惡的追蹤者可以看到閃光","Может видеть ''Вспышку Убийства''","Pode Ver ""Clarão"" Quando Impostor Matar",""
"EvilTrackerTargetMode","Can Set Target","ターゲットの設定タイミング","目标更换时点","可以更換目標","Может установить цель","Pode Definir Alvos",""
-"EvilTrackerTargetMode.Never","","なし","无","關閉","Никто","Nunca",""
+"EvilTrackerTargetMode.Never","Never","なし","不更换","關閉","Никто","Nunca",""
"EvilTrackerTargetMode.OnceInGame","Once In Game","試合毎","每局游戏一次","每局遊戲一次","В каждой игре","Uma Vez no Jogo",""
"EvilTrackerTargetMode.EveryMeeting","Every Meeting","ターン毎","每次会议","每回合","На каждой встрече","Toda Reunião",""
"EvilTrackerTargetMode.Always","Always","常時","一直","隨時","Всегда","Sempre",""
@@ -466,7 +466,7 @@
"NekoKabochaRevengeOnExile","Revenge When Exiled","追放された時に誰かを道連れにする","被驱逐时复仇","","Месть во время изгнания","Vinagança Quando Exilado",""
"EvilHackerCanSeeDeadMark","Can See The Location of Dead-bodies","死体位置がわかる","可以知道尸体的位置","","Может видеть местоположение трупов","Pode Ver Local dos Corpos",""
"EvilHackerCanSeeImpostorMark","Can See The Location of Other Impostors","他のインポスターの位置がわかる","可以知道内鬼的位置","","Может видеть местоположение других Предателей","Pode Ver o Local de Outros Impostores",""
-"EvilHackerCanSeeKillFlash","","インポスターキル時にフラッシュが見える","当内鬼击杀时你可以看到杀戮闪烁","","Может видеть ''Вспышку Убийства''","",""
+"EvilHackerCanSeeKillFlash","Can See ''Kill Flash''","インポスターキル時にフラッシュが見える","当内鬼击杀时你可以看到杀戮闪烁","當狼人隊友殺人時邪惡的追蹤者可以看到閃光","Может видеть ''Вспышку Убийства''","Pode Ver ""Clarão"" Quando Impostor Matar",""
"EvilHackerCanSeeMurderRoom","Can See The Murder Location","キルの発生場所がわかる","可以知道某个房间发生了击杀","","Может увидеть место убийства","Pode Ver Localidade do Assassinato",""
"PenguinAbductTimerLimit","Dragging Time","引き摺れる時間","最长拖拽时间","","Время перетаскивания","Tempo Para Arrastar",""
"PenguinMeetingKill","Kill If Meeting Starts During Dragging","会議開始時に引き摺り中ならキルする","拖拽时开会将立刻击杀目标","","Убить если встреча начнется во время перетаскивания","Matar Se Reunião Começar Enquanto Arrasta",""
@@ -475,12 +475,12 @@
"InsiderCanSeeMadmates","Can See Madmates","マッドメイトが分かる","可以看到叛徒","","Может видеть Безумцев","Pode Ver Tripulantes Loucos",""
"InsiderKillCountToSeeMadmates","Kill Count To See Madmates","必要なキル数","看到叛徒所需击杀数","","Количество убийств при котором будет виден Безумец","Quantas Kills Para Ver Tripulante Louco",""
"PlagueDoctorInfectLimit","Infect Count","感染回数","可主动感染次数","","Количество заражений","Limite de Infectados",""
-"PlagueDoctorInfectWhenKilled","Infect When Killed","キルされた時に感染させる","被击杀时感染凶手","","Заразить убийцу при смерти заражённого","Infectar Ao Ser Morto",""
+"PlagueDoctorInfectWhenKilled","Infect When Killed","キルされた時に感染させる","被击杀时感染凶手","","Заразить убийцу Чумного Доктора, когда он никого не заразил","Infectar Ao Ser Morto",""
"PlagueDoctorInfectTime","Infect Time","感染に必要な時間","感染所需时间","","Время заражения","Tempo de Infecção",""
"PlagueDoctorInfectDistance","Infect Distance","感染する距離","感染有效传播距离","","Радиус заражения","Distância de Infecção",""
"PlagueDoctorInfectInactiveTime","Infect Invalid Time","行動開始から感染しない時間","主动感染冷却时间","","Недействительное время заражения","Tempo Inativo da Infecção",""
"PlagueDoctorCanInfectSelf","Can Infect Self","自身も感染する","可以感染自己","","Может заразить себя","Pode Infectar A Si Mesmo",""
-"PlagueDoctorCanInfectVent","Can Infect in Vent","ベント内外でも感染する","可以感染管道内的玩家","","Может заразить в вентиляции","Pode Infectar no Duto",""
+"PlagueDoctorCanInfectVent","Can Infect in Vent","ベント内外でも感染する","可以感染管道内的玩家","","Может заразить находясь в вентиляции","Pode Infectar no Duto",""
"## ランダムスポーンポイント"
"Junction","Junction","三叉路","三岔路","","Перекресток","",""
@@ -507,9 +507,9 @@
"HideAndSeekRoles","Hide and Seek Roles","かくれんぼの役職","躲猫猫职业","躲貓貓職業","Роли в Прятках","Classes do Esconde-Esconde",""
"## 死因"
-"DeathReason.Kill","","キル","击杀","被殺","Убит","Abatido",""
+"DeathReason.Kill","Kill","キル","被杀","殺死","Убить","Abatido",""
"DeathReason.Vote","Ejected","追放","放逐","被丟","Изгнан","Exilado",""
-"DeathReason.Suicide","","自殺","自杀","自殺","Суицид","Suicídio",""
+"DeathReason.Suicide","Suicide","自殺","自杀","自殺","Суицид","Suicídio",""
"DeathReason.Spell","Spell","呪殺","咒杀","咒殺","Заколдован","Feitiço",""
"DeathReason.Bite","Bitten","噛殺","吸血","咬死","Укушен","Mordido",""
"DeathReason.FollowingSuicide","Lover's Suicide","後追い","为爱而死","戀人共死","♡Суицид♡","Suicídio por Amor",""
@@ -626,7 +626,7 @@
"TabGroup.CrewmateRoles","Crewmate Roles","クルー役職","船员阵营职业","船員職業","Роли Членов Экипажа","Classes de Tripulante",""
"TabGroup.NeutralRoles","Neutral Roles","ニュートラル役職","独立阵营职业","中立職業設定","Нейтральные Роли","Classes Neutras",""
"TabGroup.ImpostorRoles","Impostor Roles","インポスター役職","内鬼阵营职业","偽裝者職業設定","Роли Предателей","Classes de Impostor",""
-"TabGroup.Addons","Add-Ons","属性","附加效果","屬性","Атрибут","Atributos",""
+"TabGroup.Addons","Add-Ons","属性","附加职业","屬性","Атрибут","Atributos",""
"ActiveRolesList","Active Roles List","有効な役職一覧","有效职业一览","已開啟職業列表","Список Активных Ролей","Lista de Classes Ativas",""
"ForExample","Example Use","使用例","使用例子","使用例子","Например","Exemplo de Uso",""
"ForceEnd","Aborted","廃村","强制结束游戏","遊戲已被強制結束","Игра Окончена","Abortado",""
@@ -662,14 +662,14 @@
"ColoredOff","OFF","オフ","关闭","關閉","ВЫКЛ","Desativado",""
"CurrentActiveSettingsHelp","Current Active Settings Help","現在有効な設定の説明","当前启用设置及帮助","現在設定的模式和職業說明","Справка по текущим активным настройкам","Ajuda com Configurações Ativas",""
"WitchCurrentMode","Current Mode:","現在のモード:","当前模式:","現在模式:","Текущий Режим: ","Modo Atual:",""
-"WitchModeKill","","キル","击杀","殺人","Убит","Matar",""
-"WitchModeSpell","Spell","スペル","诅咒","下咒","Заклинать","Feitiço",""
+"WitchModeKill","Kill","キル","击杀","WitchModeKill ","Убит","Matar",""
+"WitchModeSpell","Spell","スペル","下咒","下咒","Заклинать","Feitiço",""
"WitchModeDouble","Double Enable","ダブル有効","双重有效","兩個模式同時啟用","Двойной","Duplo Ativado",""
"BountyCurrentTarget","Current Target","現在のターゲット","当前目标","目標","Текущая цель","Alvo Atual",""
"StealthDarkened","Darkened: {0}","暗転中: {0}","失明:{0}","","Затемнено: {0}","Escurecidos: {0}",""
-"Roles","Roles","役職","职业","職業","Роль","Classes",""
+"Roles","Roles","役職","职业","職業","Роли","Classes",""
"Settings","Settings","設定","设定","設定","Настройки","Configurações",""
-"Addons","Add-Ons","属性","附加职业","屬性","Атрибут","",""
+"Addons","Add-Ons","属性","附加职业","屬性","Атрибут","Atributos",""
"LastResult","Match Results","試合結果","游戏结果","上一局的遊戲結果","Результат матча","Resultados da Partida",""
"KillLog","Kill Log","キル履歴","击杀日志","擊殺紀錄","История убийств","Log de Mortes",""
"Maximum","Max","最大数","最多人数","最大數量","Максимум","Máximo",""
@@ -712,7 +712,7 @@
"FireWorksInstallAtionButtonText","Set","設置","设置","安裝","Установить","Colocar",""
"SerialKillerSuicideButtonText","Suicide Timer","自殺まで","自杀倒计时","自殺倒數","До Суицида","Suicídio Em",""
"WarlockCurseButtonText","Curse","呪う","下咒","詛咒","Проклинать","Amaldiçoar",""
-"WitchSpellButtonText","Spell","スペル","下咒","下咒","Заклясть","Feitiço",""
+"WitchSpellButtonText","Spell","スペル","下咒","下咒","Заклинать","Feitiço",""
"VampireBiteButtonText","Bite","噛む","吸血","吸血","Укусить","Morder",""
"ArsonistDouseButtonText","Douse","塗る","涂油","澆油","Облить","Encharcar",""
"PuppeteerOperateButtonText","Manipulate","操る","操控","操控","Управлять","Manipular",""
@@ -727,4 +727,4 @@
"Deadbody","DEAD","死体","尸体","","Труп","MORTO",""
"PenguinKillButtonText","Drag","拉致","拖拽","","ПЕРЕТАСКИВАТЬ","Arrastar",""
"PenguinTimerText","Drag Timer","残り時間","剩余时间","","Время перетаскивания","Tempo para Arrastar",""
-"Infected","","感染","感染","","Заражён","Infectado",""
\ No newline at end of file
+"Infected","Infected","感染","感染","","Заражён","Infectado",""
\ No newline at end of file
diff --git a/Roles/Core/CustomRoleManager.cs b/Roles/Core/CustomRoleManager.cs
index ddfd77335..ac20737b3 100644
--- a/Roles/Core/CustomRoleManager.cs
+++ b/Roles/Core/CustomRoleManager.cs
@@ -237,11 +237,10 @@ public static void OtherRolesAdd(PlayerControl pc)
/// 受信したRPCから送信先を読み取ってRoleClassに配信する
///
///
- ///
- public static void DispatchRpc(MessageReader reader, CustomRPC rpcType)
+ public static void DispatchRpc(MessageReader reader)
{
var playerId = reader.ReadByte();
- GetByPlayerId(playerId)?.ReceiveRPC(reader, rpcType);
+ GetByPlayerId(playerId)?.ReceiveRPC(reader);
}
//NameSystem
public static HashSet> MarkOthers = new();
diff --git a/Roles/Core/RoleBase.cs b/Roles/Core/RoleBase.cs
index 4bd2994a5..cbb72ff31 100644
--- a/Roles/Core/RoleBase.cs
+++ b/Roles/Core/RoleBase.cs
@@ -86,9 +86,9 @@ public virtual void OnDestroy()
protected class RoleRPCSender : IDisposable
{
public MessageWriter Writer;
- public RoleRPCSender(RoleBase role, CustomRPC rpcType)
+ public RoleRPCSender(RoleBase role)
{
- Writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)rpcType, SendOption.Reliable, -1);
+ Writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.CustomRoleSync, SendOption.Reliable, -1);
Writer.Write(role.Player.PlayerId);
}
public void Dispose()
@@ -102,17 +102,16 @@ public void Dispose()
///
/// 送信するCustomRPC
/// 送信に使用するRoleRPCSender
- protected RoleRPCSender CreateSender(CustomRPC rpcType)
+ protected RoleRPCSender CreateSender()
{
- return new RoleRPCSender(this, rpcType);
+ return new RoleRPCSender(this);
}
///
/// RPCを受け取った時に呼ばれる関数
/// RoleRPCSenderで送信されたPlayerIdは削除されて渡されるため意識しなくてもよい。
///
/// 届いたRPCの情報
- /// 届いたCustomRPC
- public virtual void ReceiveRPC(MessageReader reader, CustomRPC rpcType)
+ public virtual void ReceiveRPC(MessageReader reader)
{ }
///
/// 能力ボタンを使えるかどうか
@@ -142,6 +141,22 @@ public virtual void ApplyGameOptions(IGameOptions opt)
public virtual void OnMurderPlayerAsTarget(MurderInfo info)
{ }
+ ///
+ /// 自視点のみ変身する
+ /// 抜け殻を自視点のみに残すことが可能
+ ///
+ public virtual bool CanDesyncShapeshift => false;
+
+ ///
+ /// シェイプシフトチェック時に呼ばれる
+ /// 自分自身が変身したときのみ呼ばれる
+ /// animateを操作して変身アニメーションのカットも可能
+ ///
+ /// 変身先
+ /// アニメーションを再生するかどうか
+ /// falseを返すと変身がキャンセルされる
+ public virtual bool OnCheckShapeshift(PlayerControl target, ref bool animate) => true;
+
///
/// シェイプシフト時に呼ばれる関数
/// 自分自身について呼ばれるため本人確認不要
diff --git a/Roles/Crewmate/Sheriff.cs b/Roles/Crewmate/Sheriff.cs
index a4a90df0c..fdedc02e2 100644
--- a/Roles/Crewmate/Sheriff.cs
+++ b/Roles/Crewmate/Sheriff.cs
@@ -122,13 +122,11 @@ public override void Add()
}
private void SendRPC()
{
- using var sender = CreateSender(CustomRPC.SetSheriffShotLimit);
+ using var sender = CreateSender();
sender.Writer.Write(ShotLimit);
}
- public override void ReceiveRPC(MessageReader reader, CustomRPC rpcType)
+ public override void ReceiveRPC(MessageReader reader)
{
- if (rpcType != CustomRPC.SetSheriffShotLimit) return;
-
ShotLimit = reader.ReadInt32();
}
public float CalculateKillCooldown() => CanUseKillButton() ? CurrentKillCooldown : 0f;
diff --git a/Roles/Impostor/BountyHunter.cs b/Roles/Impostor/BountyHunter.cs
index 246d88123..4c7787e81 100644
--- a/Roles/Impostor/BountyHunter.cs
+++ b/Roles/Impostor/BountyHunter.cs
@@ -75,14 +75,12 @@ public override void Add()
}
private void SendRPC(byte targetId)
{
- using var sender = CreateSender(CustomRPC.SetBountyTarget);
+ using var sender = CreateSender();
sender.Writer.Write(targetId);
}
- public override void ReceiveRPC(MessageReader reader, CustomRPC rpcType)
+ public override void ReceiveRPC(MessageReader reader)
{
- if (rpcType != CustomRPC.SetBountyTarget) return;
-
byte targetId = reader.ReadByte();
Target = Utils.GetPlayerById(targetId);
diff --git a/Roles/Impostor/EvilHacker.cs b/Roles/Impostor/EvilHacker.cs
index 70835a033..eaf92a522 100644
--- a/Roles/Impostor/EvilHacker.cs
+++ b/Roles/Impostor/EvilHacker.cs
@@ -144,16 +144,13 @@ private void RpcCreateMurderNotify(SystemTypes room)
CreateMurderNotify(room);
if (AmongUsClient.Instance.AmHost)
{
- using var sender = CreateSender(CustomRPC.EvilHackerCreateMurderNotify);
+ using var sender = CreateSender();
sender.Writer.Write((byte)room);
}
}
- public override void ReceiveRPC(MessageReader reader, CustomRPC rpcType)
+ public override void ReceiveRPC(MessageReader reader)
{
- if (rpcType == CustomRPC.EvilHackerCreateMurderNotify)
- {
- CreateMurderNotify((SystemTypes)reader.ReadByte());
- }
+ CreateMurderNotify((SystemTypes)reader.ReadByte());
}
///
/// 名前の下にキル発生通知を出す
diff --git a/Roles/Impostor/EvilTracker.cs b/Roles/Impostor/EvilTracker.cs
index 2571fac0a..e31248489 100644
--- a/Roles/Impostor/EvilTracker.cs
+++ b/Roles/Impostor/EvilTracker.cs
@@ -122,10 +122,8 @@ public bool CheckKillFlash(MurderInfo info) // IKillFlashSeeable
}
public bool CanMakeSidekick() => CanCreateMadmate; // ISidekickable
- public override void ReceiveRPC(MessageReader reader, CustomRPC rpcType)
+ public override void ReceiveRPC(MessageReader reader)
{
- if (rpcType != CustomRPC.SetEvilTrackerTarget) return;
-
var operation = (TargetOperation)reader.ReadByte();
switch (operation)
@@ -141,7 +139,7 @@ private void ReEnableTargeting()
CanSetTarget = true;
if (AmongUsClient.Instance.AmHost)
{
- using var sender = CreateSender(CustomRPC.SetEvilTrackerTarget);
+ using var sender = CreateSender();
sender.Writer.Write((byte)TargetOperation.ReEnableTargeting);
}
}
@@ -150,7 +148,7 @@ private void RemoveTarget()
TargetId = byte.MaxValue;
if (AmongUsClient.Instance.AmHost)
{
- using var sender = CreateSender(CustomRPC.SetEvilTrackerTarget);
+ using var sender = CreateSender();
sender.Writer.Write((byte)TargetOperation.RemoveTarget);
}
}
@@ -164,7 +162,7 @@ private void SetTarget(byte targetId)
TargetArrow.Add(Player.PlayerId, targetId);
if (AmongUsClient.Instance.AmHost)
{
- using var sender = CreateSender(CustomRPC.SetEvilTrackerTarget);
+ using var sender = CreateSender();
sender.Writer.Write((byte)TargetOperation.SetTarget);
sender.Writer.Write(targetId);
}
@@ -185,16 +183,17 @@ private bool IsTrackTarget(PlayerControl target)
&& (target.Is(CustomRoleTypes.Impostor) || TargetId == target.PlayerId);
// 各所で呼ばれる処理
- public override void OnShapeshift(PlayerControl target)
+ public override bool OnCheckShapeshift(PlayerControl target, ref bool animate)
{
- var shapeshifting = !Is(target);
- if (!CanTarget() || !shapeshifting) return;
- if (target == null || target.Is(CustomRoleTypes.Impostor)) return;
+ //ターゲット出来ない、もしくはターゲットが味方の場合は処理しない
+ //※どちらにしろシェイプシフトは出来ない
+ if (!CanTarget() || target.Is(CustomRoleTypes.Impostor)) return false;
SetTarget(target.PlayerId);
Logger.Info($"{Player.GetNameWithRole()}のターゲットを{target.GetNameWithRole()}に設定", "EvilTrackerTarget");
Player.MarkDirtySettings();
Utils.NotifyRoles();
+ return false;
}
public override void AfterMeetingTasks()
{
diff --git a/Roles/Impostor/Mare.cs b/Roles/Impostor/Mare.cs
index b028bb5b3..1728dc9ee 100644
--- a/Roles/Impostor/Mare.cs
+++ b/Roles/Impostor/Mare.cs
@@ -83,13 +83,11 @@ private void ActivateKill(bool activate)
}
public void SendRPC()
{
- using var sender = CreateSender(CustomRPC.MareSync);
+ using var sender = CreateSender();
sender.Writer.Write(IsActivateKill);
}
- public override void ReceiveRPC(MessageReader reader, CustomRPC rpcType)
+ public override void ReceiveRPC(MessageReader reader)
{
- if (rpcType != CustomRPC.MareSync) return;
-
IsActivateKill = reader.ReadBoolean();
}
diff --git a/Roles/Impostor/Penguin.cs b/Roles/Impostor/Penguin.cs
index 5980ede79..4c6912c40 100644
--- a/Roles/Impostor/Penguin.cs
+++ b/Roles/Impostor/Penguin.cs
@@ -63,15 +63,13 @@ public override void Add()
public override void ApplyGameOptions(IGameOptions opt) => AURoleOptions.ShapeshifterCooldown = AbductVictim != null ? AbductTimer : 255f;
private void SendRPC()
{
- using var sender = CreateSender(CustomRPC.PenguinSync);
+ using var sender = CreateSender();
sender.Writer.Write(AbductVictim?.PlayerId ?? 255);
}
- public override void ReceiveRPC(MessageReader reader, CustomRPC rpcType)
+ public override void ReceiveRPC(MessageReader reader)
{
- if (rpcType != CustomRPC.PenguinSync) return;
-
var victim = reader.ReadByte();
if (victim == 255)
{
@@ -238,14 +236,14 @@ public override void OnFixedUpdate(PlayerControl player)
var position = Player.transform.position;
if (Player.PlayerId != 0)
{
- AbductVictim.RpcSnapTo(position);
+ AbductVictim.RpcSnapToForced(position);
}
else
{
_ = new LateTask(() =>
{
if (AbductVictim != null)
- AbductVictim.RpcSnapTo(position);
+ AbductVictim.RpcSnapToForced(position);
}
, 0.25f, "");
}
diff --git a/Roles/Impostor/Puppeteer.cs b/Roles/Impostor/Puppeteer.cs
index 1f26a25a1..ad8349bb3 100644
--- a/Roles/Impostor/Puppeteer.cs
+++ b/Roles/Impostor/Puppeteer.cs
@@ -42,15 +42,13 @@ public override void OnDestroy()
private void SendRPC(byte targetId, byte typeId)
{
- using var sender = CreateSender(CustomRPC.SyncPuppet);
+ using var sender = CreateSender();
sender.Writer.Write(typeId);
sender.Writer.Write(targetId);
}
- public override void ReceiveRPC(MessageReader reader, CustomRPC rpcType)
+ public override void ReceiveRPC(MessageReader reader)
{
- if (rpcType != CustomRPC.SyncPuppet) return;
-
var typeId = reader.ReadByte();
var targetId = reader.ReadByte();
diff --git a/Roles/Impostor/Sniper.cs b/Roles/Impostor/Sniper.cs
index f4b0bfe96..840fc33fa 100644
--- a/Roles/Impostor/Sniper.cs
+++ b/Roles/Impostor/Sniper.cs
@@ -91,7 +91,7 @@ public override void Add()
private void SendRPC()
{
Logger.Info($"{Player.GetNameWithRole()}:SendRPC", "Sniper");
- using var sender = CreateSender(CustomRPC.SniperSync);
+ using var sender = CreateSender();
var snList = ShotNotify;
sender.Writer.Write(snList.Count);
@@ -101,9 +101,8 @@ private void SendRPC()
}
}
- public override void ReceiveRPC(MessageReader reader, CustomRPC rpcType)
+ public override void ReceiveRPC(MessageReader reader)
{
- if (rpcType != CustomRPC.SniperSync) return;
ShotNotify.Clear();
var count = reader.ReadInt32();
while (count > 0)
diff --git a/Roles/Impostor/Stealth.cs b/Roles/Impostor/Stealth.cs
index fc750330b..34193c00f 100644
--- a/Roles/Impostor/Stealth.cs
+++ b/Roles/Impostor/Stealth.cs
@@ -121,16 +121,13 @@ private void RpcDarken(SystemTypes? roomType)
{
logger.Info($"暗転させている部屋を{roomType?.ToString() ?? "null"}に設定");
darkenedRoom = roomType;
- using var sender = CreateSender(CustomRPC.StealthDarken);
+ using var sender = CreateSender();
sender.Writer.Write((byte?)roomType ?? byte.MaxValue);
}
- public override void ReceiveRPC(MessageReader reader, CustomRPC rpcType)
+ public override void ReceiveRPC(MessageReader reader)
{
- if (rpcType == CustomRPC.StealthDarken)
- {
- var roomId = reader.ReadByte();
- darkenedRoom = roomId == byte.MaxValue ? null : (SystemTypes)roomId;
- }
+ var roomId = reader.ReadByte();
+ darkenedRoom = roomId == byte.MaxValue ? null : (SystemTypes)roomId;
}
/// 発生している暗転効果を解除
private void ResetDarkenState()
diff --git a/Roles/Impostor/Warlock.cs b/Roles/Impostor/Warlock.cs
index 0989add6f..494cb1016 100644
--- a/Roles/Impostor/Warlock.cs
+++ b/Roles/Impostor/Warlock.cs
@@ -126,5 +126,6 @@ public override void OnShapeshift(PlayerControl target)
public override void AfterMeetingTasks()
{
CursedPlayer = null;
+ IsCursed = false;
}
}
\ No newline at end of file
diff --git a/Roles/Impostor/Witch.cs b/Roles/Impostor/Witch.cs
index d315c89b0..fed851b8d 100644
--- a/Roles/Impostor/Witch.cs
+++ b/Roles/Impostor/Witch.cs
@@ -68,7 +68,7 @@ public override void Add()
}
private void SendRPC(bool doSpell, byte target = 255)
{
- using var sender = CreateSender(CustomRPC.WitchSync);
+ using var sender = CreateSender();
sender.Writer.Write(doSpell);
if (doSpell)
{
@@ -80,10 +80,8 @@ private void SendRPC(bool doSpell, byte target = 255)
}
}
- public override void ReceiveRPC(MessageReader reader, CustomRPC rpcType)
+ public override void ReceiveRPC(MessageReader reader)
{
- if (rpcType != CustomRPC.WitchSync) return;
-
var doSpel = reader.ReadBoolean();
if (doSpel)
{
diff --git a/Roles/Neutral/Arsonist.cs b/Roles/Neutral/Arsonist.cs
index 827d922df..e30f72156 100644
--- a/Roles/Neutral/Arsonist.cs
+++ b/Roles/Neutral/Arsonist.cs
@@ -86,24 +86,30 @@ public override void ApplyGameOptions(IGameOptions opt)
{
opt.SetVision(false);
}
- public void SendRPC(CustomRPC rpcType, byte targetId = byte.MaxValue, bool isDoused = false)
+ enum RPC_type
{
- using var sender = CreateSender(rpcType);
+ SetDousedPlayer,
+ SetCurrentDousingTarget
+ }
+ private void SendRPC(RPC_type rpcType, byte targetId = byte.MaxValue, bool isDoused = false)
+ {
+ using var sender = CreateSender();
sender.Writer.Write(targetId);
-
- if (rpcType == CustomRPC.SetDousedPlayer)
+ sender.Writer.Write((byte)rpcType);
+ if (rpcType == RPC_type.SetDousedPlayer)
sender.Writer.Write(isDoused);
}
- public override void ReceiveRPC(MessageReader reader, CustomRPC rpcType)
+ public override void ReceiveRPC(MessageReader reader)
{
var targetId = reader.ReadByte();
+ var rpcType = (RPC_type)reader.ReadByte();
switch (rpcType)
{
- case CustomRPC.SetDousedPlayer:
+ case RPC_type.SetDousedPlayer:
bool doused = reader.ReadBoolean();
IsDoused[targetId] = doused;
break;
- case CustomRPC.SetCurrentDousingTarget:
+ case RPC_type.SetCurrentDousingTarget:
TargetInfo = new(targetId, 0f);
break;
}
@@ -118,7 +124,7 @@ public void OnCheckMurderAsKiller(MurderInfo info)
{
TargetInfo = new(target.PlayerId, 0f);
Utils.NotifyRoles(SpecifySeer: killer);
- SendRPC(CustomRPC.SetCurrentDousingTarget, target.PlayerId);
+ SendRPC(RPC_type.SetCurrentDousingTarget, target.PlayerId);
}
info.DoKill = false;
}
@@ -136,7 +142,7 @@ public override void OnFixedUpdate(PlayerControl player)
{
TargetInfo = null;
Utils.NotifyRoles(SpecifySeer: Player);
- SendRPC(CustomRPC.SetCurrentDousingTarget);
+ SendRPC(RPC_type.SetCurrentDousingTarget);
}
else
{
@@ -151,9 +157,9 @@ public override void OnFixedUpdate(PlayerControl player)
Player.SetKillCooldown();
TargetInfo = null;//塗が完了したのでTupleから削除
IsDoused[ar_target.PlayerId] = true;//塗り完了
- SendRPC(CustomRPC.SetDousedPlayer, ar_target.PlayerId, true);
+ SendRPC(RPC_type.SetDousedPlayer, ar_target.PlayerId, true);
Utils.NotifyRoles();//名前変更
- SendRPC(CustomRPC.SetCurrentDousingTarget);
+ SendRPC(RPC_type.SetCurrentDousingTarget);
}
else
{
@@ -167,7 +173,7 @@ public override void OnFixedUpdate(PlayerControl player)
{
TargetInfo = null;
Utils.NotifyRoles(SpecifySeer: Player);
- SendRPC(CustomRPC.SetCurrentDousingTarget);
+ SendRPC(RPC_type.SetCurrentDousingTarget);
Logger.Info($"Canceled: {Player.GetNameWithRole()}", "Arsonist");
}
diff --git a/Roles/Neutral/Executioner.cs b/Roles/Neutral/Executioner.cs
index 152586cb0..c16ae5dea 100644
--- a/Roles/Neutral/Executioner.cs
+++ b/Roles/Neutral/Executioner.cs
@@ -104,10 +104,10 @@ public void SendRPC()
{
if (!AmongUsClient.Instance.AmHost) return;
- using var sender = CreateSender(CustomRPC.SetExecutionerTarget);
+ using var sender = CreateSender();
sender.Writer.Write(TargetId);
}
- public override void ReceiveRPC(MessageReader reader, CustomRPC rpcType)
+ public override void ReceiveRPC(MessageReader reader)
{
byte targetId = reader.ReadByte();
TargetId = targetId;
diff --git a/Roles/Neutral/PlagueDoctor.cs b/Roles/Neutral/PlagueDoctor.cs
index a4fa4aacc..a45a9d4c5 100644
--- a/Roles/Neutral/PlagueDoctor.cs
+++ b/Roles/Neutral/PlagueDoctor.cs
@@ -138,14 +138,12 @@ public static bool CanInfect(PlayerControl player)
}
public void SendRPC(byte targetId, float rate)
{
- using var sender = CreateSender(CustomRPC.SyncPlagueDoctor);
+ using var sender = CreateSender();
sender.Writer.Write(targetId);
sender.Writer.Write(rate);
}
- public override void ReceiveRPC(MessageReader reader, CustomRPC rpcType)
+ public override void ReceiveRPC(MessageReader reader)
{
- if (rpcType != CustomRPC.SyncPlagueDoctor) return;
-
var targetId = reader.ReadByte();
var rate = reader.ReadSingle();
InfectInfos[targetId] = rate;
diff --git a/Roles/Neutral/SchrodingerCat.cs b/Roles/Neutral/SchrodingerCat.cs
index 823868ef7..447bfd48d 100644
--- a/Roles/Neutral/SchrodingerCat.cs
+++ b/Roles/Neutral/SchrodingerCat.cs
@@ -218,16 +218,12 @@ public void RpcSetTeam(TeamType team)
Team = team;
if (AmongUsClient.Instance.AmHost)
{
- using var sender = CreateSender(CustomRPC.SetSchrodingerCatTeam);
+ using var sender = CreateSender();
sender.Writer.Write((byte)team);
}
}
- public override void ReceiveRPC(MessageReader reader, CustomRPC rpcType)
+ public override void ReceiveRPC(MessageReader reader)
{
- if (rpcType != CustomRPC.SetSchrodingerCatTeam)
- {
- return;
- }
Team = (TeamType)reader.ReadByte();
}
diff --git a/main.cs b/main.cs
index fb8abbc42..4c18463ba 100644
--- a/main.cs
+++ b/main.cs
@@ -12,6 +12,7 @@
using TownOfHost.Attributes;
using TownOfHost.Roles.Core;
+using TownOfHost.Modules;
[assembly: AssemblyFileVersionAttribute(TownOfHost.Main.PluginVersion)]
[assembly: AssemblyInformationalVersionAttribute(TownOfHost.Main.PluginVersion)]
@@ -50,7 +51,7 @@ public class Main : BasePlugin
// ==========
//Sorry for many Japanese comments.
public const string PluginGuid = "com.emptybottle.townofhost";
- public const string PluginVersion = "5.1.4";
+ public const string PluginVersion = "5.1.5";
// サポートされている最低のAmongUsバージョン
public static readonly string LowestSupportedVersion = "2023.10.24";
// このバージョンのみで公開ルームを無効にする場合
@@ -221,6 +222,8 @@ public override void Load()
ClassInjector.RegisterTypeInIl2Cpp();
+ SystemEnvironment.SetEnvironmentVariables();
+
Harmony.PatchAll();
}
}