Jewellery tabs by slot, loupe doubles crafts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
8d6d23261e
commit
2816ca8606
3 changed files with 25 additions and 8 deletions
|
|
@ -50,7 +50,7 @@ Alpha. One season, bandit raids plus two friendly events, six buildings.
|
|||
without a smithy. Past quartz each piece needs a shard from that tier's
|
||||
area. Rings for offence (swing speed, crit, power), amulets for defence (max
|
||||
HP, ward, regen), trinkets for the rest (XP, double gathering,
|
||||
masterwork).
|
||||
double crafting), each in its own tab.
|
||||
- **Tools and stations:** smiths make every tool: one per gathering skill and
|
||||
one per crafting skill (chisel, gem drill, hammer, cleaver, mortar and
|
||||
pestle, awl, shears). Builders make every station, a second slot for each
|
||||
|
|
|
|||
17
game.py
17
game.py
|
|
@ -236,7 +236,8 @@ PROSPECT_ODDS = 0.15 # ...for this chance at its gem
|
|||
GEM_ROCKS = {"mine_stone": "quartz", "mine_copper": "quartz", "mine_iron": "garnet", "mine_coal": "amethyst",
|
||||
"mine_mithril": "sapphire", "mine_adamantite": "emerald", "mine_runite": "diamond"}
|
||||
PROSPECT = ["stone", "iron_ore", "coal", "mithril_ore", "adamantite_ore", "runite_ore"]
|
||||
# Rings for offence, amulets for defence, trinkets for everything else.
|
||||
# Rings for offence, amulets for defence, trinkets for everything else; each its own tab.
|
||||
JEWEL_GROUPS = {"ring": "Rings", "amulet": "Amulets", "trinket": "Trinkets"}
|
||||
# key, slot, noun, stat, bonus by tier, bands, gems, shards, level above the tier, glyph
|
||||
JEWELLERY = [
|
||||
("haste", "ring", "ring of haste", "haste", [5, 7, 8, 9, 10, 11], 1, 1, 1, 2, "diamond-ring"),
|
||||
|
|
@ -247,7 +248,7 @@ JEWELLERY = [
|
|||
("mending", "amulet", "amulet of mending", "regen", [10, 20, 30, 40, 50, 60], 2, 1, 2, 8, "tribal-pendant"),
|
||||
("hourglass", "trinket", "hourglass", "xp", [2, 3, 5, 6, 8, 10], 1, 2, 1, 5, "hourglass"),
|
||||
("charm", "trinket", "lucky charm", "double", [2, 3, 4, 5, 6, 8], 1, 2, 1, 5, "clover"),
|
||||
("loupe", "trinket", "loupe", "masterwork", [2, 3, 4, 4, 5, 6], 1, 2, 1, 5, "magnifying-glass"),
|
||||
("loupe", "trinket", "loupe", "craft_double", [2, 3, 4, 4, 5, 6], 1, 2, 1, 5, "magnifying-glass"),
|
||||
]
|
||||
# How each jewellery bonus reads: name, unit, glyph, tint (and a sign, if it takes away).
|
||||
JEWEL_STATS = {
|
||||
|
|
@ -259,7 +260,7 @@ JEWEL_STATS = {
|
|||
"regen": {"name": "HP regen", "unit": "%", "glyph": "heart-plus", "tint": "#e06a8a"},
|
||||
"xp": {"name": "XP", "unit": "%", "glyph": "sparkles", "tint": "#f0d060"},
|
||||
"double": {"name": "Double gathering", "unit": "%", "glyph": "clover", "tint": "#5fae5a"},
|
||||
"masterwork": {"name": "Masterwork", "unit": "%", "glyph": "anvil", "tint": "#d07a3c"},
|
||||
"craft_double": {"name": "Double crafting", "unit": "%", "glyph": "anvil", "tint": "#d07a3c"},
|
||||
}
|
||||
ITEMS["silver_ore"] = {"name": "Silver ore", "icon": "⚪", "value": 6}
|
||||
ITEMS["silver_bar"] = {"name": "Silver bar", "icon": "🥈", "value": 15, "tier": 1}
|
||||
|
|
@ -867,12 +868,12 @@ def _jewel_actions() -> list[dict]:
|
|||
{"gold_bar": 1}, group="Bars"),
|
||||
]
|
||||
for tier, (gem, gem_name, *_rest) in enumerate(GEMS):
|
||||
for key, _slot, noun, _stat, _bonus, bands, gems, shards, offset, _glyph in JEWELLERY:
|
||||
for key, slot, noun, _stat, _bonus, bands, gems, shards, offset, _glyph in JEWELLERY:
|
||||
inputs = {BANDS[tier]: bands, gem: gems, **({reagent("jewel", tier): shards} if tier else {})}
|
||||
actions.append(_action(f"jc_{gem}_{key}", "jewelcrafting", f"{gem_name} {noun}", TIER_LEVELS[tier] + offset,
|
||||
35 + 5 * (bands + gems) + 2 * tier,
|
||||
round([15, 32, 52, 75, 100, 130][tier] * (bands + gems) / 2),
|
||||
inputs, {f"{gem}_{key}": 1}, group=gem_name))
|
||||
inputs, {f"{gem}_{key}": 1}, group=JEWEL_GROUPS[slot]))
|
||||
return actions
|
||||
|
||||
|
||||
|
|
@ -2064,7 +2065,7 @@ def _complete(world: dict, player: dict, action: dict, now: float, rng: random.R
|
|||
cls = CLASSES[player["cls"]]
|
||||
lucky = bool(action["outputs"]) and (
|
||||
action["skill"] in cls["craft"] or (player["cls"] == "miner" and action["skill"] == "mining")
|
||||
) and rng.random() < LUCKY_CHANCE + gear_bonus(player, "masterwork") / 100
|
||||
) and rng.random() < LUCKY_CHANCE
|
||||
outputs = {item: qty * (2 if lucky else 1) for item, qty in action["outputs"].items()}
|
||||
if lucky:
|
||||
summary["lucky"] += 1
|
||||
|
|
@ -2072,7 +2073,9 @@ def _complete(world: dict, player: dict, action: dict, now: float, rng: random.R
|
|||
for item, qty in action["outputs"].items():
|
||||
outputs[item] += qty
|
||||
summary["lucky"] += 1
|
||||
if action["skill"] in GATHERING and rng.random() < gear_bonus(player, "double") / 100:
|
||||
# Lucky charm doubles gathering, loupe doubles crafting, for any class.
|
||||
jewel = "double" if action["skill"] in GATHERING else "craft_double" if action["skill"] in CRAFTING else None
|
||||
if jewel and action["outputs"] and rng.random() < gear_bonus(player, jewel) / 100:
|
||||
for item, qty in action["outputs"].items():
|
||||
outputs[item] += qty
|
||||
summary["lucky"] += 1
|
||||
|
|
|
|||
|
|
@ -1723,6 +1723,20 @@ class JewelcraftingTest(unittest.TestCase):
|
|||
p["equip"]["ring"] = "garnet_might"
|
||||
self.assertEqual(game.combat_power(p), game.combat_power({**p, "equip": {**p["equip"], "ring": None}}) + 4)
|
||||
|
||||
def test_loupe_doubles_any_class_crafts(self):
|
||||
self.ann["xp"]["jewelcrafting"] = game.XP_TABLE[15]
|
||||
for loupe, rings in ((None, 1), ("quartz_loupe", 2)):
|
||||
self.ann["equip"]["trinket"] = loupe
|
||||
self.ann["bank"] = {"copper_bar": 1, "quartz": 1}
|
||||
game.start_action(self.world, self.ann, "jc_quartz_haste", T0)
|
||||
game.process_player(self.world, self.ann, T0 + 1000, Always())
|
||||
self.assertEqual(self.ann["bank"], {"quartz_haste": rings})
|
||||
|
||||
def test_jewellery_tabs_by_slot(self):
|
||||
self.assertEqual(game.ACTION_BY_ID["jc_garnet_haste"]["group"], "Rings")
|
||||
self.assertEqual(game.ACTION_BY_ID["jc_diamond_warding"]["group"], "Amulets")
|
||||
self.assertEqual(game.ACTION_BY_ID["jc_quartz_loupe"]["group"], "Trinkets")
|
||||
|
||||
def test_miners_cut_jewels(self):
|
||||
self.assertIn("jewelcrafting", game.CLASSES["miner"]["fast"])
|
||||
self.assertIn("jewelcrafting", game.CLASSES["miner"]["craft"])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue