Repository navigation
Sword
The Sword is the melee crowd-control weapon: instead of stabbing one spot like the Knife, it sweeps a 90° arc around the player over the course of the swing. It covers a much larger area at the cost of a slower attack.
SwordWeaponComponent extends WeaponComponent, so cooldown gating and damage come from the shared WeaponStatsComponent: damage is round(baseAttack × multiplier), meaning Strength Charm buffs scale sword hits.
Each swing spawns a blade-shaped hitbox (1.0 × 0.4 m) through HitboxFactory and drives it along an arc:
- The swing starts half the arc before the aim direction (45° for the 90° arc), so the direction the player is facing sits in the middle of the sweep.
- A
SweepComponenton the hitbox interpolates the angle from start to end over the swing's duration (0.5 s), updating theFollowComponentoffset each frame. Because the offset is relative to the player, the whole arc moves with them while they walk. - The hitbox is transposed to match the attack axis and rides the arc at a reach just outside the player's edge.
The swing draws a sword sprite that turns with the arc: SweepComponent also rotates the sprite each frame so the blade points along the swing, and a visual offset pulls the sprite back so the handle stays at the player's hand rather than the blade's midpoint riding the arc. The sprite is sized independently of the thin collision hitbox — see Weapon Rendering for how that works.
Upgrading the sword does not change the sweep. It makes the existing swing hit harder and unlocks a heavy attack on K: the same blade swept a full 360° around the player, like a spinning blade. The player chooses which to use — J for the quick arc in front, K for the spin that clears every side at once.
Upgrade state lives in WeaponUpgradeComponent on the player rather than in the sword, and the bonuses are applied when a swing resolves its damage and cooldown. The shared WeaponStatsComponent is never edited, so upgrading the sword cannot buff the Knife or Bow. See Weapon Upgrades for the shared system.
What the upgrade grants:
-
Light attack (
J): the same 90° arc, blade and 0.25 s swing, dealing ×1.2 damage. -
Heavy attack (
K): a 360° spin using the same 1.0 × 0.4 m blade, over a slower 0.8 s swing so the full turn reads clearly, dealing ×1.35 damage to every enemy the blade passes through. - Sprite: both attacks draw a fancier winged sword cut from the same sprite sheet, so an upgraded sword is recognisable at a glance.
The spin is built from the same parts as the normal swing: it starts half the arc before the aim direction (180° behind the player), and a SweepComponent carries the blade through the full turn, rotating the sprite as it goes. Because the arc is a parameter rather than a constant, the light and heavy attacks share one code path.
A heavy attack sets the shared cooldown to ×2 (1.0 s at attack speed 1), so the spin cannot be spammed and a light attack cannot be chained straight out of one. The cooldown can never be shorter than the spin itself, so an attack-speed buff can never start a second spin while one is still swinging.
Without the upgrade the sword behaves exactly as it did in Sprint 1, and K does nothing but play the attack sound.
SwordWeaponComponentTest covers the sword in both states.
Unupgraded, it covers the sweeping hitbox (follow and sweep together), axis transposition, the arc starting half a turn before the aim, sprite alignment and rotation through the swing, and damage scaling. Two further tests pin the sword to its Sprint 1 behaviour: that a swing keeps its original blade size, arc and damage before any upgrade, and that K spawns nothing and starts no cooldown while the sword is unupgraded.
Upgraded, it covers the boosted light damage with an unchanged 90° arc, the heavy spin using the same blade through a full 360° turn, the spin running slower than the light sweep, the heavy damage multiplier, the doubled shared cooldown blocking a following light attack, and the cooldown floor that stops an attack-speed buff starting a second spin mid-swing. Two more cover the sprite: the base blade while unupgraded, the winged blade for both attacks once upgraded. A final test reverts the upgrade and confirms the Sprint 1 sword, damage and sprite all return.
SweepComponentTest covers the arc interpolation shared by both attacks: start angle on the first frame, midpoint at half duration, clamping at the end, safe handling of odd frame times, and that the blade's position is updated in the same frame as its rotation, so fast sweeps never look tilted. WeaponComponentTest covers the heavy attack pipeline that the spin is built on, and WeaponUpgradeComponentTest and UpgradeCommandTest cover the upgrade system and the QA command. See the Weapons Test Plan for the full table.
Run the game, open the debug terminal (F1), type weapon sword and press Enter to equip the sword. Type debug on to see hitbox outlines, then close the terminal (F1) to return to the game. Move with WASD, attack with J and heavy attack with K.
Unupgraded. The hitbox outline should sweep a visible 90° arc around the player centred on the facing direction, with the sword sprite turning through the swing and its handle staying near the player. Enemies anywhere along the arc take damage. Attacking while walking moves the whole arc with the player — clearly distinct from the Knife's fixed stab. Pressing K plays the attack sound but spawns no hitbox, since the heavy attack is locked until the sword is upgraded.
Upgraded. Reopen the terminal and type upgrade sword to apply the upgrade immediately — no pickup or shop needed. Attack with J: the same 90° arc, now drawn with the winged sprite and killing enemies in fewer hits. Press K while surrounded: the blade sweeps a full circle around the player, damaging enemies on every side, slowly enough to follow the whole turn. Press J straight after the spin and it is blocked until the longer cooldown ends.
Reverting. Type upgrade sword off and attack again. The Sprint 1 blade, sprite and damage return, and K goes back to playing only the attack sound — confirming the upgrade is fully reversible and the base sword is untouched.
This page was written with LLM assistance (Claude Code on Opus 5), generated from the sword implementation and its test suite, and reviewed before publishing.