Skip to content

Added bulk dependency-ignore actions, local mod aliases, and an Ignored filter. Resolves #421 #436

Open
CrowSoda wants to merge 1 commit intoX2CommunityCore:masterfrom
CrowSoda:feat/bulk-ignore-dependencies
Open

Added bulk dependency-ignore actions, local mod aliases, and an Ignored filter. Resolves #421 #436
CrowSoda wants to merge 1 commit intoX2CommunityCore:masterfrom
CrowSoda:feat/bulk-ignore-dependencies

Conversation

@CrowSoda
Copy link
Copy Markdown

Dependency Management UX Improvements

This PR adds three user-facing features and one UX fix for dependency management in the per-mod Required Mods grid.

More detailed pictures can be seen in #421.

Bulk Ignore Actions

Right-click any row in the Required Mods grid to access the new bulk ignore actions.

Ignore a dependency for all mods that require it

Ignore <dep> for all mods that require it

Shows a confirmation prompt with the dependent mod count, then adds the dependency's Workshop ID to IgnoredDependencies on every mod that lists it.

This is useful when running a non-Workshop version of a popular dependency, such as:

  • LWOTC
  • X2WOTCCommunityHighlander

It is also useful when a dependency is replaced by another mod, such as:

  • Mod Jam to TJ
  • Primary Secondaries to True Primary Secondaries
  • [WOTC] LW2 Secondary Weapons to LWOTC

Stop ignoring a dependency globally

Stop ignoring <dep> for all mods

Performs the inverse operation and removes that dependency from all mods.

This action does not show a confirmation prompt.

Ignore or unignore selected dependencies on the current mod

When multiple rows are selected, the context menu now shows:

  • Ignore selected (N) on this mod
  • Stop ignoring selected (N) on this mod

These actions only affect the currently viewed mod.

Substitute Picker for Local Mod Resolution

Find substitute for <dep>... opens a modal dialog for selecting an installed mod as a substitute for a missing Workshop dependency.

The dialog includes:

  • A filter textbox
  • Sortable columns for:
    • Mod
    • Source
    • Workshop ID
    • Substitutes?
  • An explicit Substitute or Remove substitute button

The button is disabled until a row is selected. Its label changes based on whether the selected mod is already acting as a substitute.

This is backed by a new ModEntry.WorkshopIdAliases field with type List<long>.

When a Workshop dependency cannot be resolved by an exact WorkshopID match, GetRequiredMods now also checks WorkshopIdAliases.

This allows a locally installed mod to satisfy a Workshop dependency. Examples include:

  • A non-Workshop install of LWOTC
  • A beta version of a mod with a different Workshop ID
  • A local replacement for a Workshop dependency

Exact Workshop ID matches always take priority over alias matches through OrderBy.

The same resolution behavior is mirrored in:

  • LoadNotInstalledDependencies
  • The cheap GetDependentMods path

Ignored Dependencies Filter

A new yellow Ignored (N) checkbox has been added to the legend pane next to Missing dep.

This filter shows only mods with at least one ignored dependency.

This is useful for:

  • Reviewing ignored dependencies
  • Finding accidental bulk ignores
  • Recovering from incorrect ignore state changes

This is implemented through a new showIgnoredDepsOnly parameter on ModListFilter.

UX Fix: Filter and Counter Refresh on Dependency State Changes

Previously, the legend filters and label counters did not re-evaluate when a mod's dependency state changed through the per-row Ignore checkbox.

For example, a row could remain visible under Missing dep until the user clicked away.

Dependency-state mutations are now routed through a new RefreshDependencyState helper, which calls the following together:

  • RefreshObjects
  • UpdateStateFilterLabels
  • RefreshModelFilter

The same fix was also applied to the activation-toggle handler in MainForm.ModList.cs.

Layout Improvements

The bottom split container was changed from FixedPanel.Panel2 to FixedPanel.None.

This allows both panels to resize proportionally when the form is resized.

Previously, the bottom info panel stayed pinned at about 270 px regardless of how large the user made the window.

Additional layout changes:

  • Increased SplitterWidth from 5 to 16 for better grabbability
  • Added Panel1MinSize = 100
  • Added Panel2MinSize = 150

Backwards Compatibility

WorkshopIdAliases is a new public auto-property on ModEntry.

Old settings.json files load with an empty list through Newtonsoft's default behavior.

New saves write the field.

No schema bump or migration is required.

Testing

Manually tested against a real XCOM 2 mod set with:

  • Non-Workshop installs of LWOTC
  • Non-Workshop installs of X2WOTCCommunityHighlander
  • Dev-recommended substitutions and ignores, including:
    • Primary Secondaries to True Primary Secondaries
    • Mod Jam
  • A full game launch after applying the dependency changes

…ed filter. Resolves X2CommunityCore#421.

- Added a context menu on the per-mod Required Mods grid:
  - "Ignore '<dep>' for all mods that require it" with a confirmation prompt showing the dependent count, plus a symmetric "Stop ignoring '<dep>' for all mods" inverse.
  - "Find substitute for '<dep>'..." opens a picker dialog (filterable, sortable, single-select with an explicit Substitute / Remove substitute button) to declare an installed mod as a substitute for the Workshop dependency.
  - "Ignore selected (N) on this mod" / inverse, conditional on multi-select in the grid.

- Added ModEntry.WorkshopIdAliases (List<long>). When a Workshop dependency cannot be resolved by exact WorkshopID match, GetRequiredMods now also checks WorkshopIdAliases so a locally-installed mod (e.g. a non-Workshop install of LWOTC, or a beta version under a different Workshop ID) can satisfy the dependency. Exact WorkshopID matches always take priority over alias matches via OrderBy. Mirrored in LoadNotInstalledDependencies and the cheap GetDependentMods path.

- Added a new "Ignored" filter checkbox in the legend pane to surface mods that have at least one ignored dep. Useful for review and recovery from accidental bulk-ignores. Implemented via a new showIgnoredDepsOnly parameter on ModListFilter.

- Routed all dep-state mutations through a new RefreshDependencyState helper that calls RefreshObjects, UpdateStateFilterLabels, and RefreshModelFilter together. Active filters and the legend counters now reflect state changes immediately. Wired into the existing per-row Ignore checkbox handler, the new bulk operations, the alias picker, and the activation-toggle path.

- Bottom split container: changed FixedPanel from Panel2 to None so both panels grow proportionally with the form, increased SplitterWidth from 5 to 16 for grabbability, and set Panel1MinSize / Panel2MinSize.
@RevZero
Copy link
Copy Markdown
Member

RevZero commented Apr 27, 2026

Thanks for the PR and the detailed description, looks like some useful additions. I'll try to take a closer look at it soon.

@CrowSoda
Copy link
Copy Markdown
Author

No worries, just figured I'd help of Tedster. If I need to make any changes let me know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants