Major accessibility overhaul: redesigned menus, column painting, info cards, DLC support, and dozens of fixes#106
Draft
aaronr7734 wants to merge 213 commits intoAccessMods:masterfrom
Draft
Major accessibility overhaul: redesigned menus, column painting, info cards, DLC support, and dozens of fixes#106aaronr7734 wants to merge 213 commits intoAccessMods:masterfrom
aaronr7734 wants to merge 213 commits intoAccessMods:masterfrom
Conversation
Add a complete multi-select system that lets blind players select multiple pawns and issue group commands, eliminating the need to individually select and command each pawn one at a time. Selection mechanics: - Alt+Shift+Left/Right: contiguous selection (extend to adjacent pawns) - Alt+Space: toggle individual pawns in/out of selection - Alt+Ctrl+Space: select all colonists / clear all selection - Alt+Ctrl+F1-F5: save selection to persistent group (survives save/load) - Alt+F1-F5: recall saved group Navigation in multi-select mode: - Comma/period, Alt+Left/Right, Alt+1-0, Alt+Up/Down all move focus without changing the selection set - Camera does not follow focus navigation - Focused pawn announced with selected/not-selected status and job - Ctrl+Alt reorder blocked during multi-select Group commands: - R key drafts/undrafts using vanilla InheritInteractionsFrom behavior (only toggles pawns with same state as first pawn) - G key always shows selected pawns' gizmos in multi-select mode - Gizmo grouping via GroupsWith/MergeWith mirrors vanilla GizmoGridDrawer - Gizmo execution propagates to grouped gizmos via InheritInteractionsFrom - Right bracket (]) context menu works automatically via Find.Selector - "Go here (formation)" option added for line formation movement Line formation placement: - Two-point placement with Space bar (first point, second point) - Enter to confirm, Escape to cancel - Pawns distribute evenly along the line in colonist bar order - Uses RCellFinder.BestOrderedGotoDestNear for valid destinations Action feedback (job-diff system): - Snapshots pawn jobs + queue counts before action, compares after - Announces using shorter-list logic: "Everyone drafted" / "Everyone except Bob, Sarah drafted" / "Only Carol, Dave drafted" - Detects targeting mode activation for attack commands - Post-targeting summary in TargetingPatch for Squad Attack Pawn info shortcuts with multi-select: - Alt+H/M/N/K/G/B: cursor pawn takes priority, then pawn picker menu - Alt+C: pawn picker menu for camera jump - Menus support typeahead search Persistent groups (MultiSelectGroupComponent): - GameComponent with 5 slots, auto-discovered by RimWorld - Saves/loads pawn references via Scribe_Collections LookMode.Reference - Filters to current map on recall, announces unavailable pawns Localization: - Uses game translation keys where available (GoHere, Everyone) - Properly strips XML tags via implicit string cast on TaggedString
…ment Replace manual line distribution math with the game's own controller, which handles duplicate-cell prevention, mech command range checks, exit map handling, and proper job creation via PawnGotoAction.
- Change permadeath from toggle to two radio button options (Up/Down) - Add MenuHelper for navigation (respects WrapNavigation setting) - Add TypeaheadSearchHelper for storyteller and difficulty search - Add Home/End navigation for all three sections - Add position announcements (X of Y) - Auto-select first item on first visit to each section - Simplify mode announcements (removed verbose help text)
Add accessible custom difficulty settings navigation during character creation. When selecting "Custom..." difficulty, press Enter to open a 2-level menu for editing all difficulty settings. Features: - Navigate sections with Up/Down, Enter to drill into settings - Adjust sliders with Left/Right arrows - Toggle checkboxes with Enter/Space - Typeahead search in both sections and settings - Alt+R to jump directly to playstyle reset section - Escape to go back or exit to difficulty selection Refactored difficulty settings into shared DifficultySettingsHelper used by both character creation and in-game storyteller selection, removing ~550 lines of duplicate code.
- Add MapSize and StartingSeason to unified field menu with (Advanced) label - Sync slider values from game on init (fixes navigation starting from wrong position) - Use MenuHelper for navigation respecting user settings - Add TypeaheadSearchHelper for field search - Add Home/End navigation - Support all 7 slider values for Rainfall/Temperature/Population/LandmarkDensity - Add dev mode options: 5% coverage with (dev) marker, extra map sizes - Use game translation strings for all labels and warnings - Add warnings for 100% coverage, large maps, and winter start - Values clamp instead of wrap
When using PageUp/PageDown to cycle through pawns in the scanner, the announcement now includes the pawn's current activity (e.g., "cooking four lavish meals", "sleeping"). Respects the existing ShowPawnActivityOnMap setting.
- Add FactionsNavigationState for faction list and add menu navigation - Tab/Shift+Tab toggles between World Params and Factions sections - Up/Down/Home/End navigates faction list with typeahead search - Alt+A opens add faction menu, Delete removes selected faction - Faction announcements include full description with xenotype info - Block Enter/Escape appropriately to prevent unintended page navigation - Fix storyteller screen to show position on initial entry
When the cursor moves to a door or when cycling through doors in the scanner, the announcement now includes whether the door is open or closed (e.g., "wooden door (open)" or "autodoor (closed)").
- Add fish species and population to key 2 (terrain info) when Odyssey DLC is active, matching what sighted players see in the mouseover readout - Add colons after stat labels in terrain info (beauty:, cleanliness:, path cost:) - Update light info (key 4) to show percentage with translated label (e.g., "light: 50% (Lit)") matching sighted player display - Add temperature label to light info for consistency
- Create FishingZoneMenuState for keyboard navigation of fishing zone settings - Support repeat mode, target count, minimum population, and fish species list - Add tooltips from game UI for fish population and minimum population fields - Integrate with inspection system via TabRegistry and InspectionTreeBuilder - Register in KeyboardHelper to properly block conflicting keys - Add InfoCardState check to yield control when viewing fish info cards - Use rounded fish population values for consistency with game display
The game plays a sound when drafting and undrafting pawns via the UI. Now the mod's R key shortcut plays the same sound.
Previously, activating a Dialog_NodeTree option that navigates to a sub-dialog (like 'Request trade caravan' -> trader type selection) would immediately close the dialog instead of showing the sub-menu. Now correctly checks DiaOption's resolveTree, link, and linkLateBind fields to determine whether to close the dialog or refresh to show the new dialog node's options.
…controls Ability Targeting: - When targeting a psycast, announces ability name, range, AOE radius, psyfocus cost, and neural heat - Press R during targeting to check distance to cursor and line of sight status - Press T during targeting to hear which pawns are in the area of effect (AOE abilities only) - Clear error messages for out of range, no line of sight, psychic immunity, and missing targets - Support for two-phase abilities like Skip (target selection then destination selection) - World map targeting support for abilities like Farskip Neural Heat Gizmo: - Renamed "Psychic Entropy" to "Neural Heat" (the player-facing term) - Gizmo now shows limiter state: "Neural heat: 0/80, Psyfocus: 39%, Limiter: ON" - Press Enter on the gizmo to toggle the neural heat limiter on/off Ability Gizmo Improvements: - Psycast gizmos now announce their costs when browsing: "Vertigo pulse (M). Costs 2% psyfocus, requires 50%, Neural heat: 30" - Shows both the psyfocus cost (consumed when casting) and minimum required (band threshold) Bug Fixes: - Fixed rich text tags appearing in letter/message announcements (e.g., "(*Name)Mikaela(/Name)" now shows as "Mikaela") - Fixed targeting using mouse position instead of accessibility cursor position
…criptions Animal Attack Target (Odyssey DLC): - Announce range from master when entering targeting mode - Press R during targeting to check distance to cursor and range status - Pre-validate range before executing, with clear error on out-of-range - Keep targeting open on range failure so user can adjust cursor and retry - Detect attack commands by icon match against game's AttackTargetTexture - Use game's Pawn_TrainingTracker.AttackTargetRange const for range value Ability Gizmo Descriptions: - Psycast gizmos now include the spell description after name and cost - Pull description from ability.def.description instead of Command.Desc (which is only populated during mouse hover rendering) - Reorder announcement: name, hotkey, cost, then description Dialog Tree Navigation: - Fix dialog option close logic to not depend on resolveTree flag
…and destination phase tracking
- Detect all ability verbs via IAbilityVerb interface (not just Verb_CastAbility),
supporting Verb_AbilityShoot and modded ability verbs automatically
- Add self-cast feedback: abilities with targetRequired=false now announce
"Casting {name}" instead of producing no feedback
- Track destination phase for dual-target abilities (Skip): R key reports
distance from selected target using destination comp's range
- Handle touch/zero-range abilities: announce "Touch range" instead of
misleading range values, skip range pre-validation
- Add range and effect radius to ability gizmo descriptions (after cost,
before description), with world map and self-cast variants
- Add affected pawns announcement for world-targeting AOE abilities (Farskip)
- Fix location-targeting AOE abilities (Solar Pinhole) showing misleading
"No pawns in radius" on target confirmation
- Use verb.EffectiveRange for range calculations (respects equipment bonuses)
- Separate cost stats with periods for natural screen reader pauses
- Move hotkey to end of ability announcements
- Add animal attack range to gizmo description
- Clean up stale I key documentation from Abilities CLAUDE.md
Check if announcement already ends with a period before appending period-separated sections for attack range and ability info.
Toggle gizmos previously only announced label and ON/OFF state. Now includes the tooltip description that sighted players see on hover, giving screen reader users the same context (e.g., "Animals attack: OFF. While this is on, mastered animals are sent forth to attack distant targets. While it is off, they remain near and guard the master.").
- Add Predator column and sort predators to top (closes AccessMods#74) - Replace mod-added columns (Age, BodySize, Health, Pregnant) with vanilla columns (ManhunterOnDamage, ManhunterOnTameFail) - Add column tooltips announced only on left/right navigation, not up/down, for both wildlife and animals menus - Add jump-to-animal on Enter for wildlife Name column - Fix Hunt/Tame columns showing empty text by using Yes/No translations
… tree enrichments Add Alt+I keyboard shortcut across all major menus and states to open info cards for the currently selected item. This brings RimWorld's hyperlink-based info card system to screen reader users who previously had no way to access it. Info card access points (15 contexts): - Map cursor: opens info card for thing/terrain at cursor position, with float menu selection when multiple things occupy the same cell - Architect menu: opens info card for selected building designator - Plant selection menu: info card for selected plant def - Storage settings: info card for selected ThingDef filter item - Bills menu: info card for selected bill's product - Bill config: info card for the bill's produced item - Gizmo navigation: handles Command_Ability (ability def), Designator_Build (building def with stuff), and fallback to owner - Colony inventory: info card for selected inventory item - Research menu: info card for selected research project - Research detail: info card for project, unlocked items (things/recipes) - Colony animals menu: info card for selected animal - Wildlife menu: info card for selected wild animal - Float menus: extracts Def from shownItem/iconThing/revalidateClickTarget - Info card itself: nested info cards via vanilla's hyperlink system Nested info card navigation: - State stack (SavedCardState) preserves cursor position, expansion state, and visible items when drilling into a linked def - Escape pops back to the outer card; final Escape closes entirely - Multi-hyperlink stat entries present a float menu for selection - closingFromAccessibility flag prevents PostClose from interfering with stack-managed transitions - onlyOneOfTypeAllowed set to false to allow multiple Dialog_InfoCard instances on the WindowStack simultaneously Info card tree improvements: - Stat entry labels now include hyperlink def names inline (sighted users see clickable links; screen reader users now hear the names) - "Inspectable" hint appended to announcements for stat entries that have hyperlinks, guiding users to press Alt+I - Stat expandability checked upfront via GetExplanationText; stats with no explanation are marked non-expandable instead of showing "No items to show" on expand - Empty-children edge case now corrects IsExpandable dynamically Typeahead search fix (all menus): - Alt+key combos no longer accidentally trigger typeahead search input - Added !Event.current.alt guard to ~15 typeahead handlers across UnifiedKeyboardPatch, BuildingInspectPatch, StorageSettingsMenuPatch, PlantSelectionMenuState, WindowlessFloatMenuState, and others - Info card typeahead switched from ev.character to KeyCode-based input (matching all other menus), with progressive backspace deletion and Up/Down match navigation during active search Pawn data improvements: - Xenotype genes now carry GeneDef reference for future info card use - Melanin skin color genes get descriptive shade names (very light, light, fair, medium, tan, brown, dark brown) based on luminance calculation, replacing the generic "Skin color" label - Health capacity tooltips now use HealthCardUtility.GetPawnCapacityTip (showing impactors: hediffs, body parts, genes) instead of the always-empty capacityDef.description - Capacity tooltip text split into individual tree lines per impactor - Skill passion labels changed from * / ** to readable text: "(Minor passion)" / "(Major passion)" Permits system overhaul (Royalty DLC): - Shows ALL permits per faction matching vanilla's PermitsCardUtility layout, not just the pawn's granted permits - Status reflects actual state: Granted, Granted (on cooldown), Available (X points), Locked (requires prerequisite/title) - Adds current title, unused permit points, and royal favor per faction - Required title shown in permit detail expansion Bug fixes: - Zone rename category comparison uses literal "Rename" instead of translated string (fixes potential locale mismatch) - Removed duplicate MenuHelper.GetLevelSuffix call in research detail - Research detail announcements trim trailing punctuation before appending state/position info - BillsMenuState passes ProducedThingDef to FloatMenuOption for info card extraction - KeyboardHelper.IsBlockingPanelActive includes InfoCardState - StorageSettingsMenuPatch returns early when InfoCardState is active - ArchitectMenuPatch skips input when InfoCardState is active - InfoCardDataExtractor extracts worldObject, hediff, titleDef, faction, and stuff fields for comprehensive title generation - InfoCardTreeBuilder generates proper titles for WorldObject, Hediff, AbilityDef, RoyalTitleDef, Faction, and ThingDef+stuff combinations
Apply the same skin color descriptors (very light, light, fair, medium, tan, brown, dark brown) from InfoCardDataExtractor to the unborn baby gene tree. Skin colors now route through a dedicated DescribeSkinShade method using perceptual luminance (0.299r + 0.587g + 0.114b) instead of the generic brightness-based labels (medium-dark, etc.). Hair and other cosmetic colors retain their existing hue-based descriptions.
Sighted players see fertility in the mouse-over tooltip but it was missing from the key 2 terrain announcement. Now shows fertility right after the terrain name, e.g. "Rich soil (140% fertility)".
- Move pregnancy approach menu after Relationship line instead of end - Use game's i18n methods (GetLabel/GetDescription) for pregnancy approach - Add CanEverProduceChild check with translated reason - Consolidate duplicate certainty into single item with change rate - Use translated labels (IdeoRoles, NoRoleAssigned, Effects, Certainty) - Fix cursor jumping after role/pregnancy actions via parent walk-up - Allow ITab_Genes through Hidden tab filter for gene inspection - Add Alt+I to open info cards for gear, hediffs, and genes - Show "Inspectable." suffix on items with available info cards - Set LinkedDef on gene tree nodes for info card navigation
…tech DLC) Integrates the Biotech DLC's "Try Romance" feature into the accessible Social tab tree with keyboard navigation. Viable targets show success chance percentages, Enter initiates romance, and Alt+I opens a factor breakdown via StatBreakdownState. Gated behind Biotech DLC, pawn eligibility, and Full inspection mode. Includes duplicate job guard and Dialog_MessageBox passthrough for relationship warning dialogs.
Rearchitect starting site selection to share the same navigation experience as the in-game F8 world map. World gen now supports the scanner, Z search, number keys 1-5, 3D compass navigation, and biome descriptions announced on biome change. - Add WorldNavContext enum (InGame/WorldGen) to WorldNavigationState - Add BiomeDescriptionTracker for MUD-style biome descriptions - Add StartingSiteContext for world-gen-only features (I-menu, R random, Ctrl+arrows biome jump, faction warnings, tile validation) - Rewrite StartingSitePatch to route through shared WorldNavigationState - Add context guards to caravan/quest methods (InGame only) - Relax ProgramState.Playing checks for scanner search and tile info keys - Guard EARLY BLOCK and F8 handler with InGame context - Remove StartingSiteNavigationState (migrated to shared system) - Remove dead code: CycleToNext/PreviousSettlement, CheckOffRoadOrRiver, wasOnRoad/wasOnRiver fields, lastAnnouncedInfo field, BiomeDescriptionTracker.SetCurrentBiome, ValidateTileForSettlement
…ing filtering Replace static DefDatabase recipe query with vanilla's ingredient-aware filtering (PotentiallyMissingIngredients, Worker.AvailableReport, HasHediff) so the operations list dynamically shows/hides recipes based on available items on the map. Modernize HealthTabState with MenuHelper navigation (Home/End, wrapping), TypeaheadSearchHelper for recipe and body part lists, and streamlined announcements without redundant instructional text. Fix Enter key leak where ActivateAction continued running after OnActivate closed the inspection state, causing a spurious "No items to inspect" announcement.
…rgeting Items like sentience catalyst and mech serums use CompUsable/CompTargetable targeting which was silently ignored by the mod. Now announces targeting start using the game's own mouse-attached label text, provides error feedback on invalid targets, and handles multi-phase targeting (e.g., select colonist then select animal).
Gizmo navigation now supports two new interaction types accessible to
screen reader users:
- Right bracket on gizmos with RightClickFloatMenuOptions opens the
options in WindowlessFloatMenuState, mirroring vanilla's grouped gizmo
option merging from GizmoGridDrawer. Covers designators ("Designate
All"), Command_Hide subclasses, and MechanitorControlGroupGizmo.
- Enter on Gizmo_Slider subclasses (fuel, hemogen, etc.),
Gizmo_PruningConfig, and MechCarrierGizmo enters a slider adjustment
mode. The Heat and Psyfocus gizmo uses right bracket instead since
Enter already toggles the neural heat limiter. Left/Right arrows step
one increment, Shift+Left/Right steps 5x. Plays SoundDefOf.DragSlider
on each step to match vanilla audio feedback.
Announcements now include discoverability hints and the current
psyfocus target value alongside the existing heat/psyfocus status.
Also fixes input priority so WindowlessFloatMenuState takes keyboard
focus when opened over an active GizmoNavigationState.
- Reorder list item announcements to put content first, then type, then date, so screen reader users can stop listening once they've heard what they need. - Change Alt+L and Alt+M filter toggle announcements from "Letters filter on/off" to "Showing/hiding letters" and "Showing/hiding messages" for clarity. - Announce the Alt+L and Alt+M hotkey hints on tab entry so users know how to toggle filters. - Reorder tab switch announcements so the tab name is spoken first, then the current item, then the hotkey hint.
MinifiedThing overrides LabelNoCount to delegate to InnerThing, but does not override LabelNoParenthesis. The scanner used LabelNoParenthesis for clean announcements (no health/quality suffixes), so every minified item was announced as the generic "minified thing" from the MinifiedThing def — hiding Royalty monument markers, uninstalled beds, tables, and any other minified buildings from both the 'z' search and page navigation. Add a GetNoParenthesisLabel helper that unwraps MinifiedThing and returns the inner thing's label. Apply it in both ScannerItem Thing constructors and in RefreshLabel (which re-derives the label before every announcement and would otherwise clobber the constructor-set label).
Adds a Shift+T shortcut that announces the current time speed, actual vs target ticks per second, and percent of requested speed, mirroring RimWorld's internal TPS counter formula. When a combat threat forces the game to normal speed, the announcement includes a "slowed by threat" clause so the speed-name and TPS numbers don't look inconsistent. In-game messages are also emitted on both OFF-to-ON and ON-to-OFF transitions of TimeSlower.ForcedNormalSpeed, but only when the user's set speed is faster than Normal (otherwise the slowdown has no observable effect). Messages are auto-announced by the existing NotificationAccessibilityPatch. Also replaces hardcoded English labels in TimeAnnouncementState with RimWorld's vanilla translation keys where they exist (ClockTime, ClockDate, Weather, AM, PM, Period1Day/PeriodDays) so non-English players hear more of the announcement in their own language. Labels without vanilla keys (Season, Days passed, error strings) remain in English. TimeControlAccessibilityPatch exposes LocalizedSpeedName as an internal static helper so PerformanceAnnouncementState can reuse the single TimeSpeed-to-display-name mapping instead of duplicating the switch.
- Change PrismConfig from 16 bytes to 1 byte to match Prism v0.11+ header - Remove obsolete platformPointer field - Add debug logging for config version Fixes prism_init returning null context on all platforms.
fix: correct PrismConfig struct size for v0.11+ API
User-visible improvements:
* New "All" top-level category at the very top of the scanner. Lists
every scanner item on the map in one closest-first list. Useful for
"show me the closest thing of any kind near me right now."
* Every category also gets an "All" subcategory by default. Pressing
Ctrl+PgDn now lands on the All view of each category, and Shift+PgDn
drills into the specialized buckets when you want to filter further.
* Pawns are split by faction relationship: Colonists, Prisoners, Slaves,
Guests, Hostile, Player Mechs, Hostile Mechs. Raids during friendly
visits no longer mix raiders and visitors into one bucket. Visiting
traders, quest lodgers, and allied raid help all live in Guests.
* Mud, moss, riverbank, lava, volcanic rock, flesh, space, and many
other natural terrain types now show up in the scanner. The terrain
filter no longer relies on hardcoded English defNames — it uses
fertility and pathCost so DLC and modded terrain are caught
automatically.
* Dead pawns and destroyed items are now detected mid-navigation and
removed silently with an "Item no longer exists" notice, instead of
being announced as still alive until you switch categories.
* Standing on a rich-soil patch, in your bedroom, or on a stockpile
zone now correctly reads "here" instead of pointing miles away at
the geometric center of the area. Distance to area-backed items
uses the nearest cell.
* Multi-region terrain (e.g. 63 separate marble patches as one item)
now describes the specific area you're on as "10x10, here, area 1
of 63" — matching the format used when you Alt+PgDn through them —
instead of misleading totals like "290 tiles, here".
* Page Up/Down preserves your position when the list re-sorts. Moving
the cursor a few tiles or watching things shift positions no longer
shuffles the list and resets you to the closest item. You stay on
whatever you were looking at, and the next press advances normally.
* The list also re-sorts on every navigation press to catch moving
things (pawns, animals) updating their positions in real time. This
one is marked experimental in the code and may be reverted if it
feels worse during play.
* Sort tie-breaking is now stable, fixing a bug where two items at
exactly equal distance (e.g. rich soil and dandelions both 11 tiles
south) would swap places on every press, trapping the user bouncing
between them.
Refactor / code health:
* Extracted four new helpers from the scanner to eliminate duplication
and god-method clutter:
- ScannerLabelBuilder — label formatting (was duplicated 3x)
- ScannerDirectionHelper — compass math (was duplicated 2x)
- ScannerSearchEngine — generic match-type filter (was duplicated
4x across map/world × update/refresh)
- ScannerCategorySchema — declarative category structure +
ScannerBuckets lookup helper, replacing 150+ lines of manual
"new ScannerCategory(...) / new ScannerSubcategory(...)" boilerplate
* CollectMapItems is now driven by ScannerCategorySchemas.All, so
adding a new category is a one-line schema entry instead of editing
five places.
* Switched in-place List.Sort to OrderBy.ToList() in the cursor-aware
re-sort paths. List.Sort is documented as unstable, which is what
caused the tied-item bouncing bug above. OrderBy is stable.
* Added an AddTo helper that centralizes the "specialized + All"
pattern so every item added to a specialized subcategory also lands
in the category's All subcategory automatically.
The combat triage summary was recently expanded to list every capacity that wasn't at 100%, which produces noisy announcements when chronic or minor capacities are affected. Restore the previous behavior of showing only the three capacities that matter most for combat decisions — sight, manipulation, and moving — so the readout stays focused on actionable triage information.
Integrate the PositionalFootsteps mod into RimWorld Access as an event-driven spatial audio system. Pawns produce footstep sounds when entering new tiles via a Harmony Postfix on TryEnterNextPathCell, replacing the original polling MapComponent for better performance. Features: - Terrain-aware human footsteps (dirt, stone, wood, metal, carpet, bridge, water, snow) - Animal footsteps (light and heavy categories by body size) - Mechanoid footsteps - Stereo panning based on screen position relative to camera - Distance-based volume attenuation with near/mid/far field zones - Low-pass filter for distant sounds, reverb for enclosed rooms - Zoom-level volume scaling - Per-category volume sliders (human, animal, mechanoid) - Master "Enable Sound Effects" toggle for vanilla-experience players - All settings accessible via the keyboard-navigable options menu - 80 OGG sound files deployed as loose assets for ContentFinder Based on original work by OlegTheSnowman (https://github.com/OlegTheSnowman) Co-authored-by: OlegTheSnowman <OlegTheSnowman@users.noreply.github.com>
Unify terrain sound mapping using TerrainAudioHelper's 100+ defName dictionary instead of the footstep mod's 8 substring patterns. Metal tiles now get metal footsteps, snow/ice get snow footsteps. Add wall-based sound occlusion using RimWorld's region/room system: sounds are muffled through walls via low-pass filter and volume reduction, with open doors partially restoring clarity. Uses bounded BFS through regions (max 30) with per-tick listener room caching. Fix room reverb bug where openness calculation always produced values ≤1.0 but thresholds checked for ≥2.5, making Livingroom and StoneCorridor presets unreachable. Now uses room.CellCount directly. Unify cursor terrain sounds with the pawn footstep .ogg pool so both systems share the same sound files with room-aware reverb.
…stance controls - Scanner harvestable subcategories now require plants/trees to be fully mature (PlantLifeStage.Mature) instead of just past harvestMinGrowth - Mod list quick toggle (Space) and detail toggle now force-refresh the filtered list before announcing, fixing stale "Now on" announcements - Ctrl+Shift+Left/Right adjusts preset jump distance by 10 tiles
Wire up the existing FootstepPerformanceMode setting to cap footsteps at 18 per tick, prioritizing selected, drafted, and hostile pawns. Skip all processing for categories with volume set to 0%.
fix: ensure Alt+H reports healthy colonists clearly
TryEnterNextPathCell has early-return paths where the pawn doesn't actually move (door waiting, pawn collision, forbidden door). The postfix now compares position before and after to only trigger footsteps on actual tile changes.
Small mechs now sound lighter and tinnier while large mechs keep their deep rumble. Pitch scales inversely with body size using 0.9 * (4.0 / bodySize)^0.4, and a high-pass filter strips bass from smaller mechs (cutoff from 50Hz at size 4.0 to 400Hz at 0.3).
Play footstep sounds every 2nd tile entry instead of every tile to prevent audio overlap on fast-moving pawns. Interval may need further tuning based on playtesting and feedback.
Bind = and - to zoom in and out on the map. Play the game's DragSlider sound on every zoom step, and announce zoom tier (closest/close/middle/ far/furthest) when crossing into a new tier. Announce "Zoom limit" when already at min or max.
The previous step1.ogg and step2.ogg clips were loud and bassy. Replace them with a single lighter clip that gets pitched and filtered per-mech by body size at playback time.
…andling Rework the footstep wall-occlusion system to address three issues uncovered while using it: 1. No zoom coupling. Occlusion was identical at every zoom level, so a zoomed-out "radar" view still muffled pawns behind walls as aggressively as a zoomed-in tactical view. Now occlusion strength fades from full at Close tier to zero by the Middle/Far boundary (RootSize 13.8 to 42), so zooming out reveals distant pawns through walls while zooming in keeps the muffled-indoors feel. 2. Cursor-on-wall was degenerate. IntVec3.GetRoom() returns null for wall cells, and the old code early-returned 1.0 occlusion in that case -- meaning every pawn sounded fully un-occluded whenever the cursor landed on a wall, regardless of actual geometry. Now wall cells gather their cardinal-neighbor rooms and regions, so a shared wall lets the listener "hear both sides un-occluded" and an exterior wall still muffles distant outdoor pawns correctly. 3. Doorway reverb was wrong. Door cells are their own Region but RimWorld assigns them a Room that's often the larger connected room, so cursor on a doorway between a tiny bedroom and a large hall inherited the hall's StoneCorridor preset and boomed. Same bug applied to wall cells. Added ResolveReverbRoom() which picks the smallest non-outdoor adjacent room for doorway/wall cells, so reverb matches the acoustic volume the listener is actually adjacent to. Also removed the zoom-based footstep volume scaling. It made footsteps ~150% at Closest zoom, which drowned out the rest of the game, and ~30% at Middle zoom, which made them too quiet to be useful. Zoom now drives only occlusion, not volume -- footsteps stay at consistent amplitude across all zoom levels. Repurpose the existing FootstepZoomScaling setting as a master toggle for wall occlusion: on means occlusion applies with zoom-based fading, off means no occlusion whatsoever (all footsteps audible regardless of walls). UI label updated to "Wall occlusion" / "Footstep Wall Occlusion" to match. Internal field name preserved to keep existing save-file Scribe keys valid. Files: - src/Sounds/CameraZoomUtility.cs: drop all volume-scaling code and the camera cache; add GetOcclusionStrength() driven by CameraDriver.RootSize (returns 0 when toggle is off, so Lerp(1, raw, 0) = 1 = no occlusion). - src/Sounds/FootstepSoundBank.cs: replace single cached listener room with per-tick cached listener rooms + regions (HashSet); add ResolveReverbRoom() and wall-cell neighbor scan; split GetWallOcclusion into raw computation + zoom-strength blend at the end. - src/Sounds/FootstepManager.cs: drop GetZoomVolumeScale() call. - src/Core/RimWorldAccessSettings.cs + src/UI/WindowlessOptionsMenuState.cs: relabel the toggle with new semantics.
RimWorld's CameraDriver.ApplyPositionToGameObject computes the camera's world-space Y as 15 + t*50, where t is the normalized zoom (0 at Closest, 1 at Furthest). Since the AudioListener is attached to the camera GameObject, zooming lifts the listener up to 50 units higher. Every spatialized world sound uses Unity 3D distance attenuation, so the full game audio mix quieted and re-panned as the player zoomed out -- even though the player was using zoom as a visual-navigation tool, not an audio-distance expression. For a screen-reader user who depends on audio to identify activity across the map, that coupling was hostile: zooming out to survey the colony made the exact sounds they were trying to hear fade away. Fix by hosting a proxy AudioListener on a mod-owned GameObject. The proxy's X/Z track the camera (so left/right/front/back panning still reflects what you're looking at) but Y is pinned at 15 -- the Closest-zoom value, which is the loudest, nearest audio profile the game produces. Result: ambient sounds, combat, weather, and everything else sound identical at every zoom level. Two surgical Harmony patches: - Postfix on CameraDriver.ApplyPositionToGameObject: lazy-init the proxy GameObject on first run (also disables the original AudioListener on the camera), then each frame mirror the camera's X/Z and rotation but hold Y constant. Uses DontDestroyOnLoad so the proxy survives world transitions. Also reparents RimWorld's OneShotSourcesCameraContainer (which holds the 16 "on-camera" oneshot voices plus MusicManagerPlay's output) from the camera to the proxy -- those sources are meant to be coincident with the listener, and leaving them on the camera caused intermittent choppiness at max zoom-out as voices danced near Unity's virtualization threshold 50 units below the listener. - Prefix on SoundParamSource_CameraAltitude.ValueFor: returns the same pinned Y so sound defs binding to the CameraAltitude param (certain ambient/weather sounds) also stop reacting to zoom. No setting -- this is always on, since the behavior it replaces is actively harmful for the mod's use case.
Transpile Command.GizmoOnGUIInt so bare letter gizmo hotkeys no longer fire — users must hold Shift (e.g. Shift+K to build a wall). This frees bare letters for other accessibility shortcuts. Draft (Command_ColonistDraft, default R) is exempt: R remains the vanilla draft/undraft toggle. Players rely on this muscle memory and no other gizmo shares R on a draftable pawn, so leaving it bare is safe. The SR announcement and visual badge both skip the "Shift+" prefix for the draft key. Shift+T previously announced performance stats; it now falls through so it can reach gizmos with hotkey T. Performance stats moved to Alt+T. Screen reader ordering updated: the hotkey is now spoken immediately after the gizmo title, before descriptions and ability cost/range/ cooldown.
When MapNavigationState.CurrentCameraMode is Pawn (set by comma/period cycling or colonist-bar selection), place the mod's proxy AudioListener directly on the focused pawn's DrawPos each frame. Route ScreenPanUtility's pan/distance math through the listener anchor (not the camera) so the followed pawn's own footsteps stay dead-center and other pawns pan relative to the focused pawn's position. Any arrow-key press flips the mode back to Cursor and the listener falls back to its camera anchor (existing behavior). Fixes the practical issue that the camera lags slightly behind a moving pawn, so pan cues for the followed pawn themselves (and for nearby activity) drifted in the pawn's walking direction even though the user was clearly watching that specific pawn. Implementation: - AudioZoomDecouplePatch.cs: add ResolveListenerAnchor(cam) helper that picks pawn.DrawPos (Y pinned to 15) when CurrentCameraMode == Pawn AND Find.Selector.SingleSelectedThing is a spawned pawn on the current map; otherwise falls back to the camera anchor. Also expose GetListenerWorldPosition() so other modules can align with the same anchor. - ScreenPanUtility.cs: replace TryGetCameraMapPosition with TryGetListenerMapPosition, which reads the proxy listener's world XZ first, with the old camera lookups kept as fallback. This behavior may be temporary. The long-term goal of the mod's audio system is to give a blind player a feel for how pawns pathfind across the map -- an absolute-position soundscape where walking directions, distances, and routes are audible. Centering audio on the followed pawn trades that for a first-person "what the pawn hears" view, which means the listener loses absolute positional cues and must rely on environmental sounds or other pawns to orient on the map. The first- person framing felt right in this session's testing; it may get reconsidered or made togglable once the broader pathfinding-audibility system is designed.
…ction
Add two new keyboard shortcuts for faster pawn command flow:
/ (slash): Focus the colonist/mech bar on whichever pawn is standing
under the map cursor. Selects the pawn in-game, jumps the camera, and
syncs the bar position so subsequent comma/period/Alt+arrow navigation
picks up where the cursor pointed. If the cursor isn't on a pawn on
the bar (e.g. an animal or a raider), announces "Not on colonist bar".
[ (left bracket): Execute the top option of the same context menu that
] builds — whatever the first FloatMenuMakerMap entry is for the
currently selected pawn(s) at the cursor. Shift+[ queues the order
instead (KeyBindingDefOf.QueueOrder picks up the shift during action()
invocation, matching vanilla shift-click queueing).
For single-pawn selections, announcement is "PawnName: action" (plus
", Queued" when Shift is held). For multi-select, [ uses the same
per-pawn success/failure wrapping that Enter-on-top-option already
does from the right-bracket menu ("Everyone X", "No one could X",
"Everyone except A X", "Only A X"). That wrapping logic is now
factored into a shared WrapOptionsForMultiSelectFeedback helper so
both bracket handlers stay in sync.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is a big one. Four rounds of changes spanning most of the mod's feature surface — schedule and assign menus rebuilt from scratch, column painting generalized across all supported tables, universal Alt+I info cards, a full tile info overhaul, and a ton of DLC features (Biotech gene inspection, mechanitor control groups, growth moments, Royalty permits, Ideology roles, Odyssey fishing zones). There are also significant improvements to the game setup flow, bill configuration, policy editors, quest system, colonist bar navigation, and the scanner.
Bug fixes touch everything from soft-locks on Biotech dialogs to keyboard layout issues, Escape key isolation, slider direction consistency, and speech sanitization. A detailed changelog and updated documentation will be included before this PR leaves draft.