CombatInventoryDisplay - UQcsse3200/2024-studio-2 GitHub Wiki

Overview

The CombatInventoryDisplay class is a specialized component of the UI entity in the CombatScreen class. It extends the abstract InventoryDisplay class and provides a way to represent the player's inventory in a combat scenario, allowing items to be used during battles.

Key Features

  1. No Hotbar: Unlike the main game inventory, CombatInventoryDisplay does not include a hotbar for combat logistics and UI simplification.
  2. Combat-Specific Item Usage: The useItem function in CombatInventoryDisplay triggers an "itemClicked" event, allowing combat-related classes to handle item usage as a combat move.
  3. Turn-Based Item Usage: Only one item can be used per turn, maintaining combat balance and sequencing.

Usage

To toggle the inventory display during combat, click the "Items" button in the CombatButtonDisplay.

Differences to InventoryDisplay

The CombatInventoryClass differs to its parent InventoryDisplay class in the following ways:

  • No Hotbar - the CombatInventoryClass does not have a hotbar for combat logistic and UI purposes.
  • Item Usage - a major difference of the CombatInventoryClass to its parent is the logic of the useItem function. When useItem is called in an instance of CombatInventoryClass, an "itemClicked" event is triggered. This allows the CombatActions and CombatManager classes to handle item usage as if it was a combat move, limiting one item to be used per turn and any relevant sequencing to occur properly.

Display

Screenshot 2024-10-02 at 10 05 52 pm

Class Diagram

classDiagram
    class InventoryDisplay {
        <<abstract>>
        #inventory: Inventory
        #numCols: int
        #hotBarCapacity: int
        +create()
        +toggleMsg(): String
        #enterSlot(item: AbstractItem)
        #exitSlot(item: AbstractItem)
        #useItem(item: AbstractItem, index: int)
    }
    class CombatInventoryDisplay {
        -inventory: Inventory
        -numCols: int
        -hotBarCapacity: int
        +CombatInventoryDisplay(inventory: Inventory, numCols: int, hotBarCapacity: int)
        +create()
        +toggleMsg(): String
        #enterSlot(item: AbstractItem)
        #exitSlot(item: AbstractItem)
        #useItem(item: AbstractItem, index: int)
        -useItemInCombat(item: AbstractItem, context: ItemUsageContext, index: int)
    }
    InventoryDisplay <|-- CombatInventoryDisplay

Loading

Implementation Details

Constructor

public CombatInventoryDisplay(Inventory inventory, int numCols, int hotBarCapacity) {
    super(inventory, numCols, hotBarCapacity, false);
}

The constructor initializes the CombatInventoryDisplay with the player's inventory, number of columns, and hotbar capacity (which is not used in combat).

Key Methods

  1. create()
@Override
public void create() {
    super.create();
    entity.getEvents().addListener("itemUsedInCombat", this::useItemInCombat);
}

This method sets up the display and adds a listener for the "itemUsedInCombat" event.

  1. useItem()
@Override
protected void useItem(AbstractItem item, int index) {
    ItemUsageContext context = new ItemUsageContext(entity);
    if (!item.onlyMapItem()) {
        entity.getEvents().trigger("itemClicked", item, index, context);
    } else {
        String[][] itemText = {{"This item can only be used on the map!"}};
        ServiceLocator.getDialogueBoxService().updateText(itemText, DialogueBoxService.DialoguePriority.BATTLE);
    }
}

This method handles item usage in combat, triggering the "itemClicked" event for combat-usable items or displaying a message for map-only items.

  1. useItemInCombat()
private void useItemInCombat(AbstractItem item, ItemUsageContext context, int index) {
    super.consumeItem(item, context, index);
}

This private method is called when an item is used in combat, consuming the item from the inventory.

Sequence Diagram

sequenceDiagram
    participant User
    participant CombatButtonDisplay
    participant CombatInventoryDisplay
    participant CombatActions
    participant CombatManager

    User->>CombatButtonDisplay: Click "Items" button
    CombatButtonDisplay->>CombatInventoryDisplay: Toggle inventory
    User->>CombatInventoryDisplay: Click on item
    CombatInventoryDisplay->>CombatInventoryDisplay: useItem(item, index)
    CombatInventoryDisplay->>CombatActions: Trigger "itemClicked" event
    CombatActions->>CombatManager: Handle item usage
    CombatManager->>CombatInventoryDisplay: Trigger "itemUsedInCombat" event
    CombatInventoryDisplay->>CombatInventoryDisplay: useItemInCombat(item, context, index)
    CombatInventoryDisplay->>CombatInventoryDisplay: consumeItem(item, context, index)

Loading

The sequence diagram above illustrates the flow of actions when a user uses an item in combat:

  1. The user clicks the "Items" button in the CombatButtonDisplay.
  2. The inventory is toggled, showing the available items.
  3. The user clicks on an item in the CombatInventoryDisplay.
  4. The useItem method is called, which triggers the "itemClicked" event.
  5. CombatActions handles the item usage and notifies the CombatManager.
  6. The CombatManager triggers the "itemUsedInCombat" event.
  7. The useItemInCombat method is called, which consumes the item from the inventory.

Testing

Here's an example of how to test the CombatInventoryDisplay class:

@ExtendWith(GameExtension.class)
class CombatInventoryDisplayTest {
    @BeforeEach
    void beforeEach() {
        // Set up necessary services
        ResourceService resourceService = new ResourceService();
        RenderService renderService = mock(RenderService.class);
        when(renderService.getStage()).thenReturn(mock(Stage.class));
        InputService inputService = new InputService();

        ServiceLocator.registerResourceService(resourceService);
        ServiceLocator.registerRenderService(renderService);
        ServiceLocator.registerInputService(inputService);

        resourceService.loadAll();
        Gdx.input.setInputProcessor(renderService.getStage());
    }

    @Test
    void testInitialisation() {
        // Test invalid initializations
        Inventory inv1 = new Inventory(9);
        Inventory inv2 = new Inventory(10);
        assertThrows(IllegalArgumentException.class,
                () -> new CombatInventoryDisplay(inv1, 7, 1));
        assertThrows(IllegalArgumentException.class, 
                () -> new CombatInventoryDisplay(inv2, 0, 1));

        // Test valid initialization
        new CombatInventoryDisplay(new Inventory(9), 3, 3);
    }

    // Add more tests for other methods
}

This test class demonstrates how to set up the necessary services and test the initialization of the CombatInventoryDisplay. You should add more tests to cover other methods and scenarios.

⚠️ **GitHub.com Fallback** ⚠️