diff --git a/MiraAPI.Example/Modifiers/CaptainModifier.cs b/MiraAPI.Example/Modifiers/CaptainModifier.cs index 20e3872..ac15a69 100644 --- a/MiraAPI.Example/Modifiers/CaptainModifier.cs +++ b/MiraAPI.Example/Modifiers/CaptainModifier.cs @@ -2,7 +2,7 @@ using MiraAPI.GameOptions; using MiraAPI.Modifiers; using MiraAPI.Modifiers.Types; - +using MiraAPI.Translation; using MiraAPI.Utilities.Assets; using UnityEngine; @@ -10,7 +10,7 @@ namespace MiraAPI.Example.Modifiers; public class CaptainModifier : GameModifier { - public override string ModifierName => "modifier.captain"; + public override string ModifierName => MiraLocaleManager.Get("modifier.captain"); public override LoadableAsset? ModifierIcon => ExampleAssets.CallMeetingButton; public override void OnDeath(DeathReason reason) @@ -20,7 +20,7 @@ public class CaptainModifier : GameModifier public override string GetDescription() { - return "modifier.captain.description"; + return MiraLocaleManager.Get("modifier.captain.TabDescription"); } public override int GetAssignmentChance() diff --git a/MiraAPI.Example/Modifiers/Freezer/FreezeModifier.cs b/MiraAPI.Example/Modifiers/Freezer/FreezeModifier.cs index 8cc961b..8cd0139 100644 --- a/MiraAPI.Example/Modifiers/Freezer/FreezeModifier.cs +++ b/MiraAPI.Example/Modifiers/Freezer/FreezeModifier.cs @@ -1,13 +1,14 @@ using Il2CppSystem; using MiraAPI.Example.Roles; using MiraAPI.Modifiers.Types; +using MiraAPI.Translation; using UnityEngine; namespace MiraAPI.Example.Modifiers.Freezer; public class FreezeModifier : TimedModifier { - public override string ModifierName => "modifier.freezed"; + public override string ModifierName => MiraLocaleManager.Get("modifier.freezed"); public override bool HideOnUi => false; public override float Duration => 15f; public override bool AutoStart => true; diff --git a/MiraAPI.Example/Modifiers/HighPriorityModifier.cs b/MiraAPI.Example/Modifiers/HighPriorityModifier.cs index a637df5..7399e6d 100644 --- a/MiraAPI.Example/Modifiers/HighPriorityModifier.cs +++ b/MiraAPI.Example/Modifiers/HighPriorityModifier.cs @@ -1,14 +1,15 @@ using MiraAPI.Modifiers.Types; +using MiraAPI.Translation; namespace MiraAPI.Example.Modifiers; public class HighPriorityModifier : GameModifier { - public override string ModifierName => "modifier.highPriority"; + public override string ModifierName => MiraLocaleManager.Get("modifier.highPriority"); public override string GetDescription() { - return "modifier.highPriority.description"; + return MiraLocaleManager.Get("modifier.highPriority.TabDescription"); } public override int GetAssignmentChance() diff --git a/MiraAPI.Example/Resources/Locale/en_US.xml b/MiraAPI.Example/Resources/Locale/en_US.xml index 5951728..e370dc3 100644 --- a/MiraAPI.Example/Resources/Locale/en_US.xml +++ b/MiraAPI.Example/Resources/Locale/en_US.xml @@ -1,33 +1,34 @@ - Teleporter - Zoom out and teleport across the map! - Zoom out and teleport across the map! - Zoom out and teleport across the map! - The Teleporter is a Crewmate role that can move around the map using their dope-ass ability. - Freezer - Get iced, nerd. - Freeze others for a duration of time. - Freeze another player for a duration of time. - The Freezer is an Impostor role that can freeze players. Or something along those lines. - Mayor - Democracy is the best policy. - Vote out the Impostors with more votes. + Teleporter + Zoom out and teleport across the map! + Zoom out and teleport across the map! + Zoom out and teleport across the map! + The Teleporter is a Crewmate role that can move around the map using their dope-ass ability. + Freezer + Get iced, nerd. + Freeze others for a duration of time. + Freeze another player for a duration of time. + The Freezer is an Impostor role that can freeze players. Or something along those lines. + Mayor + Democracy is the best policy. + Vote out the Impostors with more votes. Your votes have double the power. - You get one extra vote in the meeting! - The Mayor is a Crewmate role that gets two votes in the meeting, instead of the singular vote other Crewmates get. - Chamelon - Become one with the environment. - Fade out of everyone's vision by not moving. - Stay invisible while not moving. - The Chamelon is a Crewmate role that slowly becomes invisible while standing still. - Outcast Killer - Kill everyone else. - Be the last outcast standing. + You get one extra vote in the meeting! + The Mayor is a Crewmate role that gets two votes in the meeting, instead of the singular vote other Crewmates get. + Chamelon + Become one with the environment. + Fade out of everyone's vision by not moving. + Stay invisible while not moving. + The Chamelon is a Crewmate role that slowly becomes invisible while standing still. + Outcast Killer + Kill everyone else. + Be the last outcast standing. Eliminate every other faction. - Outcast who can kill. - The Outcast Killer is an Outcast role that can kill, like some sort of neutral killer... + Outcast who can kill. + The Outcast Killer is an Outcast role that can kill, like some sort of neutral killer... Outcast + Outcast Roles OUTCAST You are an Outcast. You do not have a team. Think diff --git a/MiraAPI.Example/Resources/Locale/zh_CN.xml b/MiraAPI.Example/Resources/Locale/zh_CN.xml index aa9f7eb..e69f22c 100644 --- a/MiraAPI.Example/Resources/Locale/zh_CN.xml +++ b/MiraAPI.Example/Resources/Locale/zh_CN.xml @@ -6,12 +6,12 @@ 缩小视野并在地图上传送! 冰冻者 将其他玩家冰冻一段时间。 - 市长 - 你拥有额外投票权! - 变色龙 - 静止不动时保持隐身。 - 流放杀手 - 可以击杀的流放者。 + 市长 + 你拥有额外投票权! + 变色龙 + 静止不动时保持隐身。 + 流放杀手 + 可以击杀的流放者。 流放者 流放者 你是流放者,你没有队伍。 @@ -22,10 +22,10 @@ 召集会议 赢得游戏 队长 - 你可以在地图上任意位置召集会议。 + 你可以在地图上任意位置召集会议。 已被冰冻 高优先级 - 你是高优先级!老实说我也不太清楚这是什么意思…… + 你是高优先级!老实说我也不太清楚这是什么意思…… 示例选项组 1 开关选项 1 开关选项 2 @@ -46,10 +46,8 @@ 通用 某个布尔选项 数字选项 - 自定义职业 冰冻时长 冰冻次数 - 传送者 传送冷却 传送持续时间 缩放距离 diff --git a/MiraAPI.Example/Roles/ChameleonRole.cs b/MiraAPI.Example/Roles/ChameleonRole.cs index e3f91b7..c1d9be2 100644 --- a/MiraAPI.Example/Roles/ChameleonRole.cs +++ b/MiraAPI.Example/Roles/ChameleonRole.cs @@ -10,7 +10,8 @@ namespace MiraAPI.Example.Roles; public class ChameloenRole : CrewmateRole, ICustomRole { - public string IdPart => "ApiExample.Role.Chamelon"; + public string IdPart => "Chamelon"; + public string IdPrefix => "ApiExample.Role.Crewmate"; public Color RoleColor => Palette.AcceptedGreen; public ModdedRoleTeams Team => ModdedRoleTeams.Crewmate; @@ -20,7 +21,9 @@ public class ChameloenRole : CrewmateRole, ICustomRole { OptionsScreenshot = ExampleAssets.Banner, Icon = MiraAssets.CrewmateFile, - IconTmp = TmpSpriteUtils.CreateSpriteAsset(MiraAssets.CrewmateFile.LoadAsset(), "ApiExample.Role.Impostor.ChameleonRole"), + IconTmp = TmpSpriteUtils.CreateSpriteAsset( + MiraAssets.CrewmateFile.LoadAsset(), + "ApiExample.Role.Impostor.ChameleonRole"), IntroSound = CustomRoleUtils.GetIntroSound(RoleTypes.Shapeshifter), }; @@ -54,12 +57,18 @@ public class ChameloenRole : CrewmateRole, ICustomRole { SpriteRenderer rend = Player.cosmetics.currentBodySprite.BodySprite; TextMeshPro tmp = Player.cosmetics.nameText; - tmp.color = Color.Lerp(tmp.color, new Color(tmp.color.r, tmp.color.g, tmp.color.b, Player.AmOwner ? 0.3f : 0), Time.deltaTime * 4f); + tmp.color = Color.Lerp( + tmp.color, + new Color(tmp.color.r, tmp.color.g, tmp.color.b, Player.AmOwner ? 0.3f : 0), + Time.deltaTime * 4f); rend.color = Color.Lerp(rend.color, new Color(1, 1, 1, Player.AmOwner ? 0.3f : 0), Time.deltaTime * 4f); foreach (var cosmetic in Player.cosmetics.transform.GetComponentsInChildren()) { - cosmetic.color = Color.Lerp(cosmetic.color, new Color(1, 1, 1, Player.AmOwner ? 0.3f : 0), Time.deltaTime * 4f); + cosmetic.color = Color.Lerp( + cosmetic.color, + new Color(1, 1, 1, Player.AmOwner ? 0.3f : 0), + Time.deltaTime * 4f); } } } @@ -73,6 +82,7 @@ public class ChameloenRole : CrewmateRole, ICustomRole { cosmetic.color = Color.white; } + Player.cosmetics.currentBodySprite.BodySprite.color = Color.white; Player.cosmetics.nameText.color = Color.white; } diff --git a/MiraAPI.Example/Roles/FreezerRole.cs b/MiraAPI.Example/Roles/FreezerRole.cs index d365b37..775b373 100644 --- a/MiraAPI.Example/Roles/FreezerRole.cs +++ b/MiraAPI.Example/Roles/FreezerRole.cs @@ -6,14 +6,15 @@ namespace MiraAPI.Example.Roles; public class FreezerRole : ImpostorRole, ICustomRole { - public string IdPart => "ApiExample.Role.Freezer"; + public string IdPart => "Freezer"; + public string IdPrefix => "ApiExample.Role.Impostor"; public Color RoleColor => Palette.Blue; public ModdedRoleTeams Team => ModdedRoleTeams.Impostor; public CustomRoleConfiguration Configuration => new CustomRoleConfiguration(this) { Icon = MiraAssets.ImpostorFile, - IconTmp = TmpSpriteUtils.CreateSpriteAsset(MiraAssets.ImpostorFile.LoadAsset(), "ApiExample.Role.Impostor.FreezerRole"), + IconTmp = TmpSpriteUtils.CreateSpriteAsset(MiraAssets.ImpostorFile.LoadAsset(), "ApiExample.Role.Impostor.Freezer"), OptionsScreenshot = ExampleAssets.Banner, MaxRoleCount = 2, }; diff --git a/MiraAPI.Example/Roles/MayorRole.cs b/MiraAPI.Example/Roles/MayorRole.cs index 6dae223..45639c0 100644 --- a/MiraAPI.Example/Roles/MayorRole.cs +++ b/MiraAPI.Example/Roles/MayorRole.cs @@ -5,7 +5,8 @@ namespace MiraAPI.Example.Roles; public class MayorRole : CrewmateRole, ICustomRole { - public string IdPart => "ApiExample.Role.Mayor"; + public string IdPart => "Mayor"; + public string IdPrefix => "ApiExample.Role.Crewmate"; public Color RoleColor => new Color32(221, 176, 152, 255); public ModdedRoleTeams Team => ModdedRoleTeams.Crewmate; public CustomRoleConfiguration Configuration => new(this); diff --git a/MiraAPI.Example/Roles/NeutralKillerRole.cs b/MiraAPI.Example/Roles/NeutralKillerRole.cs index 9ccec19..62a4cbe 100644 --- a/MiraAPI.Example/Roles/NeutralKillerRole.cs +++ b/MiraAPI.Example/Roles/NeutralKillerRole.cs @@ -8,7 +8,8 @@ namespace MiraAPI.Example.Roles; public class NeutralKillerRole : ImpostorRole, ICustomRole { - public string IdPart => "ApiExample.Role.OutcastKiller"; + public string IdPart => "OutcastKiller"; + public string IdPrefix => "ApiExample.Role.Outcast"; public Color RoleColor => Color.magenta; public ModdedRoleTeams Team => ModdedRoleTeams.Custom; @@ -19,7 +20,7 @@ public class NeutralKillerRole : ImpostorRole, ICustomRole CanUseVent = true, }; - public RoleOptionsGroup RoleOptionsGroup { get; } = new("outcast", Color.gray); + public RoleOptionsGroup RoleOptionsGroup { get; } = new("outcast.group", Color.gray); [HideFromIl2Cpp] public TeamIntroConfiguration? IntroConfiguration { get; } = new( diff --git a/MiraAPI.Example/Roles/TeleporterRole.cs b/MiraAPI.Example/Roles/TeleporterRole.cs index 8c114b8..95b8b6c 100644 --- a/MiraAPI.Example/Roles/TeleporterRole.cs +++ b/MiraAPI.Example/Roles/TeleporterRole.cs @@ -5,7 +5,8 @@ namespace MiraAPI.Example.Roles; public class TeleporterRole : CrewmateRole, ICustomRole { - public string IdPart => "ApiExample.Role.Teleporter"; + public string IdPart => "Teleporter"; + public string IdPrefix => "ApiExample.Role.Crewmate"; public Color RoleColor => new Color32(221, 176, 152, 255); public ModdedRoleTeams Team => ModdedRoleTeams.Crewmate; diff --git a/MiraAPI/Modifiers/ModifierComponent.cs b/MiraAPI/Modifiers/ModifierComponent.cs index da13f1a..1d7e5d7 100644 --- a/MiraAPI/Modifiers/ModifierComponent.cs +++ b/MiraAPI/Modifiers/ModifierComponent.cs @@ -78,7 +78,7 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr) } catch (Exception e) { - Error($"Error while deactivating modifier {modifier.ModifierName.Translate()}: {e.ToString()}"); + Error($"Error while deactivating modifier {modifier.ModifierName}: {e.ToString()}"); } Modifiers.Remove(modifier); @@ -96,7 +96,7 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr) } catch (Exception e) { - Error($"Error while activating modifier {modifier.ModifierName.Translate()}: {e.ToString()}"); + Error($"Error while activating modifier {modifier.ModifierName}: {e.ToString()}"); } if (modifier is TimedModifier { AutoStart: true } timer) @@ -123,7 +123,7 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr) } catch (Exception e) { - Error($"Error while (fixed) updating modifier {modifier.ModifierName.Translate()}: {e.ToString()}"); + Error($"Error while (fixed) updating modifier {modifier.ModifierName}: {e.ToString()}"); } } @@ -154,7 +154,7 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr) } catch (Exception e) { - Error($"Error while updating modifier {modifier.ModifierName.Translate()}: {e.ToString()}"); + Error($"Error while updating modifier {modifier.ModifierName}: {e.ToString()}"); } } } @@ -353,7 +353,7 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr) { if (!ActiveModifiers.Contains(modifier)) { - Error($"Cannot remove modifier {modifier.ModifierName.Translate()} because it is not active on this player."); + Error($"Cannot remove modifier {modifier.ModifierName} because it is not active on this player."); return; } diff --git a/MiraAPI/Modifiers/ModifierDisplay/ModifierUiComponent.cs b/MiraAPI/Modifiers/ModifierDisplay/ModifierUiComponent.cs index 861a6d0..cafbd1b 100644 --- a/MiraAPI/Modifiers/ModifierDisplay/ModifierUiComponent.cs +++ b/MiraAPI/Modifiers/ModifierDisplay/ModifierUiComponent.cs @@ -51,8 +51,8 @@ public class ModifierUiComponent(nint cppPtr) : MonoBehaviour(cppPtr) return; } - nameText.text = Modifier.ModifierName.Translate(); - desc.text = Modifier.GetDescription().Translate(); + nameText.text = Modifier.ModifierName; + desc.text = Modifier.GetDescription(); modBg.gameObject.SetActive(true); icon.gameObject.SetActive(Modifier.ModifierIcon != null); diff --git a/MiraAPI/Roles/ICustomRole.cs b/MiraAPI/Roles/ICustomRole.cs index ff061ed..13020ff 100644 --- a/MiraAPI/Roles/ICustomRole.cs +++ b/MiraAPI/Roles/ICustomRole.cs @@ -15,10 +15,15 @@ namespace MiraAPI.Roles; public interface ICustomRole : IOptionable { /// - /// Gets the id part used to build the role's translation keys. + /// Gets the id part used to build the role's translation keys. It is recommended to simply call it what the role is, as other mods may utilize it. /// string IdPart => GetType().Name; + /// + /// Gets the id part used to build the role's translation keys. It is recommended to call it ModGuid.Role.Faction + /// + string IdPrefix => GetType().Namespace!; + /// /// Gets the name of the role. /// @@ -27,7 +32,7 @@ public interface ICustomRole : IOptionable /// /// Gets the role's name id for localization. /// - string RoleNameLocale => IdPart; + string RoleNameLocale => MiraLocaleManager.BuildTranslationId(IdPrefix, IdPart); /// /// Gets the description of the role. Used in the Intro Cutscene. @@ -37,7 +42,7 @@ public interface ICustomRole : IOptionable /// /// Gets the role's intro blurb id for localization. /// - string RoleDescriptionLocale => MiraLocaleManager.BuildTranslationId(IdPart, "IntroBlurb"); + string RoleDescriptionLocale => MiraLocaleManager.BuildTranslationId(IdPrefix, IdPart, "IntroBlurb"); /// /// Gets the medium description of the role. Used in the role guide and options menu. @@ -47,7 +52,7 @@ public interface ICustomRole : IOptionable /// /// Gets the role's medium description id for localization. /// - string RoleMedDescriptionLocale => MiraLocaleManager.BuildTranslationId(IdPart, "MedDescription"); + string RoleMedDescriptionLocale => MiraLocaleManager.BuildTranslationId(IdPrefix, IdPart, "MedDescription"); /// /// Gets the long description of the role. Used in the Role Tab. @@ -57,7 +62,7 @@ public interface ICustomRole : IOptionable /// /// Gets the role's long description id for localization. /// - string RoleLongDescriptionLocale => MiraLocaleManager.BuildTranslationId(IdPart, "TabDescription"); + string RoleLongDescriptionLocale => MiraLocaleManager.BuildTranslationId(IdPrefix, IdPart, "TabDescription"); /// /// Gets the wiki description of the role. Used in the wiki, but not currently required. @@ -67,7 +72,7 @@ public interface ICustomRole : IOptionable /// /// Gets the role's wiki description id for localization. /// - string RoleWikiDescriptionLocale => MiraLocaleManager.BuildTranslationId(IdPart, "WikiDescription"); + string RoleWikiDescriptionLocale => MiraLocaleManager.BuildTranslationId(IdPrefix, IdPart, "WikiDescription"); /// /// Gets the faction / alignment of the role. Used in the role guide. diff --git a/MiraAPI/Translation/MiraLocaleManager.cs b/MiraAPI/Translation/MiraLocaleManager.cs index a34f22f..d0a642a 100644 --- a/MiraAPI/Translation/MiraLocaleManager.cs +++ b/MiraAPI/Translation/MiraLocaleManager.cs @@ -187,9 +187,14 @@ public static class MiraLocaleManager return fallback != string.Empty ? fallback : key; } - public static string BuildTranslationId(string idPart, string suffix) + public static string BuildTranslationId(string modId, string idPart, string suffix) { - return idPart.StartsWith('#') ? idPart[1..] : $"{idPart}.{suffix}"; + return idPart.StartsWith('#') ? idPart[1..] : $"{modId}.{idPart}.{suffix}"; + } + + public static string BuildTranslationId(string modId, string idPart) + { + return idPart.StartsWith('#') ? idPart[1..] : $"{modId}.{idPart}"; } private static string GetModLangDir(string modGuid)