Commit Graph

5 Commits

Author SHA1 Message Date
JonKazama-Hellion 401ebc9495 feat(recipedata): add LuminaRecipeAdapter + AnvilStrings resx
The adapter is the only place in the plugin that touches Lumina and
Dalamud types - everything outside Anvil.RecipeData.Internal stays on
the BCL surface (Critical Boundary per 00-Anvil-Scope §3.3).

- LuminaRecipeAdapter: walks Status, CraftAction, Action, Item, ItemFood,
  and Recipe + RecipeLevelTable, builds the AnvilXxx records, and
  swaps the CatalogState into RecipeDataCatalog in one atomic write.
  Cosmic actions normalise the Action-sheet ClassJob=-1 sentinel to
  RowIdByClassJob key 0 (spec §2.3.1); the legacy ARR singletons
  (Manipulation 278, Waste Not 279, Innovation 284, Waste Not II 285)
  drop out via the PrimaryCostValue == 0 filter (spec §3.1 #3). The
  CraftAction sheet wins the canonical icon at the CRP variant
  (ClassJobId 8). Per-job rows are cross-checked for Cost, ClassJobLevel,
  and Specialist consistency; mismatches log a warning.
- SH-15 option B is hard-wired: every AnvilRecipe ships with
  MissionHasMaterialMiracle = false, MissionHasSteadyHand = false, and
  IsSplendorCosmic = false in v0.1.0. IsCosmic is still set from
  Recipe.Number == 0 so the catalog can label Cosmic recipes; the WKS
  mission sheet chain is not walked. v0.2.0 will replace those constant
  assignments with the resolver and the rest of the adapter stays put.
- The adapter invariant (Cosmic sub-flag implies the master IsCosmic
  flag) throws on inconsistent recipe states at catalog-build time so
  v0.2.0+ catches a broken WKS resolver before it corrupts the simulator.
- ItemFood walk uses ItemAction.Data[0] (48 = "well fed", 49 =
  "medicated") instead of an ItemAction.Type column that does not exist
  in the current Lumina schema. The bonus extractor filters
  ItemFood.Params to the three crafting BaseParam ids (CP=11,
  Craftsmanship=70, Control=71). Item rows are populated only for the
  ItemIds that recipes / foods actually reference - no 50k-row mirror.
- AnvilStrings.resx + AnvilStrings.de.resx + AnvilStrings.Designer.cs:
  Localization layer for condition display names and the SelfTest step
  name. The adapter looks the condition strings up through the generated
  ResourceManager so culture-switching is a no-restart change later on.
2026-05-27 21:27:55 +02:00
JonKazama-Hellion eb5753eea6 feat(recipedata): add catalog + load result, wire csharpier
Two concerns bundled into one commit because the csharpier tool restore
reformatted four earlier files as soon as the manifest landed:

- .config/dotnet-tools.json: csharpier 1.2.6 as local tool, follows
  the standard .config layout (dotnet tool restore will find it).
- Anvil/packages.lock.json: produced by dotnet restore, pinned alongside
  the csproj's RestorePackagesWithLockFile=true.
- Anvil/RecipeData/RecipeDataLoadResult.cs: public record carrying the
  adapter's load-pass summary (counts + duration + warnings). Surfaced
  to the SelfTest step and future UI status surfaces.
- Anvil/RecipeData/RecipeDataCatalog.cs: public DI singleton with all
  seven dictionary lookups, the two helper methods (ActionsForClassJob,
  TryResolveActionRowId), and the four meta properties from spec §2.7.
  Backed by a private CatalogState record that the adapter swaps in via
  a volatile reference - readers either see the empty initial state or
  the fully populated post-load snapshot, never a partial mid-build.
  TryResolveActionRowId carries the Cosmic-sentinel logic so hook code
  does not need to know about the CosmicOnly flag itself.
- Reformatting in AnvilAction.cs, ActionMechanicsTable.cs,
  ConditionMechanicsTable.cs, and Anvil.csproj: csharpier-mandated
  line-wrap / blank-line tweaks. No semantic changes.
2026-05-27 20:54:14 +02:00
JonKazama-Hellion d7e8c42cc7 feat(recipedata): add hardcoded mechanics tables
Three game-mechanics tables for the simulator-relevant constants that the
Lumina sheets do not expose, plus the reverse name map the adapter uses
to walk the CraftAction + Action sheets.

- ActionMechanicsTable: 38 entries with Category, CP cost, durability,
  efficiency, IQ-stack bonus, charges, granted buff, and flags.
  Cross-checked against the spec mechanics table in 01-RecipeData.md
  §2.3.2 (verified there against Artisan's RawInformation/Character/
  Skills.cs). Combo-state CP costs (Standard/Advanced Touch) carry the
  base value; the simulator applies the discount. TrainedEye uses
  short.MaxValue as the sentinel for "fill Recipe.QualityMax in one
  step"; ByregotsBlessing carries base EfficiencyQuality=100 with the
  IQ multiplier added by the simulator.
- BuffMechanicsTable: 14 entries with StatusId, Icon, StackMax, Behavior,
  the three duration fields (Steps / Seconds / Actions populated per
  Behavior), Category, and LegacyStatusId for the older Innovation 259
  and Manipulation 258 ids. Cross-checked against ffxiv-datamining
  Status.csv (StatusId / Icon / StackMax) and Artisan's tooltip-derived
  step durations. Expedience uses the explicit StatusId 3812 - the other
  two "Expedience" rows (2712 / 3092) are non-crafting status effects
  that would otherwise produce an ambiguous name match.
- ConditionMechanicsTable: 11 entries with Quality / Progress / CP /
  Durability multipliers plus a BaseProbability slot. Robust mirrors
  Sturdy's durability discount and keeps Quality neutral (per the
  spec mechanics table - the enum doc comment in AnvilCondition.cs
  predates rev 5 and is noted as superseded in the table header).
  SplendorCosmic's Good=1.75 override lives in the simulator.
  BaseProbability stays 0.0; the static catalog has no useful per-recipe
  spawn distribution because FFXIV derives that from Recipe.IsExpert +
  RecipeLevelTable.Stars at runtime.
- ActionKindByName: reverse map from English action names to
  AnvilActionKind, plus the Action-sheet whitelist (seven step-counter
  buff actions + two Cosmic singletons) used to filter the Action sheet
  walk down to the crafting subset.
2026-05-27 20:25:52 +02:00
JonKazama-Hellion 47790a3f68 feat(recipedata): add plain-data records and enums
Module 01 public-API surface: six sealed records with init-only
properties plus their nine enums. All BCL-only - no Lumina or Dalamud
types in any public property, which is what keeps the simulator and
catalog xUnit-testable per the Critical Boundary in 00-Anvil-Scope §3.3.

- AnvilRecipe + AnvilRecipeIngredient: flat representation of the
  Recipe + RecipeLevelTable sheet pair with the five Cosmic-Exploration
  flags. v0.1.0 ships with MissionHas* always false (SH-15 option B);
  the schema stays in place so v0.2.0 can wire the WKS mission sheet
  without touching the type.
- AnvilItem: slim per-recipe / per-food item view (full ~50k-row item
  mirror is left to the UI layer).
- AnvilAction + AnvilActionKind + AnvilActionCategory + AnvilActionFlags:
  one logical action per Kind value with RowIdByClassJob mapping; Cosmic
  actions use ClassJobId 0 as the sentinel for "every crafter".
  AnvilActionFlags bit 1 << 2 is intentionally vacant (ConsumesGreatStrides
  was removed in spec rev 5; consumption logic lives in 02-CraftingSimulator).
- AnvilBuff + AnvilBuffKind + AnvilBuffBehavior + AnvilBuffCategory:
  static buff catalog entry with the duration field that matches Behavior
  (Steps / Seconds / Actions). Two Cosmic buffs (MaterialMiracleBuff,
  StellarSteadyHandBuff).
- AnvilCondition + AnvilConditionKind: eleven conditions including the
  Cosmic Robust variant. DisplayName comes from AnvilStrings.resx, not
  Lumina (the Status sheet does not expose the crafting condition labels
  cleanly).
- AnvilFood + AnvilFoodBonus + AnvilFoodKind + AnvilFoodStat: ItemFood
  mirror with IsRelative flag (percentage vs flat bonus).
2026-05-27 19:53:54 +02:00
JonKazama-Hellion 96553a849a chore: bootstrap Anvil repo skeleton
First commit on feature/v0.1.0 establishes the Hellion Forge plugin
scaffold:

- .gitattributes: Linux-first LF defaults, Windows-script CRLF exceptions,
  binary markers for fonts / images / archives. Pre-empts the
  Forgeimizer pre-push hook crash that was caused by Asriels CRLF default.
- .editorconfig: Hellion Forge .NET conventions
  (private fields _camelCase, Allman braces, var-preferred).
- .gitignore: VisualStudio baseline + secrets bucket + Anvil.Tests
  excluded (build-suite lives in the local Hellion Build test repo).
- LICENSE: MIT, Hellion Online Media 2026.
- NOTICE.md: goodwill attribution to Craftimizer and clean-room
  anonymisation note.
- PRIVACY.md: zero-telemetry statement matching 00-Anvil-Scope.
- README.md: v0.1.0 status + planned-feature outline + custom-repo URL.
- Anvil.sln + Anvil/Anvil.csproj: Dalamud.NET.Sdk/15.0.0, x64 platform
  pinned (forge-wide rule), Microsoft.Extensions.Hosting stack closed-range
  pin to 10.0.7 matching HellionChat v1.5.0. No DalamudPackager.targets
  override - SDK 15 default packager handles images / icon / image_urls.
- Anvil/Anvil.yaml: plugin manifest with explicit icon_url / image_urls
  (top-level fields required for SDK 15 default packager) and a v0.1.0
  changelog entry that names RecipeData as the first module.
2026-05-27 19:16:36 +02:00