using System; using System.IO; using System.Text; using InnerNet; using UnityEngine; // 单局游戏配置 public class GameOptionsData : IBytesSerializable { private const byte GameDataVersion = 1; public static readonly string[] MapNames = new string[] { "The Skeld", "???", "???" }; public static readonly float[] KillDistances = new float[] { 1f, 1.8f, 2.5f }; public static readonly string[] KillDistanceStrings = new string[] { "Short", "Normal", "Long" }; public int MaxPlayers = 10; public GameKeywords Keywords = GameKeywords.English; public byte MapId; public float PlayerSpeedMod = 1f; public float CrewLightMod = 1f; public float ImpostorLightMod = 1.5f; public float KillCooldown = 15f; public int NumCommonTasks = 1; public int NumLongTasks = 1; public int NumShortTasks = 2; public int NumEmergencyMeetings = 1; public int EmergencyCooldown = 15; public int NumImpostors = 1; public bool GhostsDoTasks = true; public int KillDistance = 1; public int DiscussionTime = 15; public int VotingTime = 120; public bool isDefaults = true; private static readonly int[] RecommendedKillCooldown = new int[] { 0, 0, 0, 0, 45, 30, 15, 35, 30, 25, 20 }; private static readonly int[] RecommendedImpostors = new int[] { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2 }; private static readonly int[] MaxImpostors = new int[] { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3 }; public static readonly int[] MinPlayers = new int[] { 4, 4, 7, 9 }; public void ToggleMapFilter(byte newId) { byte b = (byte)(((int)this.MapId ^ 1 << (int)newId) & 3); if (b != 0) { this.MapId = b; } } public bool FilterContainsMap(byte newId) { int num = 1 << (int)newId; return ((int)this.MapId & num) == num; } public GameOptionsData() { try { SystemLanguage systemLanguage = Application.systemLanguage; if (systemLanguage <= SystemLanguage.Portuguese) { if (systemLanguage != SystemLanguage.Korean) { if (systemLanguage == SystemLanguage.Portuguese) { this.Keywords = GameKeywords.Portuguese; } } else { this.Keywords = GameKeywords.Korean; } } else if (systemLanguage != SystemLanguage.Russian) { if (systemLanguage == SystemLanguage.Spanish) { this.Keywords = GameKeywords.Spanish; } } else { this.Keywords = GameKeywords.Russian; } } catch { } } public void SetRecommendations(int numPlayers, GameModes modes) { numPlayers = Mathf.Clamp(numPlayers, 4, 10); this.PlayerSpeedMod = 1f; this.CrewLightMod = 1f; this.ImpostorLightMod = 1.5f; this.KillCooldown = (float)GameOptionsData.RecommendedKillCooldown[numPlayers]; this.NumCommonTasks = 1; this.NumLongTasks = 1; this.NumShortTasks = 2; this.NumEmergencyMeetings = 1; if (modes != GameModes.OnlineGame) { this.NumImpostors = GameOptionsData.RecommendedImpostors[numPlayers]; } this.KillDistance = 1; this.DiscussionTime = 15; this.VotingTime = 120; this.isDefaults = true; this.EmergencyCooldown = ((modes == GameModes.OnlineGame) ? 15 : 0); } public void Serialize(BinaryWriter writer) { writer.Write(1); writer.Write((byte)this.MaxPlayers); writer.Write((uint)this.Keywords); writer.Write(this.MapId); writer.Write(this.PlayerSpeedMod); writer.Write(this.CrewLightMod); writer.Write(this.ImpostorLightMod); writer.Write(this.KillCooldown); writer.Write((byte)this.NumCommonTasks); writer.Write((byte)this.NumLongTasks); writer.Write((byte)this.NumShortTasks); writer.Write(this.NumEmergencyMeetings); writer.Write((byte)this.NumImpostors); writer.Write((byte)this.KillDistance); writer.Write(this.DiscussionTime); writer.Write(this.VotingTime); writer.Write(this.isDefaults); writer.Write((byte)this.EmergencyCooldown); } public static GameOptionsData Deserialize(BinaryReader reader) { try { byte b = reader.ReadByte(); if (b != 1 && b != 2) { return null; } GameOptionsData gameOptionsData = new GameOptionsData(); gameOptionsData.MaxPlayers = (int)reader.ReadByte(); gameOptionsData.Keywords = (GameKeywords)reader.ReadUInt32(); gameOptionsData.MapId = reader.ReadByte(); gameOptionsData.PlayerSpeedMod = reader.ReadSingle(); gameOptionsData.CrewLightMod = reader.ReadSingle(); gameOptionsData.ImpostorLightMod = reader.ReadSingle(); gameOptionsData.KillCooldown = reader.ReadSingle(); gameOptionsData.NumCommonTasks = (int)reader.ReadByte(); gameOptionsData.NumLongTasks = (int)reader.ReadByte(); gameOptionsData.NumShortTasks = (int)reader.ReadByte(); gameOptionsData.NumEmergencyMeetings = reader.ReadInt32(); gameOptionsData.NumImpostors = (int)reader.ReadByte(); gameOptionsData.KillDistance = (int)reader.ReadByte(); gameOptionsData.DiscussionTime = reader.ReadInt32(); gameOptionsData.VotingTime = reader.ReadInt32(); gameOptionsData.isDefaults = reader.ReadBoolean(); try { gameOptionsData.EmergencyCooldown = (int)reader.ReadByte(); } catch { } return gameOptionsData; } catch { } return null; } public byte[] ToBytes() { byte[] result; using (MemoryStream memoryStream = new MemoryStream()) { using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream)) { this.Serialize(binaryWriter); binaryWriter.Flush(); memoryStream.Position = 0L; result = memoryStream.ToArray(); } } return result; } public static GameOptionsData FromBytes(byte[] bytes) { GameOptionsData result; using (MemoryStream memoryStream = new MemoryStream(bytes)) { using (BinaryReader binaryReader = new BinaryReader(memoryStream)) { result = (GameOptionsData.Deserialize(binaryReader) ?? new GameOptionsData()); } } return result; } public override string ToString() { return this.ToHudString(10); } public string ToHudString(int numPlayers) { numPlayers = Mathf.Clamp(numPlayers, 0, 10); StringBuilder stringBuilder = new StringBuilder(256); stringBuilder.AppendLine(DestroyableSingleton.Instance.GetString(this.isDefaults ? StringNames.GameRecommendedSettings : StringNames.GameCustomSettings, Array.Empty())); int num = GameOptionsData.MaxImpostors[numPlayers]; stringBuilder.AppendLine(DestroyableSingleton.Instance.GetString(StringNames.GameMapName, Array.Empty()) + ": " + GameOptionsData.MapNames[(int)this.MapId]); stringBuilder.Append(string.Format("{0}: {1}", DestroyableSingleton.Instance.GetString(StringNames.GameNumImpostors, Array.Empty()), this.NumImpostors)); if (this.NumImpostors > num) { stringBuilder.Append(string.Format(" ({0}: {1})", DestroyableSingleton.Instance.GetString(StringNames.Limit, Array.Empty()), num)); } stringBuilder.AppendLine(); stringBuilder.AppendLine(string.Format("{0}: {1}", DestroyableSingleton.Instance.GetString(StringNames.GameNumMeetings, Array.Empty()), this.NumEmergencyMeetings)); stringBuilder.AppendLine(string.Format("{0}: {1}s", DestroyableSingleton.Instance.GetString(StringNames.GameEmergencyCooldown, Array.Empty()), this.EmergencyCooldown)); stringBuilder.AppendLine(string.Format("Discussion Time: {0}s", this.DiscussionTime)); if (this.VotingTime > 0) { stringBuilder.AppendLine(string.Format("{0}: {1}s", DestroyableSingleton.Instance.GetString(StringNames.GameVotingTime, Array.Empty()), this.VotingTime)); } else { stringBuilder.AppendLine(DestroyableSingleton.Instance.GetString(StringNames.GameVotingTime, Array.Empty()) + ": ∞s"); } stringBuilder.AppendLine(string.Format("{0}: {1}x", DestroyableSingleton.Instance.GetString(StringNames.GamePlayerSpeed, Array.Empty()), this.PlayerSpeedMod)); stringBuilder.AppendLine(string.Format("{0}: {1}x", DestroyableSingleton.Instance.GetString(StringNames.GameCrewLight, Array.Empty()), this.CrewLightMod)); stringBuilder.AppendLine(string.Format("{0}: {1}x", DestroyableSingleton.Instance.GetString(StringNames.GameImpostorLight, Array.Empty()), this.ImpostorLightMod)); stringBuilder.AppendLine(string.Format("{0}: {1}s", DestroyableSingleton.Instance.GetString(StringNames.GameKillCooldown, Array.Empty()), this.KillCooldown)); stringBuilder.AppendLine(DestroyableSingleton.Instance.GetString(StringNames.GameKillDistance, Array.Empty()) + ": " + GameOptionsData.KillDistanceStrings[this.KillDistance]); stringBuilder.AppendLine(string.Format("{0}: {1}", DestroyableSingleton.Instance.GetString(StringNames.GameCommonTasks, Array.Empty()), this.NumCommonTasks)); stringBuilder.AppendLine(string.Format("{0}: {1}", DestroyableSingleton.Instance.GetString(StringNames.GameLongTasks, Array.Empty()), this.NumLongTasks)); stringBuilder.Append(string.Format("{0}: {1}", DestroyableSingleton.Instance.GetString(StringNames.GameShortTasks, Array.Empty()), this.NumShortTasks)); return stringBuilder.ToString(); } public int GetAdjustedNumImpostors(int playerCount) { int numImpostors = PlayerControl.GameOptions.NumImpostors; int max = GameOptionsData.MaxImpostors[GameData.Instance.PlayerCount]; return Mathf.Clamp(numImpostors, 1, max); } }