Install target multi-game UI — New dropdown at the top of the sidebar lets users pick which Infinity Engine install this config targets (EET, BG:EE, BG2:EE, IWD:EE, PST:EE, or "All Enhanced Editions (advanced)"). No silent default — a gold "CHOOSE" chip marks it until the user picks; once chosen, the filter hides classic-only mods, surfaces compatibility badges on mod headers and per-component rows, warns when selected components can't install on the target (red ! badge + incompatible-selection banner with "Clear incompatible"), dims preset/community builds that don't fit, and pops a pre-export modal with three paths (Cancel / Export as-is / Strip and export) so WeiDU never sees components it would just skip. Essentials filter by target too (IWD:EE hides the EET toolchain). State persists in localStorage.emf_installTarget. New module-scope helpers: INSTALL_TARGETS, CLASSIC_TOKENS, normGames, compInstallableOn, modHasAnyInstallable, isClassicOnly, presetCompatible
Subcomponent hierarchy rendering (scn / grn) — Expanded mod cards now surface WeiDU's SUBCOMPONENT and GROUP structure. The "Choose One" mutex label reads the real scanner-resolved name ("Tougher Giants — Choose One", "Static PsT Character Portraits — Choose One") instead of a prefix heuristic; the heuristic is preserved as fallback for the ~211 mods whose tp2 wasn't in the Extracted bundle. Cyan uppercase section headers (grn) group subcomponents above them ("Enemy Improvements", "Update Existing Encounters"). Duplicate grn headers from tp2 authoring artifacts suppressed (WeiDU collates them at install time, we do too). Each scn group carries an optional engine-restriction badge ("PSTEE only", "EET/BG2EE only") via scnGroupGames, which intersects sibling games arrays and reports only when the restriction narrows the EE target set. Resolves the forum complaint about Tactics Remix showing 8+ identical "Double/Default HP" pairs with no enemy context and cdtweaks cn=270/271 sitting under a generic "CHOOSE ONE"
Project Infinity CSV import — Drag-and-drop a PI-format weidu-log.csv into the existing WeiDU.log drop zone. Auto-detects format via header sniffing; description-based matching with exact LABEL match first, then startsWith-unique fuzzy fallback; mojibake recovery (latin-1 → utf-8 re-decode) for double-encoded names. Fuzzy-matched rows surface in the import result with an expandable "review recommended" breakdown so users can verify before trusting the match
Category ↔ install-phase clarity — Filtering by a sidebar category (e.g. "Pre-Tactical Tweaks") now renders a flat mod list with a sticky caption ("# Pre-Tactical Tweaks — 42 mods tagged with this category") instead of the previous cross-section grouping that could show the same mod under two install-phase headers. Each card in the flat view carries a small gold ↪ {phase} chip showing the mod's primary install phase, so when filtering "Post-Tactical Tweaks" users can see at a glance which cards are actually post-tactical vs. which only also-tag that category. Sidebar category names gain a dim-gold # prefix (aria-hidden) to read as tags rather than install-phase sections
Pristine-release cleanup — Keyboard a11y generalized across card types via a clickableProps helper (Spell / Kit / Item / Portrait); filter pills unified into a <Pill> component with :focus-visible ring; Spells and Kits filter state now persists in localStorage matching Items/Portraits; <PanelBoundary> wraps every top-level tab so a single bad mod entry no longer takes the whole app down (Planner keeps its existing boundary); narrow-viewport tooltip CSS caps max-width to calc(100vw - 24px) below 400px
Config externalization — Tooltip content extracted to data/config.json::ui.tips; item type colors (49) and Unicode glyphs (49) lifted from hardcoded maps into config.json::itemColors / itemGlyphs with code-level fallbacks; scattered URL constants consolidated to config.json::urls
Virtual list scroll anchor fix — Clicking a component inside a long expanded mod (Tweaks Anthology) no longer snaps scrollTop back to the mod's top. Root cause was the expand-anchor useLayoutEffect firing on every tops change (each measuredH update from the click re-render re-applied the anchor). Fix: one-shot on expId change, clear the anchor after apply
Portrait picker modal portalization — Character Planner's portrait selector was trapped by .planner-left's position:sticky; overflow-y:auto (which creates a containing block for position:fixed). Modal now renders via ReactDOM.createPortal(..., document.body) so the backdrop escapes the sticky container and covers the full viewport
Data layer: games field — New optional per-component field tagging which Infinity Engine variants each component targets. Derived from tp2 REQUIRE_PREDICATE GAME_IS (and both NOT GAME_IS and !GAME_IS exclamation-form, expanded to the positive complement) via scripts/scan_game_targets.py; 2,500+ components across 290+ mods tagged after v2 regex caught additional !GAME_IS cases v1 missed. Mod-level games is the component union; new coGames parallel array in mods-index.json. Omitted = universal. Whitelist covers the EE family (eet bgee bg2ee iwdee pstee sod) plus classic engines (bgt tutu ca iwd_in_bg2 how totlm etc.); 200+ components are classic-only. --only <stem> flag for single-mod rescan. Pre-commit hook auto-populates on staged edits. Handoff doc: docs/GAMES_FIELD_HANDOFF.md
Data layer: subcomponent scanner — scripts/scan_subcomponents.py extracts WeiDU SUBCOMPONENT @ref / GROUP @ref directives per BEGIN block, resolves @refs via the TRA loader (shared with scan_game_targets.py), and populates scn / grn fields. Idempotent, fill-empty-only (never overwrites existing values), strictly additive. Pre-commit hook runs both scanners on staged mod edits. 2,000+ components gained scn across 200+ mods; 2,400+ gained grn across 60+ mods. Handoff doc: docs/SUBCOMPONENT_HANDOFF.md
Schema versioning (sv field) — New required field tagged on every mod detail file as its second property (after i). Anchors v1 semantics (dep as string-reason, gone:true for removed components mutually exclusive with dep, tp2n for drift detection, preset key format modId-cn, wf cross-contamination rule). Migration scaffold at scripts/migrations/ with conventions for future bumps. Validator errors on missing/unknown sv. Full schema doc: README § "Schema versioning"
tp2n backfill — scripts/tp2n_backfill.py populated 2,400+ components across 300+ mods from canonical v18 tp2 parser output. Strictly additive (never overwrites), idempotent, defends against \ufffd Unicode replacement characters from non-UTF-8 TRA files (a handful of components intentionally left empty: Polish/German/Korean TRAs that can't be cleanly decoded). Paired with scripts/tp2n_backfill_dryrun.py classifier (NEW/MATCH/DIFF/ORPHAN/NOTP2) and scripts/tp2n_sample_inspect.py for byte-level verification. tp2n coverage jumped from ~45% to ~80% of components
audit_tp2_drift.py parser hardening — LANGUAGE priority fix (previously grabbed whichever language was declared first — LivingClara's Chinese-first LANGUAGE block was polluting English display names). Now prefers setup.tra / setup-<wf>.tra / <wf>.tra in that order, then alphabetical fallback. Block comment stripping, heredoc handling, multi-line BEGIN tolerance, LANGUAGE-declared tra priority. Zero drift vs v18 tp2 baseline across 600+ scannable mods
Validator v2 — Distinguishes true duplicate wc (same cn + same name + same pi → data bug) from SUBCOMPONENT siblings (same wc, different cn/name/pi → legitimate WeiDU FORCED_SUBCOMPONENT pattern). Legitimate sibling groups de-noised (keldorn_rom, proficiency, d2-party-adder). Also checks: games whitelist tokens, empty games array, games shape; scn/grn shape (non-empty strings, <200 chars); sv presence + known version; preset key format modId-cn with gone-component warning. Zero errors / zero warnings baseline
wc-dupe + preset-gone cleanup — Fixed real data bugs: zstweaks co[253]/co[254] identical-duplicate pair (kept cat-override version), selphiratweaks co[11]/co[12] same, jtweaks co[19/20]/co[68/69] near-duplicate pairs collapsed, cdtweaks co[120] wc typo (2240→2280) + downstream co[118] typo (2280→2270). Removed stale references from Veteran's Challenge preset (Transitions components marked gone:true that the preset still pointed at)
Install-log-driven ki entries — 10+ new per-mod known-issue entries + a global pattern in data/known_issues.json from an active install's debug output. Covers: SFO/SFO2E ALTER_SCRIPT.TPH line 548 GLR parse error (WeiDU 25201 regression affecting iwdification, mih_fr, mih_sp); dw_talents ohtempus class-compat with Tempus; EET_Tweaks Higher-Framerates-Support and Import-Party-Items BCS parse failures; SubtleD Cantrips cn:62 RH#ADR25.CRE patching conflict with Rogue Rebalancing + benign UI.MENU "pattern not found" warnings; ee_cosmetic_enhancements "no effects altered on X.itm" info entries
Tethyr Forest Patch install-order rework — Mod relocated from RESTORATIONS ord=160 → QUEST MODS BG2 ord=710 per the mod's own readme ("Install Setup-TethyrForestPatch after you have installed CtB and TS-BP"). New orderOnly: true, after: true conflict entries pointing at CtB (i=505), Tortured Souls Lite (i=579), Tashia NPC (i=500) with readme citations. Reciprocal before: true conflicts added on all three target mods. Previous placement silently no-op'd TFP on any normal install order
Klatu Content Changes install order — Most sibling components in the "Content Changes" group were missing the cat: "SPELL MODS" override that one component already had. Matched the existing convention so all Content Changes now install in SPELL MODS (before PRE-TACTICAL TWEAKS where cdtweaks lives), honoring Klatu's readme directive: "Components from Content Changes, as well as the Streamlined Spell Progression Tables, should be installed prior to other tweak, fix and rule collections"
Tactics Remix per-component split — Components tagged grn: "Add New Encounters" now carry cat: "PRE-TACTICAL TWEAKS" override so they install BEFORE SCS; remaining components (Update Existing Encounters, Enemy Improvements, Spell and Item Changes, Cosmetic) stay in TACTICAL MODS per morpheus562's readme: "New encounters should be installed prior to SCS while updates to existing encounters should be installed after SCS." SCS↔TR conflict severity upgraded partial → hard (reciprocally on both mods) with revised reasoning reflecting forum feedback about TR v3.0+ being a comprehensive difficulty overhaul that substantially duplicates SCS's AI/encounter layer. New info-level ki entry framing the either-or tradeoff for users
Auto-compute mod.cats in index builder — Previously hand-maintained in detail files; most multi-category mods had correct cats arrays only because someone remembered to update. TR and others silently stayed single-category in the index despite having per-component cat overrides. Both scripts/lib/mods-io.js and scripts/build_index.py now auto-derive entry.cats = unique({mod.c} ∪ {co[].cat}) at index-build time. Stale/missing cats can no longer drift from the source of truth
Pre-commit hook orchestration — Hook now runs in order: (1) populate games field on staged mods via scan_game_targets.py --only <stem>, (2) populate scn/grn via scan_subcomponents.py --only <stem>, (3) rebuild mods-index.json, (4) run full validate_mods.js, (5) run drift scan if any staged mod has a tp2n field. Any failure aborts the commit. Single-mod --only keeps commits fast
New mod: Jarl's BGT Tweak Pack — 50+ components, NPC CUSTOMIZATION. Fully hydrated: games, scn, grn, tp2n, langs (de/en/ru with German primary), author attribution, phase tags, per-component install notes for BGT-only / BGT+EET-only / German-only components. Zero drift on add
To be perfectly clear since the block of updates crowds the screen: this tool does not have permission to host and falsely misrepresent my mods. The current update involving Tactics Remix shows years old out of date information that isn't close to correct, and I ask that my mods be removed as he continues to post bad information about my work.
Just so it doesn't get buried under your corrections.
Anyway, the Forge as of version 4.1.0 can be accessed at krion64.github.io for the time being. If Anprionsa wants me to I will take it down, although I would really rather not, if only for my own sake, but I messaged them on Reddit about my fork of the GitHub repository for their tool and they replied in a thread I made about the fork so they are least aware of it.
I am not a programmer and so will be unable to update the Forge on my end. The primary/main forge will always be the one hosted by Anprionsa unless they stop developing the project or something.
Let's not do personal attacks, please, as they are against the forum rules. We're monitoring the situation closely and hope the drama won't continue.
That is my bad for fanning the fires. I removed all references to Morpheus from my post above. Please let me know if it is okay now, when you get the chance.
What you posted still has references to my work within the forge. As requested via the original tool via an Issue Request. Remove references to my work.
What you posted still has references to my work within the forge. As requested via the original tool via an Issue Request. Remove references to my work.
Why do I need your permission in the first place? That sounds really selfish. Did you ask permission for every time you used someone else's tools, API's, or what have you?
Edit: corrected "access" to "ask" above.
Edit 2: Not to mention, it is a link and a description. Nobody else is actually hosting your work.
For those wanting to turn down the heat, this is the opportunity to do so. The response above is not what is needed right now.
What does that even mean?
Edit: If you get my GH taken down like Anprionsa, I'll just have to host it somewhere else. Worse comes to worst, I will host it on my server at home, I have a business-class subscription with my ISP so it shouldn't hurt me at all.
Edit: I can't program so even if I wanted to, I can't change anything to begin with.
You came in here blasting personal attacks against me. That's fine, I get it, you're angry. So are a lot of people.
I don't want to be associated with the tool and would appreciate common courtesy to remove my work when asked, which I have been doing for awhile now. Its creating hostilities and problems with it being hosted on the tool, so I ask again, lets ease tension and just remove me from the tool.
You came in here blasting personal attacks against me. That's fine, I get it, you're angry. So are a lot of people.
I don't want to be associated with the tool and would appreciate common courtesy to remove my work when asked, which I have been doing for awhile now. Its creating hostilities and problems with it being hosted on the tool, so I ask again, lets ease tension and just remove me from the tool.
No, because your actions and requests go against my morals. Your actions go against common decency in general.
Edit: What license you use for your software anyway? Depending on what it is you might be breaking the terms of the license or even the law, depending on if it has been enforced in court before.
I'd appreciate if we don't discuss this anymore in this thread. I'm currently in the process of restoring this via the process GitHub has for this. I'd like to focus this purely on the tool and making it better. Thank you for all that have come out to support it and work to improve it.
Morpheus. You've made your contribution, it's here going forward. You have a discord you can talk about this in if you like.
Also I don't know how to program so I can't make any changes to begin with.
Edit: Sorry Anprionsa, I know you said that you didn't want any more discussion about this, but this post and the one directly above were pending approval before you posted yours. If you want, I can ask a mod to delete them?
Comments
Just so it doesn't get buried under your corrections.
I am not a programmer and so will be unable to update the Forge on my end. The primary/main forge will always be the one hosted by Anprionsa unless they stop developing the project or something.
The source code is available on the Releases section of https://github.com/krion64/krion64.github.io
Edit: Removed references to Morpheus.
That is my bad for fanning the fires. I removed all references to Morpheus from my post above. Please let me know if it is okay now, when you get the chance.
Sure, if you give me a good reason to.
Why do I need your permission in the first place? That sounds really selfish. Did you ask permission for every time you used someone else's tools, API's, or what have you?
Edit: corrected "access" to "ask" above.
Edit 2: Not to mention, it is a link and a description. Nobody else is actually hosting your work.
Well you don't need to and neither do I.
Edit: It looks like your GitHub doesn't exist anymore anyway. The link to https://github.com/morpheus562 just says the repo no longer exists.
Edit: nevermind, it looks like you don't use GH anymore. Point still stands.
What does that even mean?
Edit: If you get my GH taken down like Anprionsa, I'll just have to host it somewhere else. Worse comes to worst, I will host it on my server at home, I have a business-class subscription with my ISP so it shouldn't hurt me at all.
Edit: I can't program so even if I wanted to, I can't change anything to begin with.
I don't want to be associated with the tool and would appreciate common courtesy to remove my work when asked, which I have been doing for awhile now. Its creating hostilities and problems with it being hosted on the tool, so I ask again, lets ease tension and just remove me from the tool.
No, because your actions and requests go against my morals. Your actions go against common decency in general.
Edit: What license you use for your software anyway? Depending on what it is you might be breaking the terms of the license or even the law, depending on if it has been enforced in court before.
Morpheus. You've made your contribution, it's here going forward. You have a discord you can talk about this in if you like.
Edit: Sorry Anprionsa, I know you said that you didn't want any more discussion about this, but this post and the one directly above were pending approval before you posted yours. If you want, I can ask a mod to delete them?