Animal Attack System - UQcsse3200/2024-studio-1 GitHub Wiki
Overview
Animal attacks are a core component of enemy behaviour in the game, providing unique challenges to players. Each animal can perform specific attacks, defined by their range, rate, and effects. The attack system is designed to be highly configurable, allowing for varied combat encounters that are tailored to each animal type.
Attack Components
Animal attacks are managed through AttackComponent classes, which handle the logic for executing attacks when certain conditions are met (e.g., proximity to the player). The architecture includes:
- AttackBehaviour Interface: Defines the key methods
performAttack
,applyEffects
, andcanAttack
, ensuring consistency across different attack types. - AttackComponent (Abstract Class): Implements
AttackBehaviour
and extendsComponent
. It provides the base functionality for attacks, including cooldown management and effect application. - MeleeAttackComponent: Extends
AttackComponent
and handles close-range attacks. This component triggers when the animal is within a specified attack range of the target (usually the player). Is activated withinChaseTask
andChargeTask
. - RangeAttackComponent: Extends
AttackComponent
, handling ranged attacks. This component also triggers when the target is within a specified range. It takes an extra parameter for the type of ranged attack - single shot or spread shot. Is activated withinRangeAttackTask
. - BossRangeAttackComponent: A component for certain boss entities only that allows a boss to unload a barrage of projectiles. Is activated in the
BulletStormTask
. - AOEAttackComponent: Extends
AttackComponent
, managing Area of Effect attacks. This component introduces a preparation phase before the actual attack, allowing for visual cues or strategic positioning. It defines an AOE radius and can affect multiple targets within that area. The component supports both instant AOE attacks and delayed attacks with a preparation time. Is activated withinJumpTask
andAOEAttackTask
.
Effects
Attack effects are additional actions triggered by attacks, including knockback, poison, or stun. These effects can be applied to the target to enhance the complexity and strategy of combat.
For detailed information about effects, refer to the Attack Effects page.
Configuration
Animal attacks are configured in the NPCs.json
file, where parameters for each animal's attack component can be changed. Example configuration for a dragon is shown below. Further explanation can be found within NPC Configuration.
"dragon": {
"attacks": {
"melee": {
"range": 1,
"rate": 0.5,
"effects": [
{
"type": "knockback",
"force": 2
}
]
},
"ranged": {
"range": 10,
"rate": 2,
"type": 0,
"effects": [
{
"type": "stun",
"duration": 0.5
}
]
}
},
...
}
This dragon has a melee attack when the target is within a range of 1, and attacks 0.5 times per second, applying knockback on each hit. Its ranged attack shoots at a target within a range of 10, shooting twice per second and applying a stun effect for 0.5 seconds to the target when hit.
Attack Execution
- Initialisation: The attack component(s) are added to the animal entity during its creation in the NPCFactory taking parameters from the configuration file.
- Behaviour Check: During each update cycle, the component checks if the animal can attack (by default this is if the target is in a given range) and whether the cooldown period has passed.
- Performing Attack: If the conditions are met, the component executes the
performAttack
method, with triggers an attack and with any associated effects. Attack animations are also triggered to provide visual feedback to the player. - Cooldown Management: After an attack is performed, the component resets its cooldown timer to prevent immediate subsequent attacks.
Class Diagram
classDiagram
class AttackComponent {
-target: Entity
-attackRange: float
-attackCooldown: float
-timeSinceLastAttack: float
-combatStats: CombatStatsComponent
+performAttack()
+canAttack(attacker: Entity, target: Entity): boolean
+enableForNumAttacks(numberOfAttacks: int)
}
class MeleeAttackComponent {
+performAttack()
}
class RangeAttackComponent {
-projectileNames: String[]
+performAttack()
+shoot(direction: Vector2)
}
class AOEAttackComponent {
-origin: Vector2
+performAttack()
}
AttackComponent <|-- MeleeAttackComponent
AttackComponent <|-- RangeAttackComponent
AttackComponent <|-- AOEAttackComponent
Sequence Diagram
Part 1: Update and Attack Check
sequenceDiagram
participant Game Loop
participant AttackComponent
Game Loop->>AttackComponent: update()
AttackComponent->>AttackComponent: canAttack(entity, target)
alt Can Attack
AttackComponent->>AttackComponent: performAttack()
end
Part 2: Melee Attack Execution
sequenceDiagram
participant MeleeAttackComponent
participant TargetEntity
participant EffectComponent
MeleeAttackComponent->>TargetEntity: hit(damage)
MeleeAttackComponent->>EffectComponent: addEffect(effect)
MeleeAttackComponent->>MeleeAttackComponent: resetCooldown()
Part 3: Range Attack Execution
sequenceDiagram
participant RangeAttackComponent
participant ProjectileFactory
participant GameArea
RangeAttackComponent->>ProjectileFactory: create(projectile)
ProjectileFactory-->>RangeAttackComponent: projectile
RangeAttackComponent->>GameArea: spawnEntityAt(projectile, position)
RangeAttackComponent->>RangeAttackComponent: resetCooldown()
Part 4: Boss Range Attack (Bullet Storm) Execution
sequenceDiagram
participant BossRangeAttackComponent
participant ProjectileFactory
participant GameArea
BossRangeAttackComponent->>ProjectileFactory: create(projectile)
ProjectileFactory-->>BossRangeAttackComponent: projectile
BossRangeAttackComponent->>GameArea: spawnEntityAt(projectile, position)
BossRangeAttackComponent->>BossRangeAttackComponent: resetCooldown()
Part 5: AOE Attack Execution
sequenceDiagram
participant AOEAttackComponent
participant TargetEntity
participant EffectComponent
AOEAttackComponent->>AOEAttackComponent: executeAOEAttack()
AOEAttackComponent->>TargetEntity: hit(damage)
AOEAttackComponent->>EffectComponent: addEffect(effect)
AOEAttackComponent->>AOEAttackComponent: resetCooldown()