Story, Revival , Defense and Loot Generation Sprint 3 - UQcsse3200/2026-studio-1 GitHub Wiki
Sprint 3's main feature is Weapon Scaling and Upgrades. On the loot side, this meant three things:
-
Weapon rarity comes from the tier system. The loot table now reads each tier's weight from
WeaponTier, so new weapon types and tiers appear in loot automatically. - Upgrade Stones. A new loot item that triggers the weapon upgrade, so the upgrade progression can actually be used in game.
- Death loot for Hero Revival. When the hero dies, everything they carried is dropped where they died, so the next hero can go back for it.
For how loot is placed in a level (ground tiles, seeds, the starter row), see Loot Generation Sprint 2. That part is unchanged.
In Sprint 2, LootTable kept its own copy of the tier weights ({60, 30, 10}). Changing the weights in WeaponTier had no effect on loot.
Now LootTable.createDefault() builds the weapon entries straight from the tier system:
- It loops over every
WeaponTypeand everyWeaponTier. - Each entry's weight is
WeaponTier.getLootWeight()(currently 60, 30 and 10), so a tier 3 weapon is about one in ten weapon drops. - A new weapon type added to
WeaponType, or a new tier added toWeaponTier, shows up in the loot table with no change toLootTable.
Potions keep their own tier weights (POTION_TIER_WEIGHTS, also 60/30/10). Their strength is scaled by ConsumableGenerator, not by weapon tiers, so adding a weapon tier should not also create a new potion tier.
The standard table now holds:
| Entry | Tiers | Weight |
|---|---|---|
| Each potion (5 types) | 1, 2, 3 | 60 / 30 / 10 |
| Each weapon (sword, bow, dagger) | every WeaponTier
|
WeaponTier.getLootWeight() |
| Upgrade Stone | 1 only | 40 |
| Shield | none | 10 |
Rolls are still seeded, so the same seed gives the same loot.
Weapon upgrades are worked out by WeaponUpgrader (see the weapon tiers work in #214), but nothing in the game called it. The Upgrade Stone is the in-game trigger.
- Upgrade Stones drop from the loot table. They are rarer than any single potion (weight 40, compared with 100 for each potion type across its tiers). One also appears in the starter loot row, which spawns one of every consumable.
- The player holds the weapon they want to upgrade, then presses the stone's number key.
- The weapon goes up one tier, and the player is holding the upgraded weapon straight away. The weapon HUD and in-hand sprite update automatically.
Examples:
- Bow: tier 1 fires 1 arrow, tier 2 fires 5, tier 3 fires 10.
- Sword: each tier has more damage, reach and knockback.
- Dagger: a dagger turns into a sword on its first upgrade (tier 1 dagger, then tier 2 sword, then tier 3 sword).
A stone used on the tier 1 bow: the HUD shows a tier 2 bow, and one shot fires 5 arrows in a spread.

A stone used on 20 tier 1 daggers: they become 20 tier 2 swords, split into two stacks of 10 because a sword stack holds 10.

- One stone upgrades the whole stack. 20 tier 1 daggers become 20 tier 2 swords, not one sword.
-
The stone is never wasted. Like a health potion at full health, the stone stays in the inventory if:
- the weapon is already at its highest tier,
- no weapon has been held yet, or the held weapon has since been dropped or thrown,
- there is not enough room for the upgraded stack. For example, 20 daggers fit in one slot, but 20 swords need two because a sword stack holds 10.
The stone is a consumable, so pickup, stacking, dropping on death and saving all work the same way as potions.
flowchart TD
A[Player holds a weapon] --> B[ConsumableUseComponent remembers that slot]
B --> C[Player presses the stone's number key]
C --> D[The stone's slot is selected, then useItem fires]
D --> E[WeaponUpgradeEffect looks up the remembered weapon slot]
E --> F{Weapon there, not max tier, enough room?}
F -- no --> G[Stone is kept]
F -- yes --> H[WeaponUpgrader upgrades each weapon in the stack]
H --> I[Upgraded weapons go back into the inventory and are selected]
I --> J[Stone is used up, weaponUpgraded event fires]
Why the stone needs to remember the weapon: pressing a number key both selects that slot and uses the item in it. By the time the stone is used, the stone's own slot is selected. ConsumableUseComponent listens for activeSlotChanged and remembers the last slot that held a weapon, and that is the weapon the stone upgrades.
Why weapons are added one at a time: when the inventory splits a large quantity across several slots, it builds the extra stacks as plain items rather than weapons. Upgrading and adding each weapon separately keeps every stack a real WeaponItem.
| Class | Responsibility |
|---|---|
WeaponUpgradeEffect |
The stone's effect: upgrades the held weapon stack with WeaponUpgrader and puts it back in the inventory |
ConsumableUseComponent |
Uses consumables, and now remembers the last weapon slot the player selected |
ConsumableType.UPGRADE_STONE |
The stone's type and sprite. isPotion() separates it from the potions |
LootTable |
Adds the stone once at tier 1 with weight 40 |
Hero Revival is a core loop in Sprint 3: the hero dies, their loot drops at the death spot, a new hero spawns, and the player can travel back to collect the old hero's loot.
The death drop is done by DeathLootDropComponent on the player (merged in #263):
- On the
deathevent, every inventory slot, all gold and any held shield are dropped as loot at the death spot, and the inventory is emptied so nothing is duplicated. - The drop happens only once, even though
deathcan fire several times for one death (CombatStatsComponentfires it on every hit at zero health, andDeathStateComponentfires it again). - The drop waits until after the current physics step. Death can be triggered from inside a Box2D collision callback, such as an enemy's touch attack, and the physics world is locked during that callback, so creating loot bodies there would fail.
- On Try Again, the dead hero is removed and a brand-new hero is created in the same room, so it starts with a fresh inventory, not the old one. Because the room is kept, the dropped loot stays where the hero died. Dropped loot never despawns.
The new hero walking back to the previous hero's loot, still lying where they died:

The loot-side design for this was worked out in #258, which was closed once #263 delivered the same behaviour.
-
LootTableTest: weapon drops follow theWeaponTierweights (within 5%), every weapon type can be found at every tier, every rolled weapon has the damage, attack speed, knockback and range its tier defines, higher tiers are rarer, the same seed rolls the same loot, and the Upgrade Stone drops only at tier 1 and less often than a tier 1 health potion. -
WeaponUpgradeEffectTest(13 tests), using the same select-then-use flow as the keyboard:- the held weapon goes up one tier, the stone is used up, and the weapon is selected again
- the bow gets more arrows
- the weapon selected before the stone is the one upgraded
- every weapon in a stack is upgraded, and daggers turning into swords split into two real weapon stacks
- the stone is kept at max tier, when no weapon was held, when the held weapon is gone, and when there is no room
- the
weaponUpgradedevent fires
-
ConsumableEffectIntegrationTest: every potion still affects the player. The stone is skipped there because it acts on a weapon. -
DeathLootDropComponentTest: inventory and gold drop on death, repeated death events drop only once, and missing components do not throw. -
In-game playtest on
mainafter the Upgrade Stone merged: the tier 2 bow fires 5 arrows, 20 daggers become 20 tier 2 swords, dying drops every stack and all gold at the death spot, and the revived hero (with a fresh starter kit) walks back and collects them.
-
Gold over 99 is cut down on death.
ItemDropComponent.dropGold()builds the gold pile with a maximum stack of 99, so a hero who dies with more than 99 gold loses the rest. The player starts with 50 gold, so this is reachable. Fix: use the gold amount as the pile's maximum stack size. - Death loot piles share one spot. Each stack is dropped at the same position beside the hero, so the piles overlap.
- Death loot is not tied to its room. Dropped loot is registered directly with the entity service rather than with the room. If the player leaves the room before collecting it, it is not cleaned up with the room, so it can appear at the same coordinates in the next room.
- The Upgrade Stone sprite is a placeholder (a 32x32 purple gem with a gold arrow).
Sprint 3 expanded the existing weapon tier system so that higher tiers provide meaningful changes to weapon statistics and behaviour. The work focused on Tier 1–3 progression, tier-based stat scaling, projectile-count scaling, weapon upgrades, weapon transformations and balancing.
Weapon tier information is centralised through WeaponTier, WeaponStats and WeaponItem. The tier system supports weapon properties including damage, attack speed, range, knockback, projectile count and weapon form.
Keeping these values within the tier/stat system allows the other weapon systems to retrieve the appropriate statistics for the weapon's current tier.
Projectile count was added as a tier-dependent weapon statistic.
| Bow Tier | Projectile Count |
|---|---|
| Tier 1 | 1 |
| Tier 2 | 5 |
| Tier 3 | 10 |
getProjectileCount() exposes the projectile count through the weapon tier/item system so that the combat implementation can retrieve the appropriate value for the current bow tier.
This allows bow upgrades to change attack behaviour rather than only increasing numerical statistics.
WeaponUpgrader implements progression between weapon tiers:
Tier 1 → Tier 2 → Tier 3
When a weapon is upgraded, the next tier determines the statistics and behaviour used by the other weapon systems.
The upgrade system also supports the agreed dagger-to-sword transformation:
Tier 1 Dagger → Tier 2 Sword → Tier 3 Sword
The Upgrade Stone described earlier on this page provides the in-game trigger for the upgrade, while WeaponUpgrader contains the underlying tier-progression logic.
Fixed dagger statistics that were incorrectly hardcoded to Tier 1. Damage, attack speed, knockback and range now use the dagger's actual tier statistics.
The dagger upgrade path was also corrected so that the first upgrade transforms a Tier 1 Dagger → Tier 2 Sword, followed by a Tier 3 Sword, matching the agreed Sprint 3 design.
Fixed the weapon HUD so that it refreshes correctly when switching between sword, bow and dagger. The HUD label colour was also changed from unreadable dark text to white to improve visibility.
Playtesting identified that higher-tier bows produced excessive total damage when combined with multi-projectile scaling.
Bow damage-per-arrow was rebalanced from 70/140/210 to 10/20/30 across Tier 1–3 so that the increased projectile count did not make higher-tier bows disproportionately powerful.
The tier and upgrade system integrates with the other Sprint 3 weapon features:
- Combat: reads tier-dependent weapon statistics and projectile counts.
- Loot: uses weapon tier information for weapon generation and rarity.
-
Upgrade Stones: trigger progression through
WeaponUpgrader. - Inventory/HUD: reflects the currently equipped/upgraded weapon and its tier.
- Rendering: uses weapon tier information to provide visual feedback for upgraded weapons.
classDiagram
class WeaponStats {
<<interface>>
+getProjectileCount()
}
class WeaponTier {
<<enumeration>>
TIER_1
TIER_2
TIER_3
}
class WeaponItem {
-WeaponStats weaponStats
+getProjectileCount()
}
class WeaponUpgrader {
+upgradeWeapon()
}
WeaponTier ..|> WeaponStats : provides tier stats
WeaponItem --> WeaponStats : uses
WeaponUpgrader --> WeaponItem : upgrades
flowchart LR
A[Weapon Item] --> B[Current Tier]
B --> C{Maximum Tier?}
C -->|No| D[WeaponUpgrader]
D --> E[Next Tier]
E --> F[Updated Weapon Stats]
F --> G[Combat]
F --> H[Inventory / HUD]
F --> I[Rendering]
C -->|Yes| J[Keep Current Tier]
Testing covered:
- Dagger damage, attack speed, knockback and range scaling across tiers.
- Tier 1, Tier 2 and Tier 3 weapon progression.
- Bow projectile-count scaling of 1 → 5 → 10.
- Sword, bow and dagger upgrade paths.
- Maximum-tier upgrade rejection.
- Null-input handling for weapon upgrades.
- Dagger-to-sword transformation.
- Bow damage balancing through in-game playtesting.
- Weapon HUD updates when switching between sword, bow and dagger.
- Compatibility and integration testing with combat, loot, inventory and rendering.
- Regression testing after Sprint 3 integration.
Relevant automated testing included:
-
WeaponTierTestfor tier statistics and projectile-count scaling. -
WeaponItemTestfor weapon item behaviour. -
WeaponUpgraderTestfor weapon upgrade progression, upgrade paths, maximum-tier rejection and null-input handling.
Manual gameplay testing was also performed to verify weapon switching/HUD updates, bow damage balancing, projectile progression and dagger-to-sword upgrade behaviour.
The resulting system provides Tier 1–3 weapon progression where upgrades can affect statistics, projectile count and weapon form while keeping tier and upgrade information centralised for use across the game's weapon systems.
For Sprint 3, my main contributions focused on two areas:
- Story and Cutscene System
- Weapon Rendering, Visuals and Animations
The Story/Cutscene system provides a reusable framework for presenting narrative sequences and integrating them with the existing gameplay and revival flow.
The Weapon Rendering system displays the player's currently equipped weapon with correct positioning, animations, weapon types and tier-based visual scaling.
The Story/Cutscene system provides a reusable framework for creating and displaying narrative sequences within the game.
The system supports:
- Multiple scenes within a cutscene
- Sequential scene progression
- Scene text and background images
- Player input for progressing through scenes
- Opening story sequences
- After-death story sequences
- Integration with the existing gameplay and revival flow
The core framework was designed so that additional story sequences can be added without changing the overall cutscene architecture.
The opening story is presented before the player enters gameplay.
Main Menu
|
v
Opening Story Cutscene
|
v
Gameplay
The opening sequence introduces the game's narrative before the player begins the main gameplay experience.
The after-death cutscene was integrated into the existing death, loot and revival flow.
Hero Dies
|
v
Loot Drops
|
v
After-Death Cutscene
|
v
Death Screen
|
v
Try Again / Revival
|
v
New Hero
|
v
Gameplay
The after-death cutscene is presented after the player's death and loot-drop process, before the existing revival flow continues.
| Component | Responsibility |
|---|---|
StoryCutscene |
Manages a sequence of story scenes and controls scene progression |
StoryScene |
Represents an individual scene within a cutscene |
StoryCutsceneScreen |
Displays the cutscene as a game screen |
StoryCutsceneInputComponent |
Handles input used to progress through the cutscene |
| Story display components | Present the scene text and visual content |
The framework separates the story content, scene sequencing, screen presentation and input handling. This allows individual scenes to be changed or additional cutscenes to be created without redesigning the entire system.
The opening cutscene consists of multiple narrative scenes that introduce the game's story and transition the player into gameplay.
The opening sequence was implemented using the reusable StoryCutscene and StoryScene framework.
Story/Cutscene Framework
Opening Story Cutscene
The after-death cutscene provides additional narrative progression after the player's character dies.
The sequence contains four narrative stages:
THE FALL
|
v
THE LEGEND
|
v
THE NEXT HERO
|
v
THE JOURNEY CONTINUES
The after-death sequence was implemented as part of the existing death and revival flow rather than replacing the existing death screen or revival functionality.
The weapon rendering system is responsible for displaying the player's currently equipped weapon separately from the main player sprite.
The system supports:
- Sword rendering
- Bow rendering
- Dagger rendering
- Weapon switching
- Correct in-hand positioning
- Player-facing direction
- Weapon attack animations
- Tier-based weapon visuals
- Tier-based visual scaling
- Tier 2 and Tier 3 sword textures
The rendering system focuses on the visual representation of weapons, while gameplay behaviour such as damage, projectile spawning and attack effects remains handled by the combat systems.
Inventory / Equipped Weapon
|
v
WeaponRenderComponent
|
v
Identify Weapon Type
|
v
Identify Tier
|
v
Select Visual Config
|
v
Select Texture
|
v
Position / Scale / Rotation
|
v
Render Weapon
This separates the visual representation of weapons from the underlying combat logic.
| Weapon | Visual Behaviour |
|---|---|
| Sword | Rendered beside the player and visually swings during attacks |
| Bow | Rendered beside the player with a draw and release animation |
| Dagger | Rendered beside the player with a throwing animation |
The renderer updates the displayed weapon according to the currently equipped weapon.
Weapon positioning was adjusted so that equipped weapons appear correctly in the player's hands.
The rendering system accounts for:
- Player-facing direction
- Hand position
- Weapon dimensions
- Weapon-specific offsets
- Weapon rotation during attacks
- Weapon scale
The hand position was refined through manual gameplay testing to ensure that the weapons visually align with the player.
The weapon rendering system supports different visual sizes for different weapon tiers.
For the sword:
| Tier | Texture | Visual Scale |
|---|---|---|
| Tier 1 | sword.png |
1.00x |
| Tier 2 | sword_t2.png |
1.20x |
| Tier 3 | sword_t3.png |
1.45x |
This allows upgraded weapons to have a visually stronger presence in addition to their gameplay upgrades.
Separate sword textures were added for Tier 2 and Tier 3 weapons.
Tier 1
sword.png
Tier 2
sword_t2.png
Tier 3
sword_t3.png
The additional textures were also included in the game's resource loading so that they can be displayed during gameplay.
The renderer determines the appropriate sword texture based on the equipped weapon's tier.
Equipped Sword
|
v
Check Weapon Tier
|
+--+--+
| | |
v v v
T1 T2 T3
| | |
v v v
sword.png sword_t2.png sword_t3.png
| | |
+--+--+
|
v
Apply Tier Scale
|
v
Render Weapon
The tier-based visual scaling is covered by automated tests.
The weapon renderer provides visual animations for the different weapon types.
Sword Idle
|
v
Sword Attack
|
v
Swing Animation
|
v
Sword Idle
The sword visually swings when an attack is performed.
Bow Idle
|
v
Bow Draw
|
v
Bow Release
|
v
Bow Idle
The bow visually draws and releases during the attack.
Dagger Idle
|
v
Dagger Throw
|
v
Dagger Idle
The dagger uses a throwing animation to visually represent its attack.
The animations represent the visual side of the attacks. The actual gameplay behaviour, including damage, projectile spawning and attack effects, is handled by the combat systems.
The Story/Cutscene system integrates with the existing game flow.
Main Menu
|
v
Opening Story Cutscene
|
v
Gameplay
|
v
Death Detection
|
v
Loot Drop
|
v
After-Death Story Cutscene
|
v
Death Screen
|
v
Revival
|
v
Gameplay
The after-death cutscene was added without removing the existing death screen or revival functionality.
The weapon renderer integrates with the player's inventory and equipped weapon state.
Player Inventory
|
v
Equipped Weapon
|
v
WeaponRenderComponent
|
+---+---+
| | |
v v v
Sword Bow Dagger
| | |
+---+---+
|
v
Visual Rendering
|
v
Player
The renderer updates when the equipped weapon changes, allowing the correct weapon to be displayed during gameplay.
The Story/Cutscene system was tested for:
- Correct scene ordering
- Scene progression
- Scene resetting
- Final-scene behaviour
- Empty cutscene handling
- Correct number and ordering of after-death scenes
- Opening cutscene transition into gameplay
- After-death cutscene integration with the death and revival flow
The weapon rendering system was tested for:
- Rendering the equipped weapon
- Stopping rendering after the selected weapon is dropped
- Tier 1 sword texture selection
- Tier 2 sword texture selection
- Tier 3 sword texture selection
- Correct tier-based visual scaling
- Weapon switching
- Weapon positioning
- Attack animations
- Resource loading for Tier 2 and Tier 3 sword textures
Manual gameplay testing was performed to verify:
- Opening cutscene presentation
- Transition from the opening cutscene into gameplay
- Player death behaviour
- Loot dropping before the after-death cutscene
- After-death cutscene presentation
- Revival after the cutscene
- Sword, bow and dagger rendering
- Weapon switching
- Weapon positioning relative to the player
- Tier 2 and Tier 3 sword visuals
- Weapon attack animations
- Integration with the Sprint 3 combat systems
MainGameScreen
|
v
StoryCutsceneScreen
|
v
StoryCutscene
|
v
StoryScene
StoryCutsceneInputComponent
|
v
Advances StoryCutscene
The StoryCutscene manages the sequence of scenes, while StoryScene represents the individual narrative elements. The screen and input components provide the presentation and interaction layer.
Player Inventory
|
v
Equipped Weapon
|
v
WeaponRenderComponent
|
+--+--+--+
| | |
v v v
Sword Bow Dagger
| | |
v v v
T1/T2/T3 Draw/Release Throw
| | |
+--+--+
|
v
Visual Rendering
|
v
Player
The Sprint 3 implementation resulted in the following additions:
- Reusable Story/Cutscene framework
- Opening story cutscene
- After-death story cutscene
- Integration of the after-death cutscene with the death and revival flow
- Equipped weapon rendering
- Sword, bow and dagger visual support
- Weapon switching visuals
- Correct in-hand weapon positioning
- Sword attack animation
- Bow draw animation
- Dagger throw animation
- Tier-based weapon visual scaling
- Tier 2 and Tier 3 sword textures
- Automated tests for story and weapon rendering functionality
- Manual integration testing across the Sprint 3 systems
Overall, the implementation separates narrative presentation, weapon visualisation and gameplay mechanics, allowing these systems to integrate with the existing game architecture without duplicating the underlying gameplay logic.
This feature introduces two new defensive/gameplay mechanics to the player:
Ballistic Shield — a stronger defensive shield that is available as a rare loot and can be activated with B when the player has obtained one. Enemy Bribe — allows the player to bribe an enemy that attacked them, temporarily preventing that enemy from continuing its attack.
Both mechanics were implemented as part of the player's combat and defensive systems and integrated with the game's configurable keybind system.
The Ballistic Shield provides the player with an additional defensive option during combat. Unlike the standard shield, the Ballistic Shield can not only block the incoming damage but also retaliate 25% of the damage back to the enemy.
The mechanic was designed to give the player a strategic defensive option when facing stronger or multiple enemies.
When the player presses the B key:
The game checks whether the player currently has a Shield. If a Ballistic Shield is available, it is activated. If no Ballistic Shield is available, the normal shield is checked instead. The Ballistic Shield activation is handled by the dedicated BallisticShieldComponent.
This allows the same player control to work with both the normal shield and the upgraded Ballistic Shield.
The Ballistic Shield functionality is implemented using a dedicated BallisticShieldComponent.
The Ballistic Shield component provides functionality for determining whether the player has a shield available and activating it when requested.
The implementation also uses the game's event system to trigger shield-related behaviour, keeping the input handling separate from the actual shield mechanics.
A dedicated Ballistic Shield visual asset was created and integrated into the game so that the item can be visually represented during gameplay.
The asset was added alongside the gameplay implementation in:
https://github.com/UQcsse3200/2026-studio-1/commit/fea54660
The Enemy Bribe mechanic provides an alternative to directly fighting an enemy. After an enemy attacks the player, the player can use the bribe action to temporarily stop that enemy from attacking.
This introduces another strategic option into combat, allowing the player to avoid or delay an encounter rather than relying entirely on attacking or shielding.
When the player presses the bribe key:
The input system detects the configured bribe key. The player's PlayerActions component attempts to bribe the attacker. The relevant enemy's melee attack component is identified. The enemy enters a bribed state. Its current attack/wind-up is cancelled. The enemy remains bribed for a fixed duration. After the duration expires, the enemy can return to its normal behaviour.
The bribe duration is currently 20 seconds.
The bribe functionality is connected through the player action system.
The input flow is:
Bribe Key → PlayerActions.bribeLastAttacker() → Enemy Bribe → MeleeAttackComponent.bribe()
The MeleeAttackComponent maintains the bribed state and the time at which the bribe expires.
When an enemy is bribed:
bribed is set to true. A 20-second expiration time is calculated. Any pending attack target is cleared. The current attack wind-up is cancelled. An enemyBribed event is triggered.
This keeps the temporary state within the enemy's melee attack component rather than placing enemy-specific combat logic inside the keyboard input component.
Both mechanics were integrated with the game's configurable keybind system.
The implementation uses KeybindSettings rather than hard-coding the controls directly into the gameplay logic. This allows the controls to remain compatible with the game's keybind configuration system.
The shield keybind was also added to the settings display so that the player can see the assigned control.
Keybind display commit: https://github.com/UQcsse3200/2026-studio-1/commit/63167f79
The Ballistic Shield was integrated into the existing shield control rather than introducing another key specifically for the Ballistic Shield.
This makes the control scheme simpler for the player:
B = Shield
The game determines which shield behaviour should be used based on whether a Ballistic Shield is available.
The bribe effect is intentionally temporary rather than permanently changing an enemy's behaviour.
A fixed duration of 20 seconds was selected so that the mechanic provides meaningful breathing room without permanently removing an enemy from combat.
The implementation separates input, player actions, and enemy behaviour:
Keyboard Input → detects the player's key press
PlayerActions → performs the requested player action
MeleeAttackComponent → manages the enemy's bribed state and attack behaviour
This prevents the keyboard input component from containing enemy-specific gameplay logic.
Player presses B ↓ KeyboardPlayerInputComponent ↓ Check for Ballistic Shield ↓ BallisticShieldComponent ↓ Activate Ballistic Shield
If no Ballistic Shield is available:
Player presses B ↓ Check for Ballistic Shield ↓ No Ballistic Shield ↓ Activate normal Shield
Player presses R ↓ KeyboardPlayerInputComponent ↓ PlayerActions.bribeLastAttacker() ↓ Identify last attacking enemy ↓ MeleeAttackComponent.bribe() ↓ Enemy enters bribed state ↓ 20-second duration ↓ Enemy can return to normal behaviour
The main implementation of both mechanics is contained in the following commit:
https://github.com/UQcsse3200/2026-studio-1/commit/fea54660
Commit: fea54660 — Add ballistic shield and enemy bribe mechanics
The commit includes the implementation of the Ballistic Shield and Enemy Bribe gameplay functionality as well as the associated Ballistic Shield asset.
The mechanics were tested during gameplay to verify that:
The shield key correctly activates the Ballistic Shield when one is available. The normal shield remains available when the player does not have a Ballistic Shield. The Ballistic Shield can be activated through the player input system. The shield behaviour integrates correctly with the existing combat system. The Ballistic Shield visual asset appears correctly in-game.
The bribe key correctly triggers the bribe action. The correct attacking enemy is identified. The enemy enters the bribed state. The enemy's current attack is interrupted. The bribe lasts for the intended 20-second duration. The enemy can resume normal behaviour after the bribe expires.