Repository navigation
Weapons
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.
What exists in the codebase today:
- Shared stats:
WeaponStatsComponent(cooldown, damage, knockback). Cooldown is a countdown in seconds (update(dt);dtis time since last frame). - Shared behaviour: abstract
WeaponComponent.attack(origin, direction)is final — it refuses to fire while cooling down, then callscreateAttack(...). - Shared spawn:
HitboxFactory+HitboxSpecbuilds a kinematic sensor onPhysicsLayer.WEAPONthat damagesPhysicsLayer.NPCusing existingTouchAttackComponent/CombatStatsComponent. - Melee movement: if the spec has an
owner,FollowComponentsetsposition = owner.position + localOffseteach frame.setLocalOffsetis there so a sword can move the offset through an arc. - Lifetime:
LifetimeComponentdisposes 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 callsweapon.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.
When the feature is complete, attacking should feel like this:
- The player faces or aims a direction and presses attack.
- 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.
- Anything on the NPC layer that overlaps the sensor takes that weapon’s damage (and knockback if configured).
- 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.
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.
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).
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());- Hitbox layer is
PhysicsLayer.WEAPON. Target layer isPhysicsLayer.NPC. Do not put weapon sensors onPLAYER— 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.
Work that belongs on this feature, not yet in main:
- Knife, sword, and bow
WeaponComponentsubclasses (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.