Upgraded Weapons - UQcsse3200/2026-studio-4 GitHub Wiki
Overview
This page covers the Weapon Upgrades feature: how a weapon becomes upgraded, what each upgrade grants, and how the work is tested.
The shared upgrade system — per-weapon upgrade stats and the heavy attack pipeline (Weapons, Weapon Upgrades).
The upgraded Sword: a 360° heavy spin on K, stronger light sweep, and a fancier blade sprite.
The upgraded Knife: a three-hit heavy flurry on K, and a fancier knife sprite.
The upgraded Bow: a three-arrow heavy volley on K, and a fancier arrow sprite.
The QA terminal command upgrade sword|knife|bow [off].
An upgrade never edits the player's shared weapon stats, so upgrading one weapon can never buff another. Every weapon also swaps to a fancier sprite while upgraded, so an upgrade is recognisable at a glance.
Testing is divided into automated unit tests (what the code must do) and manual gameplay tests (what the player must see and feel). Every behaviour listed in the automated plan is enforced by a test in the repository — the test class is named above each table.
Design Summary
An upgrade gives a weapon four things: more light-attack damage, a heavy attack on K, a longer shared cooldown when that heavy attack is used, and an upgraded sprite. Values live in WeaponUpgradeComponent on the player, keyed by weapon.
Weapon
Light damage
Heavy damage
Heavy cooldown
Sword
×1.2
×1.35
×2 (1.0 s)
Knife
×1.2
×0.6 per slash, ×1.2 for the finisher
×3 (1.5 s)
Bow
×1.2
— (3 arrows at ×1 each)
×2 (heavy attack duration is instant)
Every upgraded sprite is an unedited crop of the same CC0 steel-weapons.png sheet, drawn at the same angle as the base sprite, so swapping one needs no rendering changes. Grid cells are recorded in core/assets/licenses/OPENGAMEART-ATTRIBUTION.md.
Weapon
Base sprite
Upgraded sprite
Sword
sword.png
sword_upgraded.png — winged golden guard
Knife
knife.png
knife_upgraded.png
Bow
throwing_knife.png
throwing_knife_upgraded.png — winged blade with a blue gem
Upgraded Sword
Property
Light (J)
Heavy (K)
Arc
90°, centred on facing
360° around the player
Duration
0.25 s
0.8 s
Blade hitbox
1.0 × 0.4
1.0 × 0.4 (unchanged)
Damage at base attack 10
12
14
Sprite
Upgraded winged sword while upgraded
Same
Upgraded Knife
The heavy attack is a three-hit flurry, aimed where the player faced when K was pressed.
Strike
Spawns at
Duration
Damage at base attack 10
Knockback
Slash 1 (right → left, 70°)
0.00 s
0.12 s
6
none
Slash 2 (left → right, 70°)
0.15 s
0.12 s
6
none
Finishing stab
0.30 s
0.15 s
12
1.5× the weapon's knockback
Only the finisher knocks back, so enemies stay in reach of all three hits. Switching weapons mid-flurry cancels the strikes still queued. While upgraded, the stab and every flurry strike are drawn with the upgraded knife sprite.
Upgraded Bow
The heavy attack fires three arrows at once instead of a stronger single one — the upgrade's power comes from arrow count, not per-arrow damage.
Property
Light (J)
Heavy (K)
Arrow count
1
3 (centre + ±15°)
Damage at base attack 10
12
10 per arrow
Each arrow's path
Checked independently; a blocked shot despawns silently
Same — a wall blocking the centre arrow does not stop the two side arrows
Sprite
Upgraded arrow while upgraded
Same, on all three arrows
Unlike the sword and knife, the bow's heavy attack has no separate hitbox shape or lifetime from the light shot — it is the same arrow, fired three times in a spread, each with its own wall check.
Test Environment
Unit testing: JUnit 5 and Mockito, run headlessly with the engine's GameExtension
Game testing: Desktop application
Light attack:J — Heavy attack:K — Movement:WASD
Debug terminal (F1) commands:weapon knife|sword|bow to equip; upgrade sword|knife|bow to apply an upgrade and upgrade sword|knife|bow off to revert; debug on to show hitbox outlines
Run all automated tests with:
cdsource
./gradlew :core:test
Last verified run: 17 Sept 2026 on task/126-bow-sprite-change — 1178 tests, 0 failures.
Automated Unit Test Plan
Shared Upgrade System
WeaponUpgradeComponentTest
Test
Purpose
Expected Result
shouldNotBeUpgradedInitially
Inspect a fresh component.
Nothing is upgraded, and every multiplier reads 1, so unupgraded weapons behave exactly as before.
It starts on its offset before any update runs, so delayed strikes never render in the wrong place.
Manual Gameplay Test Plan
Setup for every test below: run the game, open the debug terminal (F1), enter weapon sword, weapon knife or weapon bow to equip, enter debug on to see hitbox outlines, then close the terminal (F1).
Unupgraded Behaviour
Test
Steps
Expected Result
Sprint 1 sword
Start a run and attack with J without upgrading.
The original 90° sweep, blade and damage.
Sprint 1 knife
Equip the knife and attack with J.
The original stab.
Sprint 1 bow
Equip the bow and attack with J.
A single arrow with the original arrow sprite.
Heavy attack locked
Press K with each weapon.
The attack sound plays, but nothing spawns.
Upgraded Sword
Test
Steps
Expected Result
Apply the upgrade
Run upgrade sword.
The blade changes to the fancier winged sword on the next attack.
Stronger light attack
Attack an enemy with J before and after upgrading.
The same 90° sweep kills in fewer hits.
Heavy spin
Press K surrounded by enemies.
The blade sweeps a full circle around the player and hits enemies on every side.
Readable spin
Watch the spin at normal speed.
The full turn is easy to follow, and the blade stays pointed along its arc rather than looking tilted.
Shared cooldown
Press K, then immediately J.
The light attack is blocked until the longer cooldown ends.
Revert
Run upgrade sword off and attack.
The Sprint 1 sword and sprite return, and K is inert again.
Upgraded Knife
Test
Steps
Expected Result
Apply the upgrade
Run weapon knife, then upgrade knife.
J still stabs, now for more damage, drawn with the upgraded knife sprite.
Flurry
Press K next to an enemy.
Two slashes sweep across the front of the player in opposite directions, then a forward stab.
Enemies stay in reach
Flurry a single enemy.
The first two slashes do not push it away; only the final stab knocks it back.
Aim is locked
Press K, then turn immediately.
All three strikes keep the direction you faced when you pressed K.
No sprite flash
Watch the player while the flurry plays.
No knife sprite appears on top of the player between strikes.
Upgraded sprite on every strike
Watch the flurry closely.
Both slashes and the finisher use the upgraded knife sprite, not just the stab.
Switching mid-combo
Press K, then change weapons on the hotbar straight away.
The remaining strikes never appear, including after switching back.
Revert
Run upgrade knife off.
The base knife sprite returns and K goes back to sound only.
Upgraded Bow
Setup: equip with weapon bow, apply with upgrade bow.
Test
Steps
Expected Result
Apply the upgrade
Run upgrade bow.
J still fires a single arrow, now for more damage and drawn with the upgraded arrow sprite.
Heavy shot
Press K facing an enemy.
Three arrows fan out and can hit multiple enemies at once.
Upgraded sprite on every arrow
Watch a volley.
All three arrows use the upgraded sprite, including the two angled ones.
Blocked centre still fires sides
Stand next to a wall directly ahead, press K.
The straight shot is blocked; the two angled arrows still fire.
Revert
Run upgrade bow off.
J returns to a single, unboosted arrow with the base sprite; K is inert again.
Interaction With Other Features
Test
Steps
Expected Result
Hotbar
Switch weapons with the hotbar, upgraded and not.
Each weapon keeps its own upgrade state; only the equipped weapon attacks.
Player abilities
Activate Invisibility, then attack with each weapon.
Weapon sprites, including every flurry strike and volley arrow, fade with the player.
Stat buffs
Pick up a Strength Charm, then attack.
Upgraded damage scales on top of the buffed base attack.
Areas Not Covered by Automated Tests
Game feel and balance (spin and flurry timings, arrow spread, damage multipliers, cooldown lengths) is judged manually, not asserted. The values are constants and are expected to change with playtesting.
Sprite appearance is tested by the values passed to the sprite batch, not by pixels. Whether an upgraded weapon looks like an upgrade is a manual judgement.
Hitboxes stay axis-aligned while their sprites rotate, a pre-existing engine limitation. During the sword's spin, reach at the player's sides is slightly shorter than straight ahead. This is accepted, not tested.
The heavy attack has no dedicated player animation; that belongs to the upgrade animations ticket.
How upgrades are granted in normal play (pickup or shop) is not built yet. Anything granting one calls WeaponUpgradeComponent.setUpgraded(...), the same entry point the terminal command uses.
AI Declaration
This page was written with LLM assistance (Claude Code on Opus 5), generated from the weapon upgrade test suite and the team's pull requests, and reviewed before publishing.