The weapon table: what the scriber can fight with, and what each costs.
A weapon is a plain map with the fields in t/0. Scriber.Game reads them like this:
hits— swings per attack; a later swing is skipped if an earlier one killed the targetpower— replaces the attacker's own power for the rolldefence— the player's mitigation while holding itpierce— armour the swing ignoresparry— probability in0.0..1.0of turning an incoming hit aside entirelystun— probability in0.0..1.0that a hit costs the target its next action
Damage per swing is max(1, power + d4 - max(target_defence - pierce, 0) - 1), and armour
applies to each swing separately, so a multi-hit weapon loses more to a heavily armoured
target than a single-hit one of equal total power.
Every weapon costs the same; the choice is which, not how much. Upgrades to power and defence cost more the more of them have been bought.
Example
Scriber.Gear.fetch(:daggers).hits
#=> 2
Scriber.Gear.power_cost(2)
#=> 75GEAR_DESIGN.md at the repository root records the modelling behind these numbers.
Summary
Functions
Every equippable name, including :unarmed. Order is unspecified.
The shard price of a weapon. The same 45 for every weapon.
The shard price of the next point of defence, given owned points already bought.
The weapon entry for name, with :name set on it.
The weapon name matching a string a player typed, or nil if none does.
The shard price of one patch.
The shard price of the next point of power, given owned points already bought.
The four buyable weapons, in the order the forge lists them. Excludes :unarmed.
What selling a weapon back pays: half its cost/1, rounded down.
The shard price of a fuse, a decoy or a pulse.
Types
@type name() :: :unarmed | :two_hand | :shield | :daggers | :mace
@type t() :: %{ name: name(), label: String.t(), hits: pos_integer(), power: pos_integer(), defence: non_neg_integer(), pierce: non_neg_integer(), parry: float(), stun: float(), blurb: String.t() }
Functions
@spec all() :: [name()]
Every equippable name, including :unarmed. Order is unspecified.
@spec cost(name()) :: pos_integer()
The shard price of a weapon. The same 45 for every weapon.
@spec defence_cost(non_neg_integer()) :: pos_integer()
The shard price of the next point of defence, given owned points already bought.
Rises linearly: 30 * (owned + 1).
The weapon entry for name, with :name set on it.
name must be one of all/0; anything else raises a FunctionClauseError.
The weapon name matching a string a player typed, or nil if none does.
The string is trimmed, downcased, and has - replaced with _ before it is matched
against both the atom names and the labels, so "Sword+Shield" and "shield" both give
:shield, and "two-hand" gives :two_hand.
@spec patch_cost() :: pos_integer()
The shard price of one patch.
@spec power_cost(non_neg_integer()) :: pos_integer()
The shard price of the next point of power, given owned points already bought.
Rises linearly: 25 * (owned + 1).
@spec purchasable() :: [name()]
The four buyable weapons, in the order the forge lists them. Excludes :unarmed.
@spec resale(name()) :: pos_integer()
What selling a weapon back pays: half its cost/1, rounded down.
@spec tool_cost(:fuse | :decoy | :pulse) :: pos_integer()
The shard price of a fuse, a decoy or a pulse.