Table of Contents

Class DurabilityLifetimeTests

Namespace
GrindFest
Assembly
GrindFest.dll

How much time a durability pool actually buys, measured - the unit the whole ladder is authored in (DURABILITY_DESIGN.md).

public class DurabilityLifetimeTests : BalanceProbe
Inheritance
object
DurabilityLifetimeTests
Inherited Members

Remarks

The pools are sized in minutes, so the only thing that can check the design is the rate: blows per minute, and what each blow costs each side. The two sides do not pay the same amount, and that is the whole point of charging per blow instead of per tick:

  • the attacker's weapon pays for the whole blow, blocked or not ("swinging into a shield is work");
  • a shield pays only for the part it stopped, so a fast attacker with a cheap weapon is the worst case for the defender's shield and a slow heavy hitter is the mildest;
  • armour pays only for what got through, so a fully blocked fight never touches it.

The matchup is a level-1 hero with a Stick against the one monster in the game that can hold block. Measured 2026-09-23 over every character prefab: Skeleton Warrior is the only monster with an offhand drop table ("Shields 1") and one of only two things carrying BlockSkill - the other is the player's own Warrior class. The stance exists but is rarely held, and this doc claimed otherwise until 2026-09-23. "A shield bearer blocks every frontal blow it receives" is false in a standing melee fight, and the measurement is the reason this class now says so: ShouldBlock is REACTIVE, not a stance - IsEnemyAttackThreatening requires the enemy to be currently using a skill (if (!_currentTarget.Character.SkillUser.IsUsingSkill) return false;) and PerformBlock drops the stance the moment that ends, so against a fast Lv1 weapon the window rarely lines up. BlockSkill.OnGetHit then only absorbs a blow whose source is within 45 degrees of the blocker's forward, and nothing turns the blocker (the Slerp that would is commented out in BlockSkill.Tick), which in play is satisfied only because the monster walked at its target first - the owner verified a normally spawned warrior blocks. Measured over 7-8 blow samples in these tests: 0-2 blocks, i.e. mostly the passive BlockChance roll. So the probe below measures what actually happens in a fight, not "a held block"; AHeldBlockChargesTheShieldAndSparesTheArmour is the one that starts the stance on purpose and verifies what a block does.

Level 1 and rank None are not arbitrary either: measured 2026-09-23, all 573 items in the database are level 1 and 562 are rank None, so that is the only tier that exists in play.

Methods

AHeldBlockChargesTheShieldAndSparesTheArmour()

A held block, actually verified: the blow is stopped, the shield pays for what it stopped, the attacker's weapon still pays the whole blow, and the armour is spared because nothing got through it.

FragileArmourBreaksOnItsFirstHit()
StickVsHeldBlock()

The rates on the pools as they exist: what one blow costs the stick and the plank, and how many minutes of continuous fighting each would last at that rate.