Skip to content

Weapons

chaubenn edited this page Sep 3, 2026 · 3 revisions

Weapons are how the player (and later other combatants) deal directed damage: a short-lived hit sensor in the world, not the NPC “touch the player” contact damage already in the engine.

The feature is meant to cover three player weapons with different hit shapes, all sharing one cooldown/stats and spawn path:

Weapon Hit shape Moves with the wielder?
Knife Small fixed area in front of the wielder Yes
Sword Sweeping arc around the wielder over the swing Yes
Bow Splash at the aim point No — stays where it was aimed

Players should be able to attack while walking. Melee hitboxes stay glued to the wielder; a bow splash stays in world space.

API reference: studio JavaDoc after merge to main (com.csse3200.game.components.weapons, HitboxFactory). That is this studio’s Pages site, not the engine JavaDoc.

Current state

What exists in the codebase today:

  • Shared stats: WeaponStatsComponent (cooldown, damage, knockback). Cooldown is a countdown in seconds (update(dt); dt is time since last frame).
  • Shared behaviour: abstract WeaponComponent. attack(origin, direction) is final — it refuses to fire while cooling down, then calls createAttack(...).
  • Shared spawn: HitboxFactory + HitboxSpec builds a kinematic sensor on PhysicsLayer.WEAPON that damages PhysicsLayer.NPC using existing TouchAttackComponent / CombatStatsComponent.
  • Melee movement: if the spec has an owner, FollowComponent sets position = owner.position + localOffset each frame. setLocalOffset is there so a sword can move the offset through an arc.
  • Lifetime: LifetimeComponent disposes the hitbox entity when its time is up.

What is not in the game yet:

  • Knife, sword, and bow subclasses (no distinct shapes in play).
  • Player Space still only plays a sound (PlayerActions.attack). Nothing calls weapon.attack(...).
  • No weapon inventory, switching, or aiming UI.
  • No weapon sprites or JSON configs.

Combat you can see in a level is still NPC-on-player contact damage only.

Intended player experience

When the feature is complete, attacking should feel like this:

  1. The player faces or aims a direction and presses attack.
  2. If the equipped weapon is off cooldown, a hitbox appears:
    • Knife — a small box just in front of the player, moving with them if they walk.
    • Sword — a larger volume that sweeps around the player during the swing, also moving with them.
    • Bow — a splash at the aimed point, which does not slide with the player.
  3. Anything on the NPC layer that overlaps the sensor takes that weapon’s damage (and knockback if configured).
  4. The hitbox disappears after a short lifetime; the weapon waits out its cooldown before the next attack.

One weapon at a time on the wielder (WeaponStatsComponent + one WeaponComponent subclass). Switching weapons later is swapping those components or their stats, not a second combat pipeline.

How an attack is built

attack(origin, direction)
  → cooldown allows it?
  → createAttack(...)           // knife / sword / bow only implement this
  → HitboxFactory.createHitbox
  → EntityService.register
  → sensor damages NPC on overlap
  → LifetimeComponent despawns
  → melee: FollowComponent tracks the wielder

Wielder must have both WeaponStatsComponent and the weapon subclass. Missing stats fail in create().

Callers register the hitbox themselves (same pattern as PlayerFactory / NPCFactory). The factory does not register.

Melee (knife / sword)

Pass the wielder as owner so the sensor follows movement:

new HitboxSpec()
    .position(origin)
    .size(new Vector2(0.4f, 0.8f))
    .lifetime(0.15f)
    .layer(PhysicsLayer.WEAPON)
    .targetLayer(PhysicsLayer.NPC)
    .damage(stats.getDamage())
    .knockback(stats.getKnockback())
    .owner(wielder)
    .localOffset(offset);
Entity hitbox = HitboxFactory.createHitbox(spec);
ServiceLocator.getEntityService().register(hitbox);

Knife: keep localOffset fixed in the facing direction.
Sword: change localOffset over the swing (FollowComponent.setLocalOffset).

Bow

Omit owner so the splash stays at the aim point:

new HitboxSpec()
    .position(aimPoint)
    .size(new Vector2(0.8f, 0.8f))
    .lifetime(0.2f)
    .layer(PhysicsLayer.WEAPON)
    .targetLayer(PhysicsLayer.NPC)
    .damage(stats.getDamage());

Conventions

  • Hitbox layer is PhysicsLayer.WEAPON. Target layer is PhysicsLayer.NPC. Do not put weapon sensors on PLAYER — NPC touch-attacks that target the player would treat the slash as the player’s body.
  • Do not bypass WeaponComponent.attack() with a second cooldown.
  • The attack sensor is a separate entity. The player already has HitboxComponent / ColliderComponent; the engine allows only one of each class per entity.
  • Damage goes through the existing combat components, not a new health system.

Still to implement

Work that belongs on this feature, not yet in main:

  • Knife, sword, and bow WeaponComponent subclasses (shapes in the table above).
  • Player "attack" → facing or aim vector → weapon.attack(origin, direction), and attaching stats + a weapon on the player.
  • Optional later: inventory/switching, sprites, tuning via JSON, enemy weapons reusing the same base.

Package for subclasses: com.csse3200.game.components.weapons.

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