feat(consumables): eating, drinking, and the three clocks #152
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/consumables"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Food and potions, which is what finally eats what Cooking makes. 163 rows
over one item op: 79 foods and 21 potion families in 84 doses.
What ships
Food — the cooked fish and meat, bread, the pie, pizza and cake chains
(a cake leaves two thirds, a pie leaves the dish), the two bowls, the seven
potatoes, kebabs, and the jug of wine. Pies carry their own skill boosts:
summer is +5 Agility and 10% run energy, wild is +5 Slayer and +4 Ranged,
admiral is +5 Fishing.
Potions — the four single-stat boosts and their supers, combat and super
combat, magic, the four flat non-combat boosts (agility, fishing, hunter,
magic essence), restore, super restore, prayer, energy, super energy,
stamina, and the Zamorak brew. A dose chain walks four down to one and leaves
a vial.
World.Energy.stamina/1andEnergy.gain/2have had no caller since June andnow have one, and
World.Content.StatBoost— the clock that walks a boostedskill back down — has had nothing to decay and now has tenants.
Three things worth a reviewer's attention
A potion's duration is not stored anywhere, and that was already true.
World.Stats.boost/4computes the percent of the base level and caps atbase-plus-boost, so a second dose of the same potion does nothing rather than
stacking;
StatBoostthen walks every boosted skill down one level a minute.A super attack at 60 is
+14and therefore lasts fourteen minutes. Bothhalves were written in June against no consumer. A stat potion is one line of
data here because of it.
The attack delay is neither
max/2nor a plain sum, and each of those iswrong in a different place. Combo eating is published as stacking — a shark
and a karambwan on the same tick is
3 + 2 = 5, whichmax/2answers asthree — while a player who eats during an ordinary weapon cooldown does not
have the cooldown lengthened by it, which a plain sum would do.
Contract.Consumable.swing/4keys on whether anything was already consumedthis same tick, which is the only reason the clocks carry a fourth field.
Six tests, because the wrong answers look right in the common case.
A row's
kindand itsverbare separate fields.kind(:foodor:potion) picks the clock and the shape of the sentence;verbis what theitem's own definition says and is what a click has to match. They come apart:
a jug of wine is food in every mechanical sense — heals 11, food clock,
gone in one gesture — and
1993's inventory actions are["Drink", "Drop"].Inferring the verb from the kind shipped it silently unclickable, falling
through to "Nothing interesting happens" and so indistinguishable from an
item nobody has written yet. The table's own cache test — every row's verb
must be one the item actually carries — caught it on its first run.
The one structural change
Eating is the first input in this engine whose rule is about when, and the
three clocks are absolute ticks.
Player.Dispatch.run/2has no tick and didnot need one, so rather than hand forty clauses an argument one of them uses,
every backpack op now routes through a new
Dispatch.item_op/3— followingthe precedent the drop op already set in
Player.Host— andContent.Item.interact/4becomes/5.One consequence worth knowing:
run/2's remaining:item_opclause is nowreached only by a container this server has not bound, which is what it
always meant.
The clocks live in
player.combat, besidenext_swingandin_combat_until— the absolute-tick clocks are already there, and three separate counters is
what makes combo eating possible, so it is where the concept belongs. No new
top-level field on
World.Player, which is at the 32-key cliff.Declined, with reasons
All of it is in
priv/data/consumables.exs's own header, where somebodyadding a row will be standing. None of the reasons is scheduling:
above the hitpoints base, and
StatBoostskips:hitpointsdeliberately.Shipping the heal without a decay leaves a player permanently over their
maximum. This is the largest single follow-on and it is one clock.
(1–10), cave eel (7–11), the snail meats; the cooked slimy eel is not stated
at all. Four of Cooking's own outputs land here and each is listed with its
reason in a test.
there is no poison, venom or dragonfire, so there is nothing to cure and
nothing to hold off. A stub that says "you feel better" and does nothing is
worse than the engine admitting it has no behaviour: the player cannot
detect the first.
raid potions — minigame-bound, and neither minigame is built.
and from content that does not exist. A data change the day it does.
shaker, and a roll that includes poisoning the eater.
Sourcing
Wiki, per the ported-constant convention, and it mattered: a cross-check
against an era-adjacent implementation disagreed in three places. Cooked meat
and chicken heal 3 and it says 4; manta ray heals 22; and its super
combat potion is
10 + 10%against the published5 + 15%— which agree at99 and nowhere else, so a wrong table would have been believable the whole way
up. Dating: food heals have never been rebalanced and the two wiki pages agree
row for row where they overlap, which is the check that was run rather than a
claim. The only family whose changes section reaches into its own boost is the
Zamorak brew, last moved 2014-04-24, three years before this cache.
Gates
Full suite 3623 tests, 1561 doctests, 60 properties, 0 failures.
mix credoclean.mix dialyzerreports exactly the two pre-existingguard_fails of #131 and no new ones.mix format --check-formattedflagsonly
test/support/login_packet.ex, which is #131's other half and wasdeliberately not touched.
Not done
No live sitting. The animation (
829, ten frames over 73 client cyclesagainst a three-tick action), the two sounds (
2393and2401, both presentin archive 4 and both resolving to a real head packet), and the exact message
strings are derived and tested but have not been watched from a real client.
Cache.Seqdoes not decode frame sounds, so if829carries one of its own aplayer hears it twice — the same decoder gap already recorded for sound.
Bots cannot eat.
Bot.Goalshas no food step, so a fighter that runs outof hitpoints still has no answer, which is a real gap now that pkers roam.
Herblore is unbuilt, so not one potion is made in this world — every
family is bank- or shop-only. The mirror of Cooking's finding that a skill's
coverage is not its reachability, from the other side: the consumable is built
and its source is not.