Skip to content

Consumables

Jeremyzihanwu edited this page Oct 18, 2026 · 2 revisions

Overview

Consumables restore health, provide temporary protection or stat boosts, affect enemies, and attract nearby items. Each successful use removes one item from the player's inventory.

Items are identified through ItemCatalog. The inventory stores their quantities and four consumable-slot assignments, while the selection and effect components handle choosing and using them.

Usage

  1. Collect a nearby ground item with E, or buy supplies from the Merchant.
  2. Press I to open the inventory book. On its Consumables page, select an item and press Space to equip or unequip it.
  3. Close the book with I or Escape.
  4. Press Tab to select a consumable slot, then Q to use its item.
Context Control Action
Gameplay E Request pickup of a nearby item. NPC interaction takes priority.
Gameplay I Open the inventory book.
Gameplay Tab Cycle through all four consumable slots, including empty slots.
Gameplay Q Use the item in the selected slot; an empty slot does nothing.
Inventory book Q / E Change book page.
Inventory book WASD / arrows, then Space Select an item, then equip or unequip it.
Inventory book I / Escape Close the book.

The four slots hold assignable item types. Picking up a newly owned consumable type fills the first empty slot when one is available. Additional types remain in the backpack. Shop purchases and Item Draw rewards add stock without automatically assigning a slot; equip a newly purchased type through the book.

Using the last copy clears that item's slot. Selection remains on the same slot until the player cycles again. Unequipping an item keeps its inventory quantity. See Inventory UI (Team Five) for book equipment controls and Consumable Slots for the four-slot display and selection behaviour.

Consumable effects

These are the nine built-in consumables and their default effects:

Item Catalog ID Default effect
Small Health Potion HEALTH_POTION Immediately restores up to 25 HP, capped at maximum health.
Medium Health Potion MEDIUM_HEALTH_POTION Immediately restores up to 50 HP, capped at maximum health.
Large Health Potion LARGE_HEALTH_POTION Immediately restores up to 100 HP, capped at maximum health.
Shield SHIELD Blocks damage routed through the status-effect system for 8 seconds.
Speed Potion SPEED_POTION Applies a 1.5× movement-speed multiplier for 8 seconds.
Strength Potion STRENGTH_POTION Applies a 1.5× attack multiplier for 8 seconds.
Freeze Bomb FREEZE_BOMB Freezes eligible enemies currently on screen for 3 seconds.
Burn Vial BURN_VIAL Burns eligible enemies currently on screen: 2 damage per tick, a 1-second tick cooldown, and a 6-second duration.
Magnet Potion MAGNET_POTION Pulls nearby Gold and consumables for 10 seconds, within a 4-world-unit radius.

Healing at full health is rejected without consuming the potion. Reusing Shield, Speed, Strength or Magnet replaces that item's previous player effect with a fresh duration. Repeated uses of the same potion do not compound its multiplier or add the old remaining duration.

Freeze and Burn select targets when used. A valid use consumes one item even if no eligible enemy is on screen. Each use applies independent effects to its targets; those effects are managed by the enemies' status controllers rather than the player's potion-refresh map. Burn timing follows the shared Burning update loop, so the configured cooldown and duration do not guarantee a fixed total number of damage ticks.

Using a consumable

ConsumableSelectionComponent tracks the selected slot. ConsumableEffectComponent owns validation, inventory consumption and effect application.

Usage

An existing player can receive a use request through its event handler:

player.getEvents().trigger(
    ConsumableEffectComponent.USE_REQUEST, ItemIds.SPEED_POTION);

Code that needs the result can call boolean tryUse(String id) on the player's ConsumableEffectComponent. Both routes use the same validation and consumption path. Callers should submit the request without removing stock first.

How it works internally

  1. Check that the effect component is active, the item ID is valid, and the player is alive and owns the item.
  2. Create one concrete item through ItemCatalog.create(id, 1) and check that it is a ConsumableItem.
  3. Call the item's canUse(stats, effects, time) to validate its specific requirements.
  4. Remove exactly one unit through InventoryComponent.removeConsumable(id).
  5. Apply the item with use(stats, time). If it returns a player timed effect, replace the previous effect for that item ID and register the new one with the status controller.
  6. Emit itemUsed with the item ID.

Invalid IDs, unavailable stock, dead or disposed players, and rejected item-specific checks leave the inventory unchanged. The base consumable check requires a live status controller and a time source. Instant healing has its own health check; Freeze and Burn additionally need the world camera and entity service, while Magnet needs the entity service.

Events

These events use the player entity's event handler:

Event Parameters Purpose
cycleConsumable None Advance the selected consumable-slot index.
selectedConsumableChanged String itemId Notify observers of the selected type; the ID can be null for an empty slot.
useSelectedConsumable None Resolve the selected slot and request use of its item.
useConsumable String itemId Request validation and use through ConsumableEffectComponent.
consumableInventoryChanged String itemId, Integer count Notify observers of the final inventory count.
itemUsed String itemId Notify observers after successful effect application.

itemUsed is a notification. Its listeners must not consume another item or initiate the same use again.

Effect implementation

ConsumableItem defines the shared item contract:

Method Responsibility
boolean canUse(CombatStatsComponent stats, StatusEffectsControllerComponent effects, GameTime time) Check whether the item can be used in the current state.
TimedStatusEffect use(CombatStatsComponent stats, GameTime time) Apply the effect and return a player timed effect, or null when application is immediate or targets enemies.
void pickUp(Entity player) Add the item's quantity to the player's inventory through addConsumable.

Healing and player effects

InstantHealingPotion applies capped healing immediately. The catalog registers its small, medium and large variants. It also supports positive custom healing amounts through derived IDs such as HEALTH_POTION_40; these custom IDs are accepted by the catalog but are not included in its built-in ID list.

ShieldPotion returns the shared Shield timed effect. Its damage handler sets intercepted damage to zero. Protection relies on the normal combat/status-effect damage path.

Speed and Strength extend StatBoostPotion, which returns a timed stat multiplier. The shared controller combines active multipliers, and combat stats calculate their effective values from those multipliers. The potions do not permanently overwrite the player's base stats.

Enemy effects

Freeze and Burn use StrategyOnscreen to find enemies whose centres lie inside the world camera's viewport bounds. This targeting does not perform a distance-radius or line-of-sight check.

Freeze adds the shared FrozenEffect to eligible enemy status controllers, immobilising the enemy and applying zero multipliers to its effective stats for the duration. Burn adds VialBurning, which extends the existing Burning effect and provides feedback when a burn tick actually reduces health.

Magnet collection

MagnetPotion returns MagnetEffect. During updates, it scans registered ground-item entities and pulls currency and consumables towards the player at 6 world units per second. Charms are excluded.

Items are collected within 0.4 world units, or when the current movement step would reach them. Collection calls the item's normal pickUp(player) method and schedules the ground entity for disposal after the update loop.

Duration and cleanup

TimedStatusEffect records an expiry deadline using GameTime.getTime(). The status controller updates and removes completed effects. Player death clears the controller's effects, and disposing the consumable component removes its tracked player effects.

Pausing world updates does not pause this elapsed-time clock. Remaining potion duration can therefore decrease while the inventory or shop is open; expired effects are cleaned up when controller updates resume.

The effect component exposes long getRemainingMs(String id) and float getRemainingFraction(String id) for the actual tracked player effect. The fraction is between zero and one. isShielded() and getShieldRemainingMs() provide shield-specific queries.

HUD and feedback

The Consumable Slots display shows four equipped positions along the bottom of the screen, with item icons, quantities, selection and Tab / Q hints. Its Speed Potion ring reads the actual remaining fraction from ConsumableEffectComponent; the ring is shown only while that type remains assigned to a slot.

PlayerFactory attaches the following feedback components:

Component Feedback
HealingPotionFeedbackComponent An expanding pulse, rising crosses and the actual amount of HP restored.
ShieldPotionFeedbackComponent A barrier around the player while the consumable shield is active.
SpeedPotionAfterimageComponent Afterimages while the player moves with an active Speed Potion.
BurnVialFeedbackComponent Animated flames tracking enemies affected by the vial's burn.

Freeze and Burn also request white and fire screen flashes through the render service. These visual components display the results of item use; inventory consumption and gameplay effects remain in their owning components.

Testing

The consumable implementation and its integration with inventory and UI include the following test classes:

  • ItemCatalogTest
  • ConsumableItemTest
  • ConsumableUseIntegrationTest
  • ConsumableSelectionComponentTest
  • FreezeBombUseTest
  • BurnVialUseIntegrationTest
  • MagnetUseIntegrationTest
  • InventoryComponentTest
  • ConsumableHotbarDisplayTest
  • SpeedPotionTimerRingTest
  • HealingPotionFeedbackComponentTest
  • ShieldPotionFeedbackComponentTest
  • SpeedPotionAfterimageComponentTest
  • BurnVialFeedbackComponentTest
  • ConsumableRoomAssetsIntegrationTest

Source and related documentation

Table of Contents

Home

Test Plan

Team 2

Features

Components
Player
Items and Inventory
Enemies
Interactable NPCs
Cutscenes and Dialogue
Music
Bosses
Rooms
Weapons
Abilities & Spells
Game Screens and Areas
Dungeons

Game Engine

Getting Started

Entities and Components

Service Locator

Loading Resources

Logging

Unit Testing

Debug Terminal

Input Handling

UI

Animations

Audio

AI

Physics

Terrain

Concurrency & Threading

Settings

Troubleshooting

MacOS Setup Guide

Clone this wiki locally