Skip to content

fix: name infused gems after their rolled stat - #45

Merged
XxFran10xX merged 2 commits into
mainfrom
fix/infused-gem-name-by-stat
Oct 17, 2026
Merged

XxFran10xX merged 2 commits into
mainfrom
fix/infused-gem-name-by-stat

Conversation

@XxFran10xX

@XxFran10xX XxFran10xX commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Problem

An infused gem is named after its drawn rarity, but the Intelligence d20 then rolls its stat across a spread that reaches 20% past that rarity's band. The bands overlap, so a Flawless Epic Agate (0.60 max health) beat a fumbled Legendary one (0.40).

Change

The rolls stay the same: the rarity draw (65/25/7/3), the d20 + Intelligence and the spread all work as before, so every gem gets the same stat it would today. Only the name is picked afterwards:

  • On every config load, GemNameCutoffs lists every result a gem can roll (each drawable rarity × each die face) and gives each rarity's name to the same share of results as its draw chance, best results first. A better name therefore never means a weaker gem.
  • The share is worked out at a new d20.infusion.name-reference-modifier (default 0, i.e. Intelligence 10–11). Players above it get better names more often, because their gems really are better.
  • buildInfusedGem names the gem, writes gem_rarity and builds the lore from that rarity. The broadcast reads the rarity from the built gem, so it announces the name the gem actually has.
  • Results that tie on one stat keep one name. When a tie would push a rarer name past its chance, the whole tie gets the lower name, so a rarer name (or a rarer name plus the ones above it) never goes over its chance.
  • Each gem's cutoffs are logged on load, e.g. Gem 'agate' names: legendary from 0.5558, epic from 0.4526, rare from 0.3347, common below.
  • A gem that can't be ranked (a drawable rarity with no stat block, or different stats per rarity) keeps the drawn rarity's name and logs a warning. None of the 40 bundled gems hit this, and neither do Dev's or Main's (same config.yml).

Effects to know about

  • Goldsmithing boost: jewelry-gem-stat-boost chances key off gem_rarity, so they now follow the name too. A fumbled Legendary named Rare gets Rare's 15%.
  • Name rates: at modifier 0, rarer names never go over 3/7/25%; the shortfall ends up in Common. Every bundled gem is within 3.1 points of 65/25/7/3; the Crystallite tier is the furthest off at 68.1/24.9/5.3/1.8.
  • Main: Main's config has no d20: section, so it uses the default reference modifier 0. No config change is needed there.
  • Existing gems: gems infused before this keep their names.

Testing

  • mvn clean verify: all tests pass locally. The only coverage gaps are InfusionStationStore and GoldsmithStationStore, whose POSIX-permission tests can't run on Windows; they're excluded locally and run on Linux CI.
  • New GemNameCutoffsTest:
    • bundled cutoffs and the Flawless-Epic/fumbled-Legendary case;
    • names never go down as the stat goes up, for every bundled gem;
    • rarer names never go over their chances, and every name stays within 3.1 points of its chance;
    • a rarity whose best tie is too big is never named;
    • effect of the reference modifier;
    • gems that can't be ranked, and rarities that can't be drawn.
  • GemOutputTest checks a built gem is named by its stat, and InfusionEventsTest that the broadcast follows that name.
  • TFMCDev01 (this build, re-run after the tie change, bot ~/gem-name-test/test.js): real infusions of 10 Agates at an enchanting table in three rounds, forced natural 20, forced natural 1 and real rolls, 55/55 checks passed:
    • startup and every reload logged the same cutoffs as the unit tests;
    • every gem's name and gem_rarity matched its stat's cutoff;
    • Flawless Commons (0.36) came out Rare; in the first Dev run, before the tie change, a Flawless Epic (0.60) came out Legendary, and 0.60 is still above the new 0.5558 cutoff;
    • the saved broadcast went to the Legendary-named gem only;
    • no GemInfusion errors in the log.

🤖 Generated with Claude Code

The drawn rarity still sets the stat's range and the d20 still picks the
stat, but the name now comes from how that stat ranks among every result
the gem could roll. Each rarity's name goes to the same share of results
as its draw chance, so a Flawless epic can no longer beat a weaker
"Legendary". The cutoffs are worked out at d20.infusion.name-reference-modifier
(default 0) and logged per gem on every config load.

The broadcast, the stored gem_rarity tag and the goldsmithing boost chance
all follow the name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the size:L 100-499 effective changed lines (tests excluded in mixed PRs). label Oct 17, 2026
@coderabbitai

coderabbitai Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e5d94a38-5f98-4d01-bdcb-2b00f9e62fbf
📥 Commits

Reviewing files that changed from the base of the PR and between 19265c5 and d491c43.

📒 Files selected for processing: 11
  • README.md
  • src/main/java/net/tfminecraft/geminfusion/ConfigLoader.java
  • src/main/java/net/tfminecraft/geminfusion/D20Roll.java
  • src/main/java/net/tfminecraft/geminfusion/GemNameCutoffs.java
  • src/main/java/net/tfminecraft/geminfusion/InfusedGemBuilder.java
  • src/main/java/net/tfminecraft/geminfusion/InfusionEvents.java
  • src/main/resources/config.yml
  • src/test/java/net/tfminecraft/geminfusion/D20RollTest.java
  • src/test/java/net/tfminecraft/geminfusion/GemNameCutoffsTest.java
  • src/test/java/net/tfminecraft/geminfusion/GemOutputTest.java
  • src/test/java/net/tfminecraft/geminfusion/InfusionEventsTest.java

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

📝 Summary

Summary by CodeRabbit

  • New Features
    • Gem names now reflect the result of their rolled stats, rather than necessarily matching the rarity drawn during infusion. Rarity chances determine the share of names each rarity receives.
    • Added a configurable modifier that affects how rolled stats are compared when assigning gem names.
    • Infusion announcements now reflect the rarity shown on the resulting gem.
  • Documentation
    • Clarified that a higher-rarity gem name does not necessarily mean the gem has stronger stats.

Gem names now reflect rolled-stat rankings within rarity-based name shares. Configuration sets the reference modifier and loads cut-offs. Gem building applies the selected name rarity to cosmetics and metadata. Infusion announcements use each output’s stored rarity.

Changes: Stat-Ranked Gem Names

Layer / File(s) Summary
Configure and calculate rarity name cut-offs
src/main/java/net/tfminecraft/geminfusion/D20Roll.java, src/main/resources/config.yml, src/main/java/net/tfminecraft/geminfusion/ConfigLoader.java, src/main/java/net/tfminecraft/geminfusion/GemNameCutoffs.java, src/test/java/net/tfminecraft/geminfusion/D20RollTest.java, src/test/java/net/tfminecraft/geminfusion/GemNameCutoffsTest.java, README.md
Configuration loads the name reference modifier and rarity shares. GemNameCutoffs calculates cut-offs from stat outcomes, with tests for limits, ties, and fallback cases. The README describes the relationship between stat rank and gem names.
Apply the name rarity when building gems
src/main/java/net/tfminecraft/geminfusion/InfusedGemBuilder.java, src/test/java/net/tfminecraft/geminfusion/GemOutputTest.java
Gem building uses the rolled stat to select the name rarity, then applies its cosmetics and stores its ID. The output test checks the resulting name and metadata.
Use each gem’s name rarity in announcements
src/main/java/net/tfminecraft/geminfusion/InfusionEvents.java, src/test/java/net/tfminecraft/geminfusion/InfusionEventsTest.java
Announcements use the rarity stored on each output, with a fallback to the drawn rarity when no configured rarity matches. The test checks announcement selection and text.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant ConfigLoader
  participant GemNameCutoffs
  participant InfusedGemBuilder
  participant InfusionEvents
  ConfigLoader->>GemNameCutoffs: load gems and rarities
  InfusedGemBuilder->>GemNameCutoffs: select rarity for rolled stat
  GemNameCutoffs-->>InfusedGemBuilder: return name rarity
  InfusedGemBuilder->>InfusedGemBuilder: apply cosmetics and store rarity ID
  InfusionEvents->>InfusionEvents: resolve rarity from output metadata
Loading

Suggested reviewers: ryanbarlow97

Merge Risk: ⚪ Minimal · up to d491c

No actionable issue remains; the change is ready to merge after normal checks.

- [ ] Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Results that tie on one stat can't be split between two names. When a
tie would push a rarer name past its chance, the whole tie now gets the
lower name, so Legendary (and Legendary plus Epic, and so on) never go
over their chances. A rarity whose best tie alone is too big is never
named, and the load log says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@XxFran10xX
XxFran10xX marked this pull request as ready for review October 17, 2026 10:30
@XxFran10xX

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Oct 17, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@XxFran10xX
XxFran10xX merged commit 8e8b2ff into main Oct 17, 2026
4 checks passed
@XxFran10xX
XxFran10xX deleted the fix/infused-gem-name-by-stat branch October 17, 2026 10:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 effective changed lines (tests excluded in mixed PRs).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant