Repository navigation
feat: expose equipment targeting, skill trees and tooltip extensions - #313
Conversation
|
Read-only source review found the separated equipment/skill-tree/tooltip design respects game vocabulary and removes consumer coordination machinery. Verified vanilla AbstractUnit.IsPlayer(true) matches only GameplayManager.Instance.spaceShip; carrier fighters are excluded. Cached specialization identifiers to avoid repeated reflective mapping. Deterministic in-game E2E passed on game 0.8.2.4 with patch-free TractorAuto: zero/half/max mastery, auto promotion, manual borrowing, saturated/busy pool guards, native candidate eligibility/order/caps, cached module tooltip, styled 0% mastery tooltip, and disabled behavior. API tested as unreleased 0.0.0.0. Report records realSavesUnchanged=true, installationRestored=true; no game process/backup marker remains. Exact harness retained under artifacts/e2e/tractor-run/source. Host tests 1820 and installed binding tests 75 pass. Public 0.2.8 does NOT contain this surface. |
61dad74 to
a7719b5
Compare
Replace RegisterTractorModule with game-aligned family surfaces: RegisterShipModule dispatches one centralized stat-builder postfix per native AbstractEquipment override with a typed ShipModule snapshot (ShipModuleKind, StatLines, tractor sub-snapshot), and RegisterItem hooks the shared tooltip content fill for item sources. All three families dispatch from a single TooltipRuntime behind one Harmony instance with fail-closed binding. E2E gains committed tractor-module case with family and item checks.
Concrete equipment leaves (turrets) declare SetMainSubStats on abstract intermediates such as AbstractTurret; skipping abstract types left those overrides unpatched. Bind every declaring override with a body, map *Turret types to the new ShipModuleKind.Turret, and extend installed bindings plus the committed E2E family/item checks. Live E2E tractor-module passes (realSavesUnchanged, installationRestored).
Claim stats/tooltip objects per frame so a future base-chaining native override cannot double-append a contribution; document that the native module stat list renders plain text only (TooltipTextStyle ignored for RegisterShipModule); drop the dead dedupe set; the E2E now asserts exactly-once contributions and rebuilds the live module stats after the family check. Live E2E tractor-module passes (run-6).
…three tooltip families One small patch-free mod shows the #313 surfaces as a modder uses them: ExtraAutoBeam borrows one manual beam (abstain-by-null when off), the ship-module registration renders live Engineering mastery on the tractor stat list, the skill-tree registration annotates the Engineering badge, and HighlightItem opt-in adds an item tip. Styles, caching and disposal contracts documented in the example README. Committed E2E case tractor-guide drives exactly that sequence (fresh tooltip per fill, consumer isolated, all fixture state restored); both tractor cases pass live on the qualified build. External consumer DLLs (VGTractorAuto) became optional staging assemblies; in-repo examples are required.
Record staged optional consumer DLLs (name/sha256/mtime) in the E2E report so a stale out-of-repo DLL is attributable; fail closed when a staged VGTractorAuto lacks the setting the case-isolation relies on; drop redundant null-forgiving initializers in the example. Tooling tests and live tractor-guide pass (guide-run-3).
…ock all examples
- RegisterShipModule/RegisterSkillTree join UiSurfaces behind a new
typed "AnnotateModules" preference; RegisterItem joins StationCommerce
as the maker tip on its own good. TractorGuide keeps exactly the one
decision it owns: the settings-gated ExtraAutoBeam borrowing.
- Live cases extended: ui-surfaces asserts six settings plus
exactly-once annotated module/badge lines; station-commerce forces the
shared item fill and asserts both authors tips once, styled.
- Fix latent example breakage found while proving this:
[BepInDependency("vgmodapi","0.2.8")] blocked every pinned example
under the deliberate 0.0.0 development version (earlier "passes" were
tag-derived 0.2.8 builds); drop the in-repo pins with a comment.
StationCommerce used a non-existent vanilla id "Carbon"; the owned
good never actually materialized. Use SalvageCarbon and trigger the
game-side lazy lookup in the case.
- tools/e2e.py staging regressed to two example DLLs on this branch;
restore the full set. observation and story-missions now pass live
again; cargo-recovery and pocket-worlds load and advance to their
movement steps, which time out (pre-existing flow drift, separate).
UiSurfaces registers its tooltip contributions before the settings- provider early return so they depend only on their own ConfigEntry; six-settings log wording; StationCommerce comment acknowledges the cross-author name match it demonstrates; dependency-comment indentation.
… all consumer-mod awareness
The example is named after the surface it demonstrates (equipment
targeting), not a game feature theme. The API repository no longer
knows any consumer mod:
- TractorCase (a consumer-migration qualification case referencing
VGTractorAuto settings and its tooltip strings) is replaced by
EquipmentPolicyCase, which verifies the same native guarantees with
API-owned registrations only: vanilla cap without rules, capacity of
a registered rule, first-non-null precedence between two rules,
disposal handing over to the remaining rule, occupied-beam guard and
teardown to vanilla.
- OPTIONAL_ASSEMBLIES ("VGTractorAuto.dll") is replaced by a generic
repeatable --stage argument; staged extras are recorded with sha256
and mtime. E2E_STAGE= passes it through from the Makefile.
- EquipmentTargetingCase dropped its consumer-isolation block; nothing
references another mod. Committed consumer verification stays in the
consumer repositories.
Live: equipment-policy and equipment-targeting pass (realSavesUnchanged,
installationRestored); host 1835, bindings 76, tooling tests OK.
The example case now bumps and restores amountOfBonusBeams like the policy case, so the borrow assertion no longer depends on the test save happening to have a manual beam. --stage rejects anything but a bare file name, keeping staged files inside the plugins directory.
Files this repo owns now speak the PR surface; names that mirror game types keep the game vocabulary (TractorBeamRuntime binds the game\s
Generic feature work: reusable, game-aligned capabilities so consumer mods need no Harmony patches. The API knows the game, never other mods.
Surfaces:
ITooltipService.RegisterShipModule— every nativeBehaviour.Equipment.Modulefamily (17ShipModuleKinds incl. Mining, Salvage, Shields, Reactor, Drones, Turret) via one centralized postfix per declaringSetMainSubStatsimplementation, including implementations on abstract intermediates such asAbstractTurret; typedShipModulesnapshot (Kind, DisplayName, QualityLevel, vanilla StatLines, tractor sub-snapshot). Native stat lists are plain text; documented.ITooltipService.RegisterItem— sharedUITooltipfill for item sources (ItemInfo).ITooltipService.RegisterSkillTree— mastery-badge contributions.ISkillTreeService.Get(CommanderSpecialization)— all nine specializations.IEquipmentService.ConfigurePlayerTractorModules— typed targeting policy (abstain-by-null, first-non-null wins); tractor-named because that is the game's own system (TractorModule).One
TooltipRuntime+ one Harmony instance per seam, fail-closed binding; per-frame claims prevent double-append; consumers never see game/Unity types.Examples, named after the surfaces:
AnnotateModulestyped preference gates module-family + Engineering-badge tooltip annotations.RegisterItem.Consumer-mod neutrality: the repository contains no references to any consumer mod. The former consumer-qualification case (referencing a sibling mod's settings and tooltip strings) is replaced by
equipment-policy, which verifies vanilla cap, rule capacity, first-non-null precedence, rule hand-over on disposal, occupied-beam guard and teardown — with API-owned registrations only. Name-specific optional staging became a generic repeatable--stageargument (E2E_STAGE= in the Makefile); staged extras are recorded with sha256+mtime. Consumer verification lives in the consumer repositories.Latent example breakage found and fixed while proving this: 0.2.8
BepInDependencypins blocked every pinned example under the deliberate 0.0.0 development version (earlier passes were tag-derived builds); in-repo pins removed. StationCommerce used a nonexistent vanilla idCarbon— its owned good had never materialized; nowSalvageCarbonwith the game's lazy-lookup path driven by the case. E2E staging list restored to all examples; ui-surfaces settings count updated to six (stale on main).Verification: make test 1835; check-bindings 76; tooling tests OK. Live on the qualified build (sha 71636b8f…): equipment-policy, equipment-targeting, ui-surfaces, station-commerce, observation, story-missions pass with realSavesUnchanged/installationRestored. cargo-recovery/pocket-worlds now load (previously dependency-blocked) and fail at pre-existing movement-step drift, tracked separately. Unreleased feature: no version guessed; public 0.2.8 does not contain it.