Beta v0.61.7 Patch Notes
v0.61.7 -- Beta
A localization-debt release on top of v0.61.6. v0.61.6 cleared a long run of individually-reported "X is not translated" bugs (puzzles, the Gauntlet entrance theater, Druid's Shrines, world boss combat/broadcasts, and more). A proactive sweep at the end of that release inventoried the remaining hardcoded-English player-facing flavor across the data files -- roughly 650 strings -- and recorded it as a tracked backlog. This release works that backlog down in dedicated passes instead of waiting for each surface to surface as its own bug report.
The pattern for every entry: the English text in the data file stays as the source/fallback, the displayed value is routed through Loc.Get keys (loc-pool lookups for random-variant arrays; localized accessors on the data type, like the v0.61.6 shrine/champion accessors), and the four non-English languages (hu/es/fr/it) are fully translated via parallel translation agents. The proper-noun layer stays English (monster/boss/champion names, beast species shown as the player's choice, solution tokens the player types). Translation-arg parity, no em-dashes, and newline/leading-space preservation are validated per file.
Beast taming and wilderness flavor localized
First backlog pass. Two surfaces, 80 strings:
Beast taming (BeastData). The eight tameable wild beasts each had a first-sighting encounter description, a tame-success line, and a one-line passive-effect summary, all hardcoded English. Localized via new accessors on the beast definition (LocEncounterFlavor / LocTameSuccessFlavor / LocPassiveDescription) resolving beast.{id}.* keys, routed through the wilderness encounter display and the Home pet roster. The beast type names (Forest Hawk, Dire Wolf, etc.) and species labels stay English (creature-name layer, same as monster names). 24 keys.
Wilderness exploration prose (WildernessData). The foraging result lines, ruins-encounter descriptions, and traveler-encounter lines (plus the traveler's role label, which appears inside other sentences like "the woodcutter shares wisdom") were hardcoded English across the four regions. Localized via new per-region accessors (GetForagingText / GetRuinsEncounter / GetTravelerText / GetTravelerName), keyed per region and position. The internal foraging effect tokens and item names that drive the reward (not displayed) stay as-is. 56 keys. (The region and discovery names, descriptions, and compass directions were already localized in v0.61.6.)
All 80 keys translated into hu/es/fr/it via parallel agents, preserving multi-line breaks and the gameplay numbers in the passive summaries.
Dungeon riddles localized
Second backlog pass, and a solvability-critical one. The dungeon RiddleGate guardians pose classic guess-the-answer riddles -- the player reads the riddle and free-types the answer -- and all 51 riddles (their text lines, the canonical answer, the alternate accepted answers, and the hint) were hardcoded English. A non-English player could read a translated prompt elsewhere but hit an English riddle they then had to answer in English.
All 51 riddles (377 strings) were extracted to riddle.{id}.* loc keys with localized accessors on the riddle type (LocText / LocAnswer / LocAlternates / LocHint), and translated into all four non-English languages. Because the riddle is only solvable if its translated text points to its translated answer, each riddle was translated as a coherent unit, and riddles built on English-specific wordplay were adapted rather than translated literally -- the letter-spelling riddles were re-anchored to letters that work in the target language, and pun riddles (the "keys / space / enter -> keyboard" one, the reversal puns) were reworked so the localized text still leads to the localized answer.
The answer check now accepts BOTH the original English answer set AND the localized one: a player reading a translated riddle types the translated answer and it works, while the English answer also still works as a fallback. That keeps the riddles robust against any translation drift and means a bilingual player is never locked out. The "the answer was..." reveal on failure and the hint whisper now show in the player's language too.
NPC orientation diversity fix -- lesbians were being mislabeled as gay
A live-world audit (prompted by player complaints about representation) found the NPC sexual-orientation system was broken in a way that erased lesbians: of the living NPCs, the world had several gay men, only a single lesbian, and a couple of female NPCs incorrectly flagged "gay."
Root cause: the orientation roll in the personality generator runs BEFORE the caller sets the NPC's gender. The profile's Gender defaults to Male, so the roll's "same-sex" branch always produced Gay and literally never produced Lesbian. Then the caller set the real gender afterward -- leaving any female who rolled the same-sex band stuck as "Gay." So lesbians only ever existed via the birth-time diversity floor, and as that initial roster aged out the lesbian count decayed toward zero while the gay-male count looked fine.
Fixes:
- New
PersonalityProfile.SyncOrientationToGender()reconciles a Gay/Lesbian orientation with the profile's finalized gender (female + gay -> lesbian, and vice versa). It is bidirectional and idempotent. Called at every NPC-creation site once gender is known -- template spawn, immigrant generation, and child coming-of-age -- so the random roll now produces lesbians organically (a female who rolls the same-sex band becomes a lesbian instead of a mislabeled gay man). - The same sync runs as a heal on world load (online and single-player), so the existing mislabeled NPCs are corrected the next time the world is loaded and re-saved -- no manual data surgery needed.
- Representation rates were raised from the old ~95% straight / 2% gay-lesbian / 3% bisexual to ~85% straight / 8% gay-lesbian / 6% bisexual / 1% pansexual, for a more representative population.
- The diversity floor (previously a flat minimum of 2 gay-male / 2 lesbian / 2 bisexual set only at world birth) is now proportional to the living population (about 4% per category, never below 3), and the late-joiner nudge that maintains it as the population turns over was strengthened (60% -> 80% chance to fill a gap). So the world keeps its representation as NPCs die and new ones arrive, instead of drifting straight over time.
Leaving an NPC conversation took multiple "0" presses (screen-reader report)
A screen-reader player reported that leaving a conversation in the city sometimes took pressing 0 once, twice, or even three times, with no obvious cause. The cause was nested menus that each use 0 to back out: talking to a townsperson opens a per-NPC interaction menu ([5] = the full visual-novel conversation, [0] = walk away), and the full conversation has its own [0] to leave. So ending the deep conversation dropped the player back into the per-NPC sub-menu ("still talking to this NPC"), where another 0 was needed to actually walk away -- and if they'd been on a "press enter to continue" prompt inside the conversation, that ate a third 0 first. The depth varied with where the player was, hence "sometimes once, twice, even three times." For a screen-reader user it is especially confusing because every nested "0. ..." option sounds alike, so there's no way to tell which level you're on.
Fix: ending the full visual-novel conversation now drops the player straight back out to where they picked the NPC, instead of re-showing the per-NPC sub-menu. The full conversation is the complete "talk to this NPC" session and already has its own Leave option, so the extra menu level was redundant. Leaving is now a single, predictable 0. (The per-NPC menu's other quick options -- rumors, dungeon talk, challenge -- are unchanged; this only affects the exit path after the full conversation.)
Boss-dialogue localization: Old Gods
The largest remaining surface. The seven Old God boss fights (Maelketh, Veloura, Thorgrim, Noctura, Aurelion, Terravok, Manwe) plus the Noctura post-Manwe betrayal variant carried all their dialogue -- the combat-entry phrase, phase-transition speeches, defeat dialogue, and (for the saveable gods) the save dialogue -- as hardcoded English. 314 strings extracted to oldgod.{god}.{section}.{i} loc keys via localized accessors on the boss-data type (LocIntro / LocPhase2 / LocPhase3 / LocDefeat / LocLoss / LocSave), with the betrayal variant keyed separately so it doesn't collide with the regular Noctura fight. Every display site in the boss system and the combat phase-transition handler was routed through the accessors, and the hardcoded phase-transition flavor ("X grows more powerful!" / "unleashes their true form!") was localized too. Translated into all four non-English languages in the dramatic divine-boss register, with the gods' names and the GODNAME: "..." speech shape preserved. (Pre-existing em-dashes in the English source were normalized to -- in the keys to match the project's no-em-dash convention.)
Boss-dialogue localization: World Bosses
Part two of the boss-dialogue megapass. The eight world bosses (Abyssal Leviathan, Void Colossus, Shadowlord Malachar, Crimson Wyrm, Lich King Vareth, Iron Titan, Dread Serpent Nidhogg, Nameless Horror) carried all their combat text -- spawn narration, phase-transition speeches, defeat lines, and the name + description of every per-phase ability -- as hardcoded English. 136 strings extracted to worldboss.{id}.* loc keys via localized accessors on the boss-definition type (LocSpawn / LocPhase2 / LocPhase3 / LocDefeat, plus LocAbilityName / LocAbilityDesc that resolve an ability by its phase and slot), with every display site in the world boss combat loop routed through them. Ability names (Tidal Surge, Fire Breath, etc.) and their descriptions both translate -- they are descriptive flavor, not proper nouns, and the player never types them, so there is nothing to break.
Two of the boss's authored dialogue arrays -- the spawn narration and the defeat line -- existed in the data but were never actually shown on screen. They are now wired up: the spawn narration plays when you first engage the boss (mirroring the Old God intro beat), and the defeat line plays for the player who lands the killing blow. So the fights read with a proper dramatic open and close instead of jumping straight into the attack exchange. Translated into all four non-English languages in the same epic boss-fight register; the boss names and titles stay English (the game-wide monster-name layer).
Boss-dialogue localization: Secret Bosses
The final part of the boss-dialogue megapass. The four optional super-bosses -- the Ocean Philosophy lore encounters hidden at floors 25, 50, 75, and 99 (The First Wave, The Forgotten Eighth, Echo of Self, The Ocean Speaks) -- carried all their text as hardcoded English: the intro narration that sets each scene, the pre-fight dialogue, the battle cry, the long victory narration that delivers the lore payoff, and the four philosophical choices the Forgotten Eighth asks. 122 strings localized via accessors on the secret-boss data type (LocIntro / LocBattleCry / LocPreDialogue / LocVictory / LocChoiceOptions, keyed secretboss.{boss}.*), with every display site routed through them -- including the battle cry that doubles as the monster's combat phrase. The four choice options translate safely because the choice is selected by number and graded by position, not by matching the text. Translated into all four non-English languages in the mythic, bittersweet register the encounters are written in; the god name "Manwe" and the quoted names of the collectible lore fragments stay English (matching the rest of the still-English lore layer).
This completes the boss-dialogue megapass (Old Gods + world bosses + secret bosses), the largest single block of the localization backlog.
Cleanup pass: backlog cleared
The two small leftovers after the megapass. The Anchor Road challenge hub's graphical-client (Electron) menu had seven labels (Bounty, Gang War, Gauntlet, Claim Town, Flee Control, Status, Prison) still hardcoded in English; they now reuse the same localized keys the text and screen-reader menus already use, so the graphical client renders them in the player's language (no new translations needed -- those keys were already translated).
The monster-family lore blurbs (the paragraph of background for Goblinoids, Undead, Dragons, and so on) were audited and deliberately left as-is: they are not shown to players anywhere in the game. Combat identifies a creature by its family name (which stays English, like all monster names), but the lore paragraph itself is only used by the modding editor and the moddable-data export. Translating text no player ever reads would just be dead weight, so it was skipped (and noted for the future, in case a bestiary screen is ever added).
With that, every player-facing surface from the localization-debt inventory taken at the end of v0.61.6 is resolved. The content that is still English by design -- proper names of monsters and bosses, and the world news feed (whose entries are written to shared world state already rendered to a string) -- is a separate, deeper architectural change, not part of this flavor-localization effort.
Rest dreams localized
A player report turned up a surface the v0.61.6 sweep had not catalogued: the dreams a character has while resting were still in English (the report named the one titled "The Eyes"). The whole dream system was hardcoded -- about forty narrative dreams, the half-dozen guilt nightmares that come from killing, and the fifteen atmospheric "visions" the dungeon shows you, each with a title, body, and a closing one-line thought. All of it now renders in the player's language: 375 strings localized via accessors on the dream and vision data types, with every place that shows a dream (resting at the Inn, at home, or camping in the dungeon, plus the dungeon visions) routed through them.
The guilt nightmares were the one tricky piece: they weave the name of someone you killed into the text at runtime. The name substitution now happens on the already-translated lines, so a Hungarian or Spanish player sees the nightmare in their language with the victim's name dropped into the right spot. God names, companion names, and the like stay English, consistent with the rest of the game.
Weekly-rank and rival login message localized
Another report: the rank message shown on login ("You moved up 9 ranks!" and "Your rival X is Level 9") was in English. The /health screen already showed these in the player's language, but the login-time announcement had been missed. It is now localized in all five languages, with proper singular/plural handling ("1 rank" vs "9 ranks") for the languages that need it.
Magic shop owner conversation localized
When you talk to Ravanella, the magic shop's owner, everything she says -- her greeting, her remarks about your class, her comments on your deeds and your alignment, and the somber scene where she explains and hands over a "corruption" fragment -- was hardcoded English. The whole conversation is now translated in all five languages. The race-based word she greets you with ("Welcome, traveler" / "Welcome, elf") is now localized too, so the greeting no longer comes out half-English. (One small fix folded in: the corruption scene said "He reaches beneath the counter" though Ravanella is female; it now reads "She".)
The shop's passive atmosphere lines -- the arcane hum, the rustling pages -- were already translated in an earlier update; that part just needs the server brought up to the current build.
Equipment slot names localized when gearing up teammates
When you equip a companion, spouse, lover, or team member, the equipment slot names (Main Hand, Off Hand, Head, Body, and so on) were showing in English. The shared slot-list display and the slot picker -- used by the Inn, Home, Team Corner, and the in-dungeon party menu -- now show the slot names in the player's language everywhere. A handful of small adjacent lines in the gear-up screen ("Current:", "Unidentified", "No items available for this slot", and the like) were tidied up to use the player's language too.
XP distribution screen localized
The party XP-split screen in the dungeon had several lines still in English -- the party roster rows ("You", "Companion", "empty"), the running total, and the "Auto-redistribute on death" toggle and its confirmation. These now display in the player's language.
Companion dungeon banter localized
Your companions chatter while you explore the dungeon -- idle observations (Aldric cleaning his blade, Vex rummaging for loot, Mira whispering a prayer), suggestions about which way to go next, and remarks when you double back through cleared rooms. All of it was hardcoded English. Every line for all five companions (Aldric, Vex, Lyris, Mira, Melodia) -- including the lines that only show up after a fight, deep in the dungeon, when you're hurt, or as Mira nears Veloura's floor -- now displays in the player's language, along with the direction words in their "let's head this way" suggestions.
Mana-siphon enchant message localized for companions
A weapon with the Siphon enchant restores mana on a hit. The message was translated when the player triggered it, but stayed English when a companion did. The companion version is now localized too.
Herb names localized
A player reported that herb names (Healing Herb, Ironbark Root, Firebloom Petal, Swiftthistle, Starbloom Essence) rendered in English in a localized session. The herb-garden / foraging system kept its names and effect descriptions as hardcoded English on the HerbData helper, so they showed English everywhere a herb was named: the combat herb pouch, the dungeon and home use-herb menus, the gather-herbs flow, the garden-upgrade unlock line, the Settlement Herbalist Hut, and the active-buff line on /health (which was the worst case -- it printed the raw enum name "HealingHerb" with no space). Only the wilderness foraging "Found: ..." lines were already localized, via their own dedicated keys. New HerbData.LocName / LocDescription accessors route every display site through herb.{id}.name / .desc keys with English fallback; the numeric effect bonuses are passed as format args so the surrounding prose can be reordered per language. Herb names are descriptive common nouns the player never types (selection is by number), so they translate safely. The translated names reuse the renderings already established for the wilderness foraging keys for consistency. 10 new keys in all 5 languages.
Wounded man dungeon event showed the gold reward as a chivalry gain (Hungarian/French)
A Hungarian player reported that the wounded man dungeon event told them they gained 3000+ chivalry. The code was correct -- it prints two separate lines (a gold reward and a chivalry gain) with two different keys and two different numbers -- but the Hungarian and French translations of the gold-reward key (dungeon.wounded_reward) had been copy-pasted from the chivalry-gain key, so both lines read "your chivalry increased by N" and the first N was actually the gold amount (~3000). The player never actually received that chivalry; only the displayed line was wrong. Fixed the two translations to proper gold-reward wording (Spanish and Italian were already correct). Data-only fix, no code change.
Monster stun abilities that lasted "one round" did nothing
A player reported that the Wild Boar's stun was nonexistent: "you get stunned in the enemy turn, then you can act again right after." This was real, and it affected seven monster abilities. The combat loop processes a character's status effects at the start of their turn -- which decrements every active effect's duration by one -- and only then checks whether they're still stunned. So a stun applied for 1 round (on the monster's turn) is decremented to zero at the very start of the player's next turn, before the can-act check ever sees it: the player loses no turn at all. To actually skip one of the player's turns, a stun has to be applied for 2 (this off-by-one is already documented and compensated for in the player's own stun abilities). Nine of the game's stun abilities already used 2; seven used 1 and were therefore no-ops: Crushing Blow (the boar), Boulder, Lightning, Earthquake, Engulf, Tentacle Grab, and Whirlpool. All seven are now 2, so their stun skips exactly one of your turns, matching the abilities that already worked. The off-by-one is now commented at each site so it doesn't get "simplified" back to 1.
Lifedrinker (and Siphon) enchants on armor and accessories stopped working
A player reported their Lifedrinker no longer procs despite a high enchantment total in it. Lifedrinker (life steal) and its mana-stealing sibling Siphon can be enchanted onto any gear slot -- weapon, shield, armor, rings, amulet -- and were always designed to add up across everything you wear. A v0.60.10 fix that stopped a dual-wielded off-hand enchant from incorrectly proccing on main-hand swings went too far: it changed combat to count only the weapon actually swinging, which silently zeroed every Lifedrinker and Siphon enchant on armor and accessories. A player who spread the enchant across their gear (the natural way to build "a high total") suddenly got nothing. Both enchants now sum across all your gear again, while still keeping the dual-wield rule: when you wield two weapons, each weapon's leech only procs on its own swing (a shield or empty off-hand is passive and always counts). The per-hit and total life-steal caps are unchanged.
Married but unable to interact with, re-equip, or adventure with the spouse (online)
A player reported being married but unable to do anything with their spouse at Home -- no conversation, no equipment changes, no taking them into the dungeon. The cause was a stale link between the marriage record and the live spouse. Every place that needed the spouse looked them up by a stored id, and if that id no longer matched any living townsperson the spouse silently dropped out of every menu at once -- which is exactly what the player saw. The id could go stale a couple of ways: a wedding performed when the partner happened to be off-screen recorded the partner's name where an id belonged, and some older saves restored townspeople under a slightly different id than the one the marriage was filed under. The spouse lookups now fall back to matching by name when the id doesn't resolve, so an existing marriage reconnects to the right person on next login -- restoring conversation, equipment management, and bringing them along to the dungeon. The same fix covers lovers and applies across Home, the Love Street date flow, the dungeon party screen, and the character sheet's partner line.
Druid's Shrine pilgrimage could be spammed (no cooldown enforced)
A player reported that the Druid's Shrine pilgrimage could be repeated without waiting for its cooldown. The pilgrimage is meant to be a once-per-attunement-period choice -- you attune to one shrine, the buff lasts a day, and each visit adds favor toward milestones (the 10-favor milestone grants a permanent stat reward). But the menu only showed the active attunement; it never actually stopped you from re-attuning, so you could pick a shrine over and over, re-applying the buff and racking up favor far faster than intended -- reaching the permanent-reward milestones on every shrine in minutes. The menu now blocks a new pilgrimage while your current attunement is still active, showing how long remains before you can attune again. (The shrine list still displays so you can check your favor.)
Files changed
Scripts/Core/GameConfig.cs-- version bumped 0.61.6 -> 0.61.7.Scripts/Data/BeastData.cs--LocEncounterFlavor/LocTameSuccessFlavor/LocPassiveDescriptionaccessors readingbeast.{id}.*with English fallback.Scripts/Locations/WildernessLocation.cs/Scripts/Locations/HomeLocation.cs-- beast encounter / tame / passive display routed through the accessors.Scripts/Data/WildernessData.cs--GetForagingText/GetRuinsEncounter/GetTravelerText/GetTravelerNameaccessors readingwilderness.forage|ruins|traveler.{region}.{i}with English fallback.Scripts/Locations/WildernessLocation.cs-- foraging / ruins / traveler display sites pick an index and render via the accessors; traveler role label localized in the talk-branch templates.Localization/*.json-- 80 new keys (24beast.*+ 56wilderness.forage|ruins|traveler.*) in all 5 languages.Scripts/Data/RiddleDatabase.cs--LocText/LocAnswer/LocAlternates/LocHintaccessors on the riddle type readingriddle.{id}.*with English fallback;CheckAnsweraccepts both the English and localized answer sets; riddle text / hint whisper / failure-answer reveal routed through the accessors.Localization/*.json-- 377 newriddle.{id}.*keys (text / answer / alternates / hint for 51 riddles) +riddle.whisper_hintchrome in all 5 languages (wordplay/letter riddles adapted per-language to stay solvable).Scripts/AI/PersonalityProfile.cs-- newSyncOrientationToGender(); orientation roll rebalanced (~85/8/6/1 straight/gay-lesbian/bi/pan).Scripts/Systems/NPCSpawnSystem.cs-- sync called at template spawn + immigrant generation;EnsureOrientationDiversity/NudgeLateJoinerOrientationuse a proportional floor (DiversityTarget, ~4% per category, min 3) and the nudge chance raised to 80%.Scripts/Systems/FamilySystem.cs-- sync called at child coming-of-age.Scripts/Systems/WorldSimService.cs/Scripts/Core/GameEngine.cs--SyncOrientationToGender()heal applied to each NPC on world load (online + single-player) so existing mislabeled NPCs self-correct.Scripts/Locations/BaseLocation.cs--InteractWithNPCexits the per-NPC menu after the full visual-novel conversation ends (stayInConversation = false), so leaving a conversation is a single0instead of backing out through a redundant nested menu.Scripts/Data/OldGodsData.cs-- newLocKeyfield +LocIntro/LocPhase2/LocPhase3/LocDefeat/LocLoss/LocSaveaccessors onOldGodBossDatareadingoldgod.{god}.{section}.{i}with English fallback; Noctura betrayal definition setsLocKey = "noctura_betrayal".Scripts/Systems/OldGodBossSystem.cs-- the boss-intro phrase, save dialogue, defeat dialogue, and the betrayal-fight intro/phrase/defeat/loss display sites routed through the Loc* accessors.Scripts/Systems/CombatEngine.cs--PlayBossPhaseTransitionrenders Old God phase-2/phase-3 dialogue viaLocPhase2()/LocPhase3(); hardcoded phase-transition flavor localized viacombat.boss_phase2_flavor/combat.boss_phase3_flavor.Localization/*.json-- 314oldgod.{god}.{section}.{i}keys (7 gods + Noctura betrayal) + 2combat.boss_phase*_flavorkeys in all 5 languages.Scripts/Data/WorldBossData.cs--LocSpawn/LocPhase2/LocPhase3/LocDefeat+LocAbilityName/LocAbilityDescaccessors onWorldBossDefinitionreadingworldboss.{id}.*with English fallback (FindAbilitylocates an ability by phase+slot).Scripts/Systems/WorldBossSystem.cs-- ability-use line, ability description, and phase-transition dialogue routed through the accessors; spawn narration now shown at engage and defeat narration shown to the killing-blow player (both arrays were previously authored-but-unused).Localization/*.json-- 136worldboss.{id}.*keys (4 dialogue arrays + per-phase ability name/desc for 8 bosses) in all 5 languages.Scripts/Data/SecretBosses.cs-- newLocKeyfield (set per boss) +LocIntro/LocBattleCry/LocPreDialogue/LocVictory/LocChoiceOptionsaccessors readingsecretboss.{boss}.*with English fallback; the intro/dialogue/battle-cry/victory/choice display sites and the combat-monsterPhraserouted through them; reward/"speaks" chrome localized (secretboss.reward_xp/reward_gold/speaks_label/press_begin). The internalAbilitiesarray (never displayed) left as-is.Localization/*.json-- 122secretboss.*keys (intro/predialogue/victory/choice/battlecry for 4 bosses + 4 chrome) in all 5 languages.Scripts/Locations/AnchorRoadLocation.cs-- the 7 hardcoded-English Electron menu labels (EmitElectronEvents) now reuse the existing localizedanchor_road.*SR/visual keys. No new loc keys. (MonsterFamilies.cslore Descriptions audited and left unlocalized -- no player-facing display path.)Scripts/Systems/DreamSystem.cs--LocTitle/LocContentLines/LocHintTextaccessors onNarrativeDreamData(keyeddream.{Id}.title|content.{i}|hint) andLocDescription/LocContentLinesonDungeonVision(keyedvision.{Id}.desc|content.{i}), with English fallback; newWithVictimSubstitutedresolves localized text then applies the{VICTIM}runtime substitution into private_resolved*overrides;GetNightmareuses it.Scripts/Locations/DungeonLocation.cs/Scripts/Locations/InnLocation.cs/Scripts/Locations/HomeLocation.cs-- all 5 rest-dream display sites + the dungeon-vision site route through the Loc* accessors.Localization/*.json-- 375 keys (308dream.*for ~43 dreams + 6 nightmares, 67vision.*for 15 visions) in all 5 languages; the 4 nightmare{VICTIM}lines preserve the token.Scripts/Core/GameEngine.cs-- the login-time weekly-rank change + rival lines route through 5 newengine.rank_moved_up_one|_many/engine.rank_dropped_one|_many/engine.rival_levelkeys (singular/plural split)./healthrank+rival display was already localized.Localization/*.json-- 5engine.rank_*/engine.rival_levelkeys in all 5 languages.Scripts/Locations/MagicShopLocation.cs--TalkToOwnerEnhanced+ShowCorruptionFragment+GetRaceGreetingrouted throughmagic_shop.talk_*/magic_shop.corrupt_*/magic_shop.race_greeting.*/address_dreamerkeys; corruption-scene pronoun "He"->"She" (Ravanella is female). Visual shop menu labels still hardcoded English -- flagged for a separate UI pass.Localization/*.json-- 43magic_shop.*conversation keys in all 5 languages ({0}/{1}args preserved; "Wave Fragment - The Corruption" name +(F)hotkey kept literal).Scripts/Locations/BaseLocation.cs--DisplayEquipmentSlotWithStatsandPromptForEquipmentSlot(shared by Home/Inn/TeamCorner/Dungeon equip flows) derive slot names fromGameConfig.GetLocalizedSlotName(slot)instead of caller-passed English labels.Scripts/Locations/HomeLocation.cs-- 5 adjacent equip-flow strings wired tohome.no_items_slot/home.must_identify/home.item_cursed/ui.unidentified/ newhome.equip_current.Localization/*.json-- 1 newhome.equip_current("Current:") in all 5 languages (the other 4 keys already existed). Decurse rename ("Cursed"->"Purified") investigated and left as-is: it operates on the English item-name layer and is language-independent (not a localization bug).Scripts/Locations/DungeonLocation.cs--ShowXPDistributionMenuparty-row labels, total line, and auto-redistribute toggle/confirmation routed through 9 newdungeon.xp_*keys.Localization/*.json-- 9dungeon.xp_label_*/dungeon.xp_total/dungeon.xp_auto_redist*/dungeon.xp_you/dungeon.xp_empty_namekeys in all 5 languages.Scripts/Systems/CompanionSystem.cs--GetCompanionIdleCommentbuilds its per-companion pool fromcompanion.idle.{comp}.*loc keys (incl. afterCombat/depth/HP/gold/Veloura-conditional lines) instead of hardcoded English.Scripts/Locations/DungeonLocation.cs--TryCompanionNavigationComment(with localizedcompanion.dir.*direction) andTryCompanionBacktrackCommentroute throughcompanion.nav.*/companion.backtrack.*keys.Localization/*.json-- 111companion.*keys (idle/nav/backtrack/dir/generic_name) in all 5 languages;{0}direction arg preserved in the 16 nav keys; 2 source em-dashes normalized to--.Scripts/Systems/CombatEngine.cs-- mana-steal enchant proc's teammate branch routed through newcombat.tm_enchant_siphon(was hardcoded English; player branch was already localized).Localization/*.json-- 1combat.tm_enchant_siphonkey ({0}=name, {1}=mana) in all 5 languages.Scripts/Core/Character.cs--HerbDatagainsGetLocKey(key stem perHerbType) +LocName(readsherb.{id}.name) +LocDescription(readsherb.{id}.desc, passing the numeric bonuses as format args); the EnglishGetName/GetDescriptionswitches kept as source/fallback.Scripts/Systems/CombatEngine.cs-- combat herb-pouch [J] menu name+description routed throughLocName/LocDescription(source em-dash separator normalized to--).Scripts/Locations/HomeLocation.cs-- gather-herb rows, pouch-full / gathered lines, active-buff line, use-herb [J] menu rows, apply-effect confirmation name, and garden-upgrade-unlock line all routed throughLocName/LocDescription(one source em-dash separator normalized to--).Scripts/Locations/BaseLocation.cs--/healthactive-herb-buff line now usesHerbData.LocName(...)instead of the raw enum.ToString()(fixes "HealingHerb" with no space, and localizes it).Scripts/Locations/SettlementLocation.cs-- Herbalist Hut max-carry / received name + description routed throughLocName/LocDescription.Localization/*.json-- 10 newherb.{id}.name|.desckeys (5 herbs) in all 5 languages; names reuse the wilderness foraging renderings, descriptions take format args for the numeric bonuses.Localization/hu.json/Localization/fr.json--dungeon.wounded_reward(the wounded-man gold-gift line) was a copy-paste ofdungeon.chivalry_increase, so the gold amount rendered on a "your chivalry increased by N" line; re-translated to a gold-reward sentence (single{0}= gold preserved). en/es/it were already correct. Cosmetic/display-only -- the actual gold and chivalry awarded were always correct.Scripts/Systems/MonsterAbilities.cs-- bumpedStatusDuration1 -> 2 on the seven Stunned-inflicting abilities that were no-ops (CrushingBlow, Boulder, Lightning, Earthquake, Engulf, TentacleGrab, Whirlpool);ProcessStatusEffectsdecrements at the start of the target's turn before the can-act check, so a 1-round stun never skips a turn (effective skip = duration - 1). The nine abilities already at 2 (incl. the v0.61.5-tuned Giant Spider WebTrap and Frozen) are unchanged. Each fixed site carries an inline "+1 for ProcessStatusEffects off-by-one" comment.Scripts/Core/Character.cs-- newGetEffectiveLifeStealPercent(weaponSlot)andGetEffectiveManaStealPercent(weaponSlot)helpers: sum LifeSteal/ManaSteal across every equipped slot (Lifedrinker/Siphon are enchantable on all slots and stack), excluding the opposite hand's weapon only when dual-wielding (preserves the v0.60.10 per-hand rule; a shield/empty off-hand is passive and always counts). Lifesteal capped atMaxEquipmentLifeStealPercent. The summedGetEquipmentLifeSteal()is left in place (no longer the combat read).Scripts/Systems/CombatEngine.cs--ApplyPostHitEnchantmentslifesteal block now readsattacker.GetEffectiveLifeStealPercent(weaponSlot)instead of only the swinging weapon'sLifeSteal(removed the now-unusedsourceWeaponlocal and thesourceWeapon != nullguard so armor-only lifesteal procs);CheckElementalEnchantProcsmana-steal now readsattacker.GetEffectiveManaStealPercent(weaponSlot)instead ofweapon.ManaSteal. Elemental enchant flags (fire/frost/etc.) still read the source weapon (correctly weapon-bound). The deadCheckElementalEnchantProcsMonster(no callers) was left as-is.Scripts/Systems/NPCSpawnSystem.cs-- newResolvePartnerNpc(npcId, npcName)(instance, over ActiveNPCs) + staticResolvePartnerNpc(pool, npcId, npcName)overload: matches a romance record to a live NPC byCharacter.IDfirst, then falls back to a case-insensitive display-name match (Name2/Name1, preferring a living NPC), trying both the cachedNPCNameand the storedNPCIdas name candidates. Rescues spouses/lovers whose stored id drifted (Love-Corner name-as-id fallback records, or legacy empty-CharacterIDrestores that collapsed tonpc_<name>). ID match always wins, so a correct record is never overridden.Scripts/Locations/HomeLocation.cs-- all 16 spouse/lover NPC lookups (family display, partners-at-home, spend-time, and the equip-spouse/lover flows incl. theallWorldNPCspath) route throughResolvePartnerNpcinstead ofActiveNPCs.FirstOrDefault(n => n.ID == record.NPCId).Scripts/Locations/DungeonLocation.cs-- spouse and lover party-join resolution route throughResolvePartnerNpc(resolve first, then apply the existing alive/not-dead/not-imprisoned/not-already-in-party filters).Scripts/Locations/LoveStreetLocation.cs-- spouse/lover date-target lookups route throughResolvePartnerNpc.Scripts/Locations/BaseLocation.cs-- the/healthpartner-name lookup routes throughResolvePartnerNpc.- (Source note:
LoveCornerLocationstill records a raw display name into NPCId in its NPC-not-found fallback, but the resolver now reconnects such records by name, so they no longer leave the spouse unreachable. Not changed to avoid regressing offline/player-spouse marriages. Pop-cap culling of a married NPC -- where the spouse isn't in the world at all -- is a separate concern the name fallback can't address.) Scripts/Locations/WildernessLocation.cs--ShowPilgrimageMenunow gates the attune flow on!currentPlayer.HasActiveShrineAttunement: while an attunement is active it shows the shrine list (favor reference) plus a cooldown line with time remaining and returns, instead of letting the player re-select and re-attune. Closes the exploit where every re-attune re-applied the buff and incrementedShrineFavor(fast-farming the 10/25/50 favor milestones, milestone 10 being a permanent stat grant). The attune chokepoint is this single menu, so one gate covers all entry paths.Localization/*.json-- 1 newwilderness.pilgrimage_cooldownkey ({0} = time-remaining label) in all 5 languages.