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
|
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
|
area. Rings for offence (swing speed, crit, power), amulets for defence (max
|
||||||
HP, ward, regen), trinkets for the rest (XP, double gathering,
|
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
|
- **Tools and stations:** smiths make every tool: one per gathering skill and
|
||||||
one per crafting skill (chisel, gem drill, hammer, cleaver, mortar and
|
one per crafting skill (chisel, gem drill, hammer, cleaver, mortar and
|
||||||
pestle, awl, shears). Builders make every station, a second slot for each
|
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",
|
GEM_ROCKS = {"mine_stone": "quartz", "mine_copper": "quartz", "mine_iron": "garnet", "mine_coal": "amethyst",
|
||||||
"mine_mithril": "sapphire", "mine_adamantite": "emerald", "mine_runite": "diamond"}
|
"mine_mithril": "sapphire", "mine_adamantite": "emerald", "mine_runite": "diamond"}
|
||||||
PROSPECT = ["stone", "iron_ore", "coal", "mithril_ore", "adamantite_ore", "runite_ore"]
|
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
|
# key, slot, noun, stat, bonus by tier, bands, gems, shards, level above the tier, glyph
|
||||||
JEWELLERY = [
|
JEWELLERY = [
|
||||||
("haste", "ring", "ring of haste", "haste", [5, 7, 8, 9, 10, 11], 1, 1, 1, 2, "diamond-ring"),
|
("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"),
|
("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"),
|
("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"),
|
("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).
|
# How each jewellery bonus reads: name, unit, glyph, tint (and a sign, if it takes away).
|
||||||
JEWEL_STATS = {
|
JEWEL_STATS = {
|
||||||
|
|
@ -259,7 +260,7 @@ JEWEL_STATS = {
|
||||||
"regen": {"name": "HP regen", "unit": "%", "glyph": "heart-plus", "tint": "#e06a8a"},
|
"regen": {"name": "HP regen", "unit": "%", "glyph": "heart-plus", "tint": "#e06a8a"},
|
||||||
"xp": {"name": "XP", "unit": "%", "glyph": "sparkles", "tint": "#f0d060"},
|
"xp": {"name": "XP", "unit": "%", "glyph": "sparkles", "tint": "#f0d060"},
|
||||||
"double": {"name": "Double gathering", "unit": "%", "glyph": "clover", "tint": "#5fae5a"},
|
"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_ore"] = {"name": "Silver ore", "icon": "⚪", "value": 6}
|
||||||
ITEMS["silver_bar"] = {"name": "Silver bar", "icon": "🥈", "value": 15, "tier": 1}
|
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"),
|
{"gold_bar": 1}, group="Bars"),
|
||||||
]
|
]
|
||||||
for tier, (gem, gem_name, *_rest) in enumerate(GEMS):
|
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 {})}
|
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,
|
actions.append(_action(f"jc_{gem}_{key}", "jewelcrafting", f"{gem_name} {noun}", TIER_LEVELS[tier] + offset,
|
||||||
35 + 5 * (bands + gems) + 2 * tier,
|
35 + 5 * (bands + gems) + 2 * tier,
|
||||||
round([15, 32, 52, 75, 100, 130][tier] * (bands + gems) / 2),
|
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
|
return actions
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2064,7 +2065,7 @@ def _complete(world: dict, player: dict, action: dict, now: float, rng: random.R
|
||||||
cls = CLASSES[player["cls"]]
|
cls = CLASSES[player["cls"]]
|
||||||
lucky = bool(action["outputs"]) and (
|
lucky = bool(action["outputs"]) and (
|
||||||
action["skill"] in cls["craft"] or (player["cls"] == "miner" and action["skill"] == "mining")
|
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()}
|
outputs = {item: qty * (2 if lucky else 1) for item, qty in action["outputs"].items()}
|
||||||
if lucky:
|
if lucky:
|
||||||
summary["lucky"] += 1
|
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():
|
for item, qty in action["outputs"].items():
|
||||||
outputs[item] += qty
|
outputs[item] += qty
|
||||||
summary["lucky"] += 1
|
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():
|
for item, qty in action["outputs"].items():
|
||||||
outputs[item] += qty
|
outputs[item] += qty
|
||||||
summary["lucky"] += 1
|
summary["lucky"] += 1
|
||||||
|
|
|
||||||
|
|
@ -1723,6 +1723,20 @@ class JewelcraftingTest(unittest.TestCase):
|
||||||
p["equip"]["ring"] = "garnet_might"
|
p["equip"]["ring"] = "garnet_might"
|
||||||
self.assertEqual(game.combat_power(p), game.combat_power({**p, "equip": {**p["equip"], "ring": None}}) + 4)
|
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):
|
def test_miners_cut_jewels(self):
|
||||||
self.assertIn("jewelcrafting", game.CLASSES["miner"]["fast"])
|
self.assertIn("jewelcrafting", game.CLASSES["miner"]["fast"])
|
||||||
self.assertIn("jewelcrafting", game.CLASSES["miner"]["craft"])
|
self.assertIn("jewelcrafting", game.CLASSES["miner"]["craft"])
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue